w3c / png

Maintenance of the PNG specification
https://w3c.github.io/png/
Other
44 stars 11 forks source link

eXIf chunk change incompatible with the previously approved specification #447

Closed jbowler closed 3 months ago

jbowler commented 4 months ago

The eXIf chunk was approved here:

https://sourceforge.net/p/png-mng/mailman/message/35943428/

The chunk specification is http://www.simplesystems.org/png-group/proposals/eXIf/png-proposed-eXIf-chunk-2017-06-15.html#C.eXIf and it includes the following:

The eXIf chunk may appear anywhere between the IHDR and IEND chunks except between IDAT chunks

The new v3 specification declares that the eXIf chunk (which, note, is still safe-to-copy) must occur before IDAT. This would apparently invalidate existing valid PNG files.

There is extensive discussion of this in the rationale and on png-mng-misc.

That data isn't going to go away and must not be made invalid. Once it is valid it remains valid.

svgeesus commented 4 months ago

If you look at 5.6 Chunk ordering you will notice that most chunks come before IDAT. Two (fcTL and fdAT) necessarily come after IDAT. The four that can come anywhere (tIME, iTXt, tEXt and zTXt) do not affect image rendering in any way. eXIf, because it contains an image orientation, affects image rendering.

To avoid re-layout, browsers ignore any EXIF which occurs after image data.

Thus, best interoperability is achieved by requiring eXIf to come before IDAT.

The original proposal states:

Safe-to-copy ("eXIf") versus unsafe-to-copy ("eXIF"): The Exif profile (and thus the eXIf chunk) may contain not only material that is safe-to-copy, such as camera, lens, exposure and GPS information, but also unsafe-to-copy material about the image data, such as image orientation, width, height, gamma, and JPEG-specific compression information. We resolved that by including a statement that such unsafe-to-copy material should be regarded as historical in nature only, and made the chunk safe-to-copy to reduce the risk of losing valuable information.

That isn't Web compatible; the image orientation is respected, and can't be brushed off as merely historical because existing web pages rely on that information..

svgeesus commented 4 months ago

The original discussion about that is

For CSS, it is at

and for HTML, the relevant issue is

ProgramMax commented 4 months ago

libpng added eXIf support in 1.6.3, released on July 18, 2013.

Firefox explicitly ignores the eXIf chunk. Glenn Randers-Pehrson even patched Firefox in 2017 to add the eXIf chunk to the list of unknown chunks so a build using the system libpng would ignore it as well. That behavior remains today.

Chromium only reads eXIf from within PNGImageDecoder::HeaderAvailable. This function is called when the first IDAT is encountered (so enforcing "before IDAT" behavior). But that was added by me in 2024 to mimic what this spec said. Prior to that, the eXIf chunk was just ignored like it is in Firefox.

All this is to say the previous eXIf definition which allowed the eXIf chunk to arrive after IDAT was not being followed on the web. So there are no new breakages there. (I don't have a good way to test old MacOS / Safari.)

libpng currently checks that eXIf comes after IHDR but doesn't check if it comes before IDAT. Contrast that to the way libpng handles bKGD, which is by checking after IHDR and before IDAT. This means libpng follows the png-mng-misc suggested behavior. EXCEPT libpng also allowings eXIf between IDAT chunks, which is explicitly disallowed by png-mng-misc. So libpng only half-follows the png-mng-misc suggested behavior.

That said, any png eXIf written with libpng is done inside png_write_info(), which puts it before all IDAT chunks.

We would need to find an encoder which 1.) knows about eXIf, and 2.) places it after all IDATs to identify a problem. I'm struggling to find one. Photoshop does not know about the eXIf chunk. GIMP does (heyyy good job, GIMP!). But only when loading. Once loaded, it applies the rotation and discards the EXIF information. That means when the image is later saved, the eXIf chunk is gone. So this doesn't satisfy the "encoder which __".

Can you help me find where in the png-mng mailing lists it was reasoned that eXIf should be allowed after IDAT? I can't find it. If I had to guess, it would be because of the displayed vs. not-displayed behavior (similar to the safe-to-copy vs. not-safe-to-copy). Camera and lens information can come after IDAT with no problems. In fact, it probably should so the image can be displayed sooner while downloaded. However, the rotation information of EXIF is problematic if it comes after IDAT, as found in the discussions @svgeesus linked above.

If my guess about png-mng's reasoning is right & given there is no new web breakage & I need to hunt pretty hard to find a case where this problem actually happens (I haven't found any cases), I feel confident saying the benefits of the "before IDAT" behavior are worth it.

ProgramMax commented 3 months ago

I'm going to close this issue because I believe the current spec wording is correct. Feel free to comment and re-open if we find an encoder that saves eXIf after all IDATs.