image-png
image-png copied to clipboard
Open questions about supporting Exif
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
}