JPEGs from cameras are often wider than they are high, with metadata that specifies the true orientation. But software often ignores this metadata, so viewers don't display or process as we would hope. This script normalises orientations.
References:
rem Remove any versions from previous builds of this page. del or_*.jpg for /L %%n in (1,1,8) do ( set FILENAME=or_%%n.jpg %IMG7%magick -size 100x200 xc: ^ -sparse-color barycentric 0,0,#f88,%%[fx:h-1],%%[fx:h-1],#8f8 ^ -pointsize 50 -gravity Center -annotate 0 "a%%nb" ^ !FILENAME! ) %IMG7%magick or_2.jpg -flop or_2.jpg %IMG7%magick or_3.jpg -rotate 180 or_3.jpg %IMG7%magick or_4.jpg -flip or_4.jpg %IMG7%magick or_5.jpg -flop -rotate -90 or_5.jpg %IMG7%magick or_6.jpg -rotate -90 or_6.jpg %IMG7%magick or_7.jpg -flop -rotate 90 or_7.jpg %IMG7%magick or_8.jpg -rotate 90 or_8.jpg for /L %%n in (1,1,8) do ( set FILENAME=or_%%n.jpg exiftool -n -Orientation=%%n !FILENAME! del or_*.jpg_original )
We can list the dimensions:
%IMG7%magick identify -format "%%f %%wx%%h\n" or_?.jpg
or_1.jpg 100x200 or_2.jpg 100x200 or_3.jpg 100x200 or_4.jpg 100x200 or_5.jpg 200x100 or_6.jpg 200x100 or_7.jpg 200x100 or_8.jpg 200x100
This is how a web-browser displays the images:
On my computer, both Firefox and MS Internet Explorer show all images (except the first) incorrectly. These browsers ignore the orientation metadata.
ImageMagick can easily re-orient the images.
for /L %%n in (1,1,8) do ( %IMG7%magick or_%%n.jpg -auto-orient or_ao_%%n.jpg )
%IMG7%magick identify -format "%%f %%wx%%h\n" or_ao_?.jpg
or_ao_1.jpg 100x200 or_ao_2.jpg 100x200 or_ao_3.jpg 100x200 or_ao_4.jpg 100x200 or_ao_5.jpg 100x200 or_ao_6.jpg 100x200 or_ao_7.jpg 100x200 or_ao_8.jpg 100x200
ImageMagick's -auto-orient works correctly. However, it re-compresses JPEGs, and this is lossy.
The script orientate.bat finds the orientation with exiftool. It then tries to re-orient the image with jpegtran.
When the image dimensions are an exact multiple of the iMCU size (usually 8 or 16 pixels), jpegtran works fine. Otherwise, jpegtran will either put pixels in the wrong place or trim them off. I don't like either option.
So I tell jpegtran to make a perfect result. If it doesn't make a perfect result, I fallback to ImageMagick to do the job.
for /L %%n in (1,1,8) do ( copy or_%%n.jpg or_et_%%n.jpg ) call %PICTBAT%orientate or_et_*.jpg
%IMG7%magick identify -format "%%f %%wx%%h\n" or_et_?.jpg
or_et_1.jpg 100x200 or_et_2.jpg 100x200 or_et_3.jpg 100x200 or_et_4.jpg 100x200 or_et_5.jpg 200x100 or_et_6.jpg 200x100 or_et_7.jpg 200x100 or_et_8.jpg 200x100
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
rem From image(s) %1 (eg *.jpg), creates orientated versions. rem exiftool tells us the orientation. rem jpegtran does the work. @rem @rem Updated: @rem 13-August-2022 for IM v7. @rem rem @echo off setlocal enabledelayedexpansion if "%1"=="" goto Bad set JT= rem For each file that needs re-orienting: rem copy it to .\backup rem %JT%jpegtran from .\backup to here rem exiftool copy all the tags from .\backup to here, changing the orientation to 1. rem Note: filenames containing commas might cause problems. set TMPFILE=%TEMP%\orient.jpg exiftool -p "$FileName,$Orientation#" %1>orient.lis type orient.lis rem 1 Horizontal (normal) rem 2 Mirror horizontal rem 3 Rotate 180 rem 4 Mirror vertical rem 5 Mirror horizontal and rotate 270 CW rem 6 Rotate 90 CW rem 7 Mirror horizontal and rotate 90 CW rem 8 Rotate 270 CW rem Note: untested for all values except 1, 6 and 8. if not exist backup md backup for /F "tokens=1,2 delims=," %%a ^ in (orient.lis) ^ do ( set FileName=%%a set /A Orient=%%b if !Orient! gtr 1 ( copy /Y !FileName! backup\ exiftool -n -Orientation=1 backup\!FileName! ) set ERR=0 if !Orient! equ 2 ( echo !FileName! !Orient! flip horizontal %JT%jpegtran -perfect -flip horizontal -outfile !FileName! backup\!FileName! if ERRORLEVEL 1 %IMG7%magick backup\!FileName! -flop !FileName! ) else if !Orient! equ 3 ( echo !FileName! !Orient! rotate 180 %JT%jpegtran -perfect -rotate 180 -outfile !FileName! backup\!FileName! if ERRORLEVEL 1 %IMG7%magick backup\!FileName! -rotate 180 !FileName! ) else if !Orient! equ 4 ( echo !FileName! !Orient! flip vertical %JT%jpegtran -perfect -flip vertical -outfile !FileName! backup\!FileName! if ERRORLEVEL 1 %IMG7%magick backup\!FileName! -flip !FileName! ) else if !Orient! equ 5 ( echo !FileName! !Orient! flip horizontal, rotate 270 %JT%jpegtran -perfect -flip horizontal -outfile %TMPFILE% backup\!FileName! if ERRORLEVEL 1 set ERR=1 if !ERR!==0 ( %JT%jpegtran -perfect -rotate 270 -outfile !FileName! %TMPFILE% if ERRORLEVEL 1 set ERR=1 ) if !ERR!==1 %IMG7%magick backup\!FileName! -rotate 90 -flop !FileName! ) else if !Orient! equ 6 ( echo !FileName! !Orient! rotate 90 %JT%jpegtran -perfect -rotate 90 -outfile !FileName! backup\!FileName! if ERRORLEVEL 1 %IMG7%magick backup\!FileName! -rotate 90 !FileName! ) else if !Orient! equ 7 ( echo !FileName! !Orient! flip horizontal, rotate 90 %JT%jpegtran -perfect -flip horizontal -outfile %TMPFILE% backup\!FileName! if ERRORLEVEL 1 set ERR=1 if !ERR!==0 ( %JT%jpegtran -perfect -rotate 90 -outfile !FileName! %TMPFILE% if ERRORLEVEL 1 set ERR=1 ) if !ERR!==1 %IMG7%magick backup\!FileName! -rotate -90 -flop !FileName! ) else if !Orient! equ 8 ( echo !FileName! !Orient! rotate 270 %JT%jpegtran -perfect -rotate 270 -outfile !FileName! backup\!FileName! if ERRORLEVEL 1 %IMG7%magick backup\!FileName! -rotate -90 !FileName! ) if !Orient! gtr 1 ( exiftool -tagsFromFile backup\!FileName! -n -Orientation=1 !FileName! del !FileName!_original ) ) if exist backup\*.jp* ( echo Original files are in .\backup ) else ( echo Removing possibly empty backup directory. rd backup ) goto :end :Bad echo Call with %%1=filename echo %%1 can contain wilcards, eg *.jpg :end endlocal @echo on
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org Copyright: (C) 1999 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI OpenCL Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib Compiler: Visual Studio 2022 (193231332)
Source file for this web page is orient.h1. To re-create this web page, execute "procH1 orient".
This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.
Anyone is permitted to re-publish this page, but only for non-commercial use.
Anyone is permitted to link to this page, including for commercial use.
Page version v1.0 30-Dec-2014.
Page created 14-Aug-2022 18:42:56.
Copyright © 2022 Alan Gibson.