jpegexiforient does not reliably detect EXIF orientation

Bug #1842116 reported by Guy Paddock
10
This bug affects 1 person
Affects Status Importance Assigned to Milestone
libjpeg9 (Ubuntu)
New
Undecided
Unassigned

Bug Description

It seems this program isn't operative in Ubuntu 18.04, unless I've overlooked something.

$ md5sum parrots.jpg
1b624b6d36f1c47f17095ae3dd336a92 parrots.jpg
$ jpegexiforient -2 parrots.jpg
$ echo $?
0
$ md5sum parrots.jpg
1b624b6d36f1c47f17095ae3dd336a92 parrots.jpg
$ jpegexiforient -9 parrots.jpg
jpegexiforient reads or writes the Exif Orientation Tag in a JPEG Exif file.
Usage: jpegexiforient [switches] jpegfile
Switches:
  --help display this help and exit
  --version output version information and exit
  -n Do not output the trailing newline
  -1 .. -8 Set orientation value 1 .. 8
$ echo $?
1
$ jpegexiforient -3 parrots.jpg
$ echo $?
0
$ md5sum parrots.jpg
1b624b6d36f1c47f17095ae3dd336a92 parrots.jpg

Visually confirmed that the image does not display any differently after the failed EXIF changes (which would have been an interesting result considering the hash of the file stayed constant).

I downloaded a sample JPEG file from the following location ("PARROTS") https://www.fileformat.info/format/jpeg/sample/

Revision history for this message
Guy Paddock (guy-paddock) wrote :

I just converted the above original question into a bug report; I was not the original author of the question.

I'm seeing similar behavior, but only with some images. I have an image where using ExifTool produces an EXIF Orientation of 3, but jpegexiforient returns nothing:

> identify -format '%[EXIF:Orientation]' 00301827_0.jpg && echo && echo
3

> jpegexiforient 00301827_0.jpg
(No output)

Attached is exiftool's EXIF metadata dump in HTML format. I am guessing that perhaps the EXIF tags are in a different place in the file than `jpegexiforient` is used to?

Revision history for this message
Guy Paddock (guy-paddock) wrote :

For additional context, the image in question was produced by an Epson Perfection V600 Photo scanner.

Revision history for this message
Guy Paddock (guy-paddock) wrote :

This issue makes the related, top-level utility `exifautotran` unreliable for auto-rotating images, since that utility depends on the output from `jpegexiforient`.

As a workaround, it appears that using `jhead -autorot` works. jhead uses `jpegtran` under the hood.

Revision history for this message
Steve Stevenson (marginallosses) wrote :

It's worth noting that for some images `jpegtran` isn't able to perform its lossless transformations cleanly due to the nature of JPEG encoding. If you use the `-perfect` option it will fail on such images. You can use the `-trim` option as an alternative, but as the name of the option implies the resulting image will be slightly cropped.

Revision history for this message
Akkana Peck (akkzilla) wrote :

Still a problem in 20.04.

I'm not using -perfect. A way to reproduce this is to start with a JPG image from a camera, then scale it down using GraphicsMagick (this happens starting with JPGs from either a Sony or Canon camera). Like this:

$ convert dsc00902.jpg -scale 1024 dsc00902sm.jpg

$ jhead dsc00902*.jpg | grep Orientation
Orientation : rotate 90
Orientation : rotate 90

$ exifautotran dsc00902*.jpg
Executing: jpegtran -copy all -rotate 90 dsc00902.jpg

$ jhead dsc00902*.jpg | grep Orientation
Orientation : rotate 90

$ jhead dsc00902*.jpg | egrep '(File name|Orientation)'
File name : dsc00902.jpg
File name : dsc00902sm.jpg
Orientation : rotate 90

$ jhead -autorot dsc00902sm.jpg
Modified: dsc00902sm.jpg

$ jhead dsc00902*.jpg | egrep '(File name|Orientation)'
File name : dsc00902.jpg
File name : dsc00902sm.jpg

So after exifautotran dsc00902*.jpg, the original full-sized Sony JPEG was rotated, but not the smaller version I'd created using convert -scale from GraphicsMagick: it just silently failed.
But jhead -autorot was able to successfully rotate the scaled image.

Is there a better workaround than jhead -autorot until exifautotran/jpegexiforient get fixed?

Revision history for this message
Steve Stevenson (marginallosses) wrote :

Apparently the issue with my example (PARROTS.JPG) is that the file simply contains no EXIF data. It seems like a tool like jpegexiforient should emit some sort of message in this case, ideally output to stderr and return a non-zero exit code, since the whole point of jpegexiforient is to get or set the Orientation tag value and it's apparently unwilling to add EXIF data if it's missing.

While looking into this bug some more I noticed that this package (libjpeg9) does not have an Ubuntu maintainer, only an upstream maintainer. So I looked around in Debian's bug reports and found this, which may be related: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=947182

If the EXIF data doesn't appear in the spot that's ostensibly required by the standard, jpegexiforient throws up its hands and gives up. The Debian maintainer refuses to apply the patch that someone submitted which would give the tool the ability to look for the EXIF data elsewhere in the file. Behold the power of open source! I suppose we're all free to build the tool ourselves with the patch applied but sadly that's a bit outside of my wheelhouse.

It's also worth noting that jpegexiforient will ONLY operate on a file which not only has EXIF data, but has the Orientation tag set to some value. Sadly neither of these requirements are mentioned in the extremely short man page.

In the case of a file which has no EXIF data, it can be added with the tool "exif":

exif --output=parrots-1.jpg --create-exif --ifd=0 --tag=Orientation --set-value=1 PARROTS.JPG

At this point I was able to use jpegexiforient to modify the orientation tag.

However if the file already contains EXIF data but in a place that jpegexiforient is unhappy about, using exif to set the orientation works:

# ifd 0 seems to be the main image
exif --output=my_photo-3.jpg --ifd=0 --tag=Orientation --set-value=3 my_photo.jpg

# ifd 1 seems to be the thumbnail
exif --output=my_photo-3.jpg --ifd=1 --tag=Orientation --set-value=3 my_photo-3.jpg

(Where my_photo.jpg is a photo I took with a Panasonic G7 and scaled down with GIMP.)

I'm not sure about any solution to the use-case described in #5 , but my main interest was simply getting images to display correctly without any lossy re-encoding, and using "exif" seems to solve that problem for me. It sounds like exifautotran will continue to be broken until the maintainer for the libjpeg-turbo-progs package in Debian decides to stop cutting off their nose to spite their face and allows jpegexiforient to look for EXIF data in "non-standard" locations. (Which seems to be substantially more widespread than they think it is.)

Revision history for this message
Akkana Peck (akkzilla) wrote :

Interesting. But my images still have the Orientation tag, as shown by the jhead | egrep commands I listed. So maybe imagemagick and graphicsmagick (I tried both, same result) are writing the Orientation tag in the wrong place, and if jpegexiforient isn't going to be fixed, maybe I should be filing bugs on both imagemagick and graphicsmagick?

I'm also a bit curious why this only appeared recently. I've been using convert and exifautotran for many years, and they've worked fine together in the past. Since that Debian bug is from December 2019, maybe exifautotran only recently started enforcing this requirement.

If I understand https://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_JPEG_files,
SOI should be 0xFF, 0xD8 and APP1 should be 0xFF, 0xEn. The beginning of one of my scaled files in hexdump is:
0000000 d8ff e0ff 1000 464a 4649 0100 0101 5e01
0000010 5e01 0000 e1ff cbbb 7845 6669 0000 4949
so the d8ff (SOI) is right at the beginning, and the e1ff is in the second line. In the original image from the camera, the first line looks like:
0000000 d8ff e1ff cbbb 7845 6669 0000 4949 002a
so indeed, APP1 is right after the SOI.

That page also says:
In theory, Exif APP1 is recorded immediately after the SOI marker (the marker indicating the beginning of the file). However, this leads to the incompatibility between the Exif and JFIF standards because both of them specify that their particular application segment (APP0 for JFIF, APP1 for Exif) must be the first in the image file. In practice, most JPEG files contain a JFIF marker segment (APP0) that precedes the Exif APP1. This allows older readers to correctly handle the format JFIF segment, while newer readers also decode the following Exif segment, being less strict about requiring it to appear first. This way will not affect the image decoding for most decoders, but poorly designed JFIF or Exif parsers may not recognize the file properly.

But presumably the Debian libjpeg-turbo-progs maintainer would disagree. Sigh. I'll file imagemagick and graphicsmagick bugs.

Revision history for this message
Akkana Peck (akkzilla) wrote :

I filed bug 1842116 on graphicsmagick, haven't yet filed a similar bug on imagemagick. But it turns out (after rewriting my resizing script) that this also applies to files scaled by PIL. I wonder if there's any way of scaling a JPG programmatically that results in a file that the new exifautotran will accept.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Related questions

Remote bug watches

Bug watches keep track of this bug in other bug trackers.