Problem when copying tags from JFIF JPEG to Adobe JPEG

Started by JonSneyers, November 08, 2017, 06:36:12 AM

Previous topic - Next topic

JonSneyers

Hi Phil,

First of all: thanks for your awesome work on Exiftool, which is a very useful tool for us!

We use Exiftool to copy metadata from one image file to another. We use the command line options "-tagsfromfile FOO -all:all BAR" to copy the metadata of FOO to BAR. That works fine in most cases, but we have found a case where it produces undesired results. The problem case is where one image is a JPEG file that starts with a JFIF marker, and the other is a JPEG file that starts with an Adobe marker. In the attachment you will find minimal test files that cause the problematic behavior.

The problematic behavior is that in the resulting file, we get both a JFIF marker and an Adobe marker. This causes the image to render incorrectly in some viewers, since they get confused by the two markers. For example Firefox, Chrome, Gnome Image Viewer (eog), and ImageMagick will get confused. The example image is supposed to be white, but in many viewers, it will render as pink instead. In other viewers, like Apple's Preview and Safari, it still renders as white.

Here is a bit of output to show what is going on:

jon@macbuntu:~/dev/laboratory/src/Image-ExifTool-10.65$ hd orig.jpg |head -n 5
00000000  ff d8 ff ee 00 0e 41 64  6f 62 65 00 64 00 00 00  |......Adobe.d...|
00000010  00 00 ff db 00 43 00 07  0a 0a 0b 0c 0c 0c 0c 0c  |.....C..........|
00000020  0f 12 0f 0c 0f 11 14 10  0f 0f 13 17 1b 14 15 11  |................|
00000030  13 1e 20 25 23 22 1b 17  1b 26 27 34 2c 24 1b 32  |.. %#"...&'4,$.2|
00000040  28 20 20 32 38 2f 32 34  38 3b 3a 3a 26 2a 40 46  |(  28/248;::&*@F|
jon@macbuntu:~/dev/laboratory/src/Image-ExifTool-10.65$ hd metadata.jpg |head -n 5
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 01 01 00 96  |......JFIF......|
00000010  00 96 00 00 ff db 00 43  00 09 06 07 08 07 06 09  |.......C........|
00000020  08 08 08 0a 0a 09 0b 0e  17 0f 0e 0d 0d 0e 1c 14  |................|
00000030  15 11 17 22 1e 23 23 21  1e 20 20 25 2a 35 2d 25  |...".##!.  %*5-%|
00000040  27 32 28 20 20 2e 3f 2f  32 37 39 3c 3c 3c 24 2d  |'2(  .?/279<<<$-|
jon@macbuntu:~/dev/laboratory/src/Image-ExifTool-10.65$ ./exiftool -tagsfromfile metadata.jpg -all:all orig.jpg
    1 image files updated
jon@macbuntu:~/dev/laboratory/src/Image-ExifTool-10.65$ hd orig.jpg |head -n 5
00000000  ff d8 ff e0 00 10 4a 46  49 46 00 01 02 01 00 96  |......JFIF......|
00000010  00 96 00 00 ff ee 00 0e  41 64 6f 62 65 00 64 00  |........Adobe.d.|
00000020  00 00 00 00 ff db 00 43  00 07 0a 0a 0b 0c 0c 0c  |.......C........|
00000030  0c 0c 0f 12 0f 0c 0f 11  14 10 0f 0f 13 17 1b 14  |................|
00000040  15 11 13 1e 20 25 23 22  1b 17 1b 26 27 34 2c 24  |.... %#"...&'4,$|

Phil Harvey

#1
Thanks for this report.

It is hard to find documentation on the Adobe APP14, but this reference says:

When reading, the contents of the stream are interpreted by the usual JPEG
conventions, as follows:

  - If a JFIF APP0 marker segment is present, the colorspace is known to be
    either grayscale or YCbCr. If an APP2 marker segment containing an embedded
    ICC profile is also present, then the YCbCr is converted to RGB according to
    the formulas given in the JFIF spec, and the ICC profile is assumed to refer
    to the resulting RGB space.

  - If an Adobe APP14 marker segment is present, the colorspace is determined by
    consulting the transform flag. The transform flag takes one of three values:
   
    2 - The image is encoded as YCCK (implicitly converted from CMYK on encoding).
    1 - The image is encoded as YCbCr (implicitly converted from RGB on encoding).
    0 - Unknown. 3-channel images are assumed to be RGB, 4-channel images are
        assumed to be CMYK.

  - If neither marker segment is present, the following procedure is followed:
    Single-channel images are assumed to be grayscale, and 2-channel images are
    assumed to be grayscale with an alpha channel. For 3- and 4-channel images,
    the component ids are consulted. If these values are 1-3 for a 3-channel
    image, then the image is assumed to be YCbCr. Subject to the availability of
    the optional color space support described above, if these values are 1-4
    for a 4-channel image, then the image is assumed to be YCbCrA. If these
    values are > 4, they are checked against the ASCII codes for 'R', 'G', 'B',
    'A', 'C', 'c'. These can encode the following colorspaces:

    RGB
    RGBA
    YCC (as 'Y','C','c'), assumed to be PhotoYCC
    YCCA (as 'Y','C','c','A'), assumed to be PhotoYCCA

    Otherwise, 3-channel subsampled images are assumed to be YCbCr, 3-channel
    non-subsampled images are assumed to be RGB, 4-channel subsampled images are
    assumed to be YCCK, and 4-channel, non-subsampled images are assumed to be
    CMYK.

  - All other images are declared uninterpretable and an exception is thrown if
    an attempt is made to read one as a BufferedImage. Such an image may be read
    only as a Raster. If an image is interpretable but there is no Java
    ColorSpace available corresponding to the encoded colorspace (e.g. YCbCr),
    then ImageReader.getRawImageType will return null.


So it seems as if one shouldn't copy JFIF information into an image with an APP14.  So for now, to be safe, I suggest that you avoid copying the JFIF:

exiftool -tagsfromfile FOO -all:all --jfif:all BAR

I was thinking about adding a patch so ExifTool 10.66 would prevent JFIF information from being copied into a JPEG with an Adobe APP14 segment, and issue this warning:

    Not creating JFIF in JPEG with Adobe APP14

But there is still another case where copying JFIF may affect the rendering of the image (point 3 in the reference).  So I'm wondering if instead I should maybe just make it unsafe to copy JFIF?

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).