PNG EXIF GPS decoding bug

Started by Neal Krawetz, September 05, 2024, 06:18:55 PM

Previous topic - Next topic

Neal Krawetz

Hi Phil,

I have a PNG file that contains EXIF with GPS.
ExifTool is reporting the raw numerator/denominator values rather than the decoded values.

ExifTool 12.92 (and lots of earlier).

It's showing output like:

Exif GPS Altitude               : 1463021/892
Exif GPS Altitude Ref           : .
Exif GPS Date Stamp             : 2024:07:30
Exif GPS Dest Bearing           : 364029/2245
Exif GPS Dest Bearing Ref       : T
Exif GPSH Positioning Error     : 95525/17884
Exif GPS Img Direction          : 364029/2245

This only seems to happen with PNG that has an "eXIf" chunk containing GPS in the EXIF data.

Neal Krawetz

Correction: The problem isn't just with GPS.

It seems to be with all rationals in PNG EXIF.

E.g.:
https://fotoforensics.com/analysis.php?id=bae46ce357c066f5647b69cc64718a1a8d46d049.181402&show=meta

There are also some formatting errors where there is no space in the field name. (Same example link shows this problem, like "Exifthumbnail Resolution Unit" and "Icccopyright".

StarGeek

Can you share the file? Reading/Writing GPS data with exiftool works correctly here.

I downloaded what I think is your file from FotoForensics (https://fotoforensics.com/analysis.php?id=bae46ce357c066f5647b69cc64718a1a8d46d049.181402&fmt=orig?) and I didn't see any coordinates in the output, just the GPS version and an info tag.

But it confirms the problem I saw with you output above. EXIF and GPS tags do not contain the word "Exif" in them. EXIF will appear in brackets if you add the -G (-groupNames) option, indicating the group name, but never in the actual tag name.

Looking at just EXIF tags doesn't return anything, just the warning about data after the PNG IDAT chunk (a whole separate subject that shouldn't be relevant, basically only affects inlined PNG images in a browser)
C:\>exiftool -G -a -s -exif:all Y:\!temp\x\bae46ce357c066f5647b69cc64718a1a8d46d049.181402.png
Warning: [minor] Text/EXIF chunk(s) found after PNG IDAT (may be ignored by some readers) - Y:/!temp/x/bae46ce357c066f5647b69cc64718a1a8d46d049.181402.png

C:\>

Compare that to a file that exiftool has written
C:\Programs\My_Stuff>exiftool -G -a -s -exif:all Y:\!temp\test.png
[EXIF]          XResolution                     : 72
[EXIF]          YResolution                     : 72
[EXIF]          ResolutionUnit                  : inches
[EXIF]          YCbCrPositioning                : Centered
[EXIF]          GPSVersionID                    : 2.3.0.0
[EXIF]          GPSLatitudeRef                  : North
[EXIF]          GPSLatitude                     : 40 deg 41' 21.12"
[EXIF]          GPSLongitudeRef                 : West
[EXIF]          GPSLongitude                    : 74 deg 2' 40.20"

Your file, on the other hand, as a bunch of tags that start with the word Exif, but are not EXIF tags
C:\>exiftool -G -a -s -exif* Y:\!temp\x\bae46ce357c066f5647b69cc64718a1a8d46d049.181402.png
[ExifTool]      ExifToolVersion                 : 12.95
[PNG]           ExifApertureValue               : 4970854/1000000
[PNG]           ExifBitsPerSample               : 8, 8, 8
[PNG]           ExifBodySerialNumber            : 243057001849
[PNG]           ExifColorSpace                  : 65535
[PNG]           ExifCompression                 : 1
[PNG]           ExifCustomRendered              : 0
[PNG]           ExifDateTime                    : 2023:12:08 10:04:43
[PNG]           ExifExifOffset                  : 504
[PNG]           ExifExposureBiasValue           : 0/1
[PNG]           ExifExposureMode                : 1
[PNG]           ExifExposureTime                : 1/250
[PNG]           ExifFileSource                  : 3
[PNG]           ExifFNumber                     : 56/10
[PNG]           ExifFocalLength                 : 47/1
[PNG]           ExifFocalPlaneResolutionUnit    : 2
[PNG]           ExifFocalPlaneXResolution       : 187405072/32768
[PNG]           ExifFocalPlaneYResolution       : 187724608/32768
[PNG]           ExifGPSInfo                     : 1240
[PNG]           ExifGPSVersionID                : 2, 3, 0, 0
[PNG]           ExifImageLength                 : 6472
[PNG]           ExifImageWidth                  : 4315
[PNG]           ExifLensModel                   : Canon EF 24-70mm f/2.8L II USM
[PNG]           ExifLensSerialNumber            : 8690002469
[PNG]           ExifLensSpecification           : 24/1, 70/1, 0/0, 0/0
[PNG]           ExifOrientation                 : 1
[PNG]           ExifPhotometricInterpretation   : 2
[PNG]           ExifPixelXDimension             : 4315
[PNG]           ExifPixelYDimension             : 5754
[PNG]           ExifPlanarConfiguration         : 1
[PNG]           ExifRecommendedExposureIndex    : 1600
[PNG]           ExifResolutionUnit              : 2
[PNG]           ExifSamplesPerPixel             : 3
[PNG]           ExifSceneCaptureType            : 0
[PNG]           ExifSceneType                   : 1
[PNG]           ExifSensitivityType             : 2
[PNG]           ExifShutterSpeedValue           : 7965784/1000000
[PNG]           ExifSubjectDistance             : 0/1
[PNG]           ExifthumbnailCompression        : 6
[PNG]           ExifthumbnailJPEGInterchangeFormat: 1352
[PNG]           ExifthumbnailJPEGInterchangeFormatLength: 4536
[PNG]           ExifthumbnailResolutionUnit     : 2
[PNG]           ExifthumbnailXResolution        : 96/1
[PNG]           ExifthumbnailYResolution        : 96/1
[PNG]           ExifXResolution                 : 3000000/10000
[PNG]           ExifYResolution                 : 3000000/10000

Using the -v3 (-verbose3) option, I can see in your file that each of the "exif" tags is a separate tEXt chunk
PNG tEXt (34 bytes):
     2bca6: 65 78 69 66 3a 41 70 65 72 74 75 72 65 56 61 6c [exif:ApertureVal]
     2bcb6: 75 65 00 34 39 37 30 38 35 34 2f 31 30 30 30 30 [ue.4970854/10000]
     2bcc6: 30 30                                           [00]
  [adding exif:ApertureValue]
  ExifApertureValue = 4970854/1000000
  - Tag 'exif:ApertureValue' (15 bytes):
      0000: 34 39 37 30 38 35 34 2f 31 30 30 30 30 30 30    [4970854/1000000]
PNG tEXt (26 bytes):
     2bcd4: 65 78 69 66 3a 42 69 74 73 50 65 72 53 61 6d 70 [exif:BitsPerSamp]
     2bce4: 6c 65 00 38 2c 20 38 2c 20 38                   [le.8, 8, 8]
  [adding exif:BitsPerSample]
  ExifBitsPerSample = 8, 8, 8
  - Tag 'exif:BitsPerSample' (7 bytes):
      0000: 38 2c 20 38 2c 20 38                            [8, 8, 8]
PNG tEXt (34 bytes):
     2bcfa: 65 78 69 66 3a 42 6f 64 79 53 65 72 69 61 6c 4e [exif:BodySerialN]
     2bd0a: 75 6d 62 65 72 00 32 34 33 30 35 37 30 30 31 38 [umber.2430570018]
     2bd1a: 34 39                                           [49]
  [adding exif:BodySerialNumber]

In the past, before EXIF was officially added to the PNG standard, exiftool would write EXIF data to a tEXt chunk, which original came from ImageMagick embedding EXIF data in this manner. But it was a single tEXt chunk which contained a actual EXIF data block. It should look like this, except it would have ha PNG tEXt instead of PNG eXIf
PNG eXIf (348 bytes):
      037b: 4d 4d 00 2a 00 00 00 08 00 05 01 1a 00 05 00 00 [MM.*............]
      038b: 00 01 00 00 00 4a 01 1b 00 05 00 00 00 01 00 00 [.....J..........]
      039b: 00 52 01 28 00 03 00 00 00 01 00 02 00 00 02 13 [.R.(............]
      03ab: 00 03 00 00 00 01 00 01 00 00 88 25 00 04 00 00 [...........%....]
      03bb: 00 01 00 00 00 5a 00 00 00 00 00 00 00 48 00 00 [.....Z.......H..]
      [snip 268 bytes]
  + [TIFF directory]
  | ExifByteOrder = MM
  | + [IFD0 directory with 5 entries]
  | | 0)  XResolution = 72 (72/1)
  | |     - Tag 0x011a (8 bytes, rational64u[1]):
  | |         004a: 00 00 00 48 00 00 00 01                         [...H....]
  | | 1)  YResolution = 72 (72/1)
  | |     - Tag 0x011b (8 bytes, rational64u[1]):
  | |         0052: 00 00 00 48 00 00 00 01                         [...H....]
  | | 2)  ResolutionUnit = 2
  | |     - Tag 0x0128 (2 bytes, int16u[1]):
  | |         002a: 00 02                                           [..]
  | | 3)  YCbCrPositioning = 1
  | |     - Tag 0x0213 (2 bytes, int16u[1]):
  | |         0036: 00 01                                           [..]
  | | 4)  GPSInfo (SubDirectory) -->
  | |     - Tag 0x8825 (4 bytes, int32u[1]):
  | |         0042: 00 00 00 5a                                     [...Z]
  | | + [GPS directory with 11 entries]
  | | | 0)  GPSVersionID = 2 3 0 0
  | | |     - Tag 0x0000 (4 bytes, int8u[4]):
  | | |         0064: 02 03 00 00                                     [....]

The short version, your file doesn't contain any EXIF tags, only a bunch of custom text tags that have exif in the name.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Neal Krawetz

Hi @StarGeek,

I can't share the GPS file, so I'm looking for other examples.

I just noticed your observation with "exiftool -v".
You're right! My GPS file contains both eXIf with regular EXIF data (processed properly) and tEXt with the numerator/denominator as text!

Not a bug! (Just a really weird screwup!)

StarGeek

Do you know what software wrote the file?
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Neal Krawetz

I'm digging up examples.

None identify the application.

Nearly all were last saved using ImageMagick.

StarGeek

The "Text/EXIF chunk(s) found after PNG IDAT (may be ignored by some readers)" is how IM saves the files and apparently has done so from the start. The biggest problem with this is with browsers. Normally, it would read the dimensions before getting the image data so the browser can reserve the proper space on the page. That's the reason for the warning.

Weird though if it's writing bad EXIF data though.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

Phil Harvey

I'm a bit late to the party (still catching up after my vacation), but any GPS written to a custom PNG tEXt chunk will be extracted as-is without any conversion.

- 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 ($).