From 6bbdb506da254033aaa60975851e5fae2a7b4c42 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 20 Oct 2024 12:03:53 -0700 Subject: [PATCH] Add EXIF and ICC encoding and fix chunk order --- src/chunk.rs | 2 ++ src/common.rs | 30 ++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/chunk.rs b/src/chunk.rs index 39578a44..3908313f 100644 --- a/src/chunk.rs +++ b/src/chunk.rs @@ -35,6 +35,8 @@ pub const gAMA: ChunkType = ChunkType(*b"gAMA"); pub const sRGB: ChunkType = ChunkType(*b"sRGB"); /// ICC profile chunk pub const iCCP: ChunkType = ChunkType(*b"iCCP"); +/// EXIF metadata chunk +pub const eXIf: ChunkType = ChunkType(*b"eXIf"); /// Latin-1 uncompressed textual data pub const tEXt: ChunkType = ChunkType(*b"tEXt"); /// Latin-1 compressed textual data diff --git a/src/common.rs b/src/common.rs index a3b6c275..259a2b1e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -507,6 +507,8 @@ pub struct Info<'a> { pub srgb: Option, /// The ICC profile for the image. pub icc_profile: Option>, + /// The EXIF metadata for the image. + pub exif_metadata: Option>, /// tEXt field pub uncompressed_latin1_text: Vec, /// zTXt field @@ -537,6 +539,7 @@ impl Default for Info<'_> { source_chromaticities: None, srgb: None, icc_profile: None, + exif_metadata: None, uncompressed_latin1_text: Vec::new(), compressed_latin1_text: Vec::new(), utf8_text: Vec::new(), @@ -631,6 +634,7 @@ impl Info<'_> { data[9] = self.color_type as u8; data[12] = self.interlaced as u8; encoder::write_chunk(&mut w, chunk::IHDR, &data)?; + // Encode the pHYs chunk if let Some(pd) = self.pixel_dims { let mut phys_data = [0; 9]; @@ -643,14 +647,6 @@ impl Info<'_> { encoder::write_chunk(&mut w, chunk::pHYs, &phys_data)?; } - if let Some(p) = &self.palette { - encoder::write_chunk(&mut w, chunk::PLTE, p)?; - }; - - if let Some(t) = &self.trns { - encoder::write_chunk(&mut w, chunk::tRNS, t)?; - } - // If specified, the sRGB information overrides the source gamma and chromaticities. if let Some(srgb) = &self.srgb { let gamma = crate::srgb::substitute_gamma(); @@ -665,11 +661,29 @@ impl Info<'_> { if let Some(chrms) = self.source_chromaticities { chrms.encode(&mut w)?; } + if let Some(iccp) = &self.icc_profile { + encoder::write_chunk(&mut w, chunk::iCCP, iccp)?; + } } + + if let Some(exif) = &self.exif_metadata { + encoder::write_chunk(&mut w, chunk::eXIf, exif)?; + } + if let Some(actl) = self.animation_control { actl.encode(&mut w)?; } + // The position of the PLTE chunk is important, it must come before the tRNS chunk and after + // many of the other metadata chunks. + if let Some(p) = &self.palette { + encoder::write_chunk(&mut w, chunk::PLTE, p)?; + }; + + if let Some(t) = &self.trns { + encoder::write_chunk(&mut w, chunk::tRNS, t)?; + } + for text_chunk in &self.uncompressed_latin1_text { text_chunk.encode(&mut w)?; }