image-png icon indicating copy to clipboard operation
image-png copied to clipboard

Open questions about supporting Exif

Open sophie-h opened this issue 1 year ago • 1 comments

Reading chunks after IDAT

Turns out that at least ImageMagic put the eXif chunk behind IDAT, not following PNG 1.3. So we will not catch those with read_until_image_data used in read_info(). Afaik there is no way to read anything behind IDAT chunks at all?

I would suggest at least adding an option to read to the end of the file to get all metadata. One argument for that is that text chunks are allowed behind IDAT even per standard. I have no idea yet how intrusive this change would be though.

Supporting legacy formats

The second thing is that there are legacy ways of storing Exif data in PNGs via text chunks. GIMP for example uses this method to this day. This information would be accessible to API users already without further support. The question is if we want to add support for it anyway. One argument would be that we can have a more reliable exif() function in image-rs one day. And maybe it makes sense to keep the code in the png crate? That's what the code would roughly look like.

The byteorder check is recommended for decoders supporting the eXif chunk as well.

    pub fn exif(&self) -> Option<Vec<u8>> {
        for chunk in self.compressed_latin1_text.iter() {
            if chunk.keyword.as_str() == "Raw profile type exif" {
                let mut chunk = chunk.clone();
                chunk.decompress_text().ok()?;
                let text = chunk.get_text().ok()?.replace('\n', "");
                let bytes = hex::decode(text.get(8..)?).ok()?;
                let relevant_bytes = bytes.get(8..)?;

                // Reject unkown byteorder
                let byteorder = relevant_bytes.get(..2)?;
                if byteorder != b"II" && byteorder != b"MM" {
                    return None;
                }

                return Some(bytes.to_vec());
            }
        }

        None
    }

sophie-h avatar Dec 16 '23 22:12 sophie-h