From e912074417f5dd3eb9f4bc2dac41f22deae889b9 Mon Sep 17 00:00:00 2001
From: Lukasz Anforowicz <anforowicz@users.noreply.github.com>
Date: Fri, 1 Nov 2024 11:22:09 -0700
Subject: [PATCH 302/302] Add support for parsing `cICP` chunks. (#529)

---
 src/chunk.rs          |  2 ++
 src/common.rs         | 42 +++++++++++++++++++++++++++++++
 src/decoder/stream.rs | 57 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
index 34a088f..b83ce54 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/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");
+/// Coding-independent code points for video signal type identification chunk
+pub const cICP: ChunkType = ChunkType(*b"cICP");
 /// Mastering Display Color Volume chunk
 pub const mDCv: ChunkType = ChunkType(*b"mDCv");
 /// Content Light Level Information chunk
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
index 4c06e3b..3d9dc13 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
@@ -470,6 +470,45 @@ impl SrgbRenderingIntent {
     }
 }
 
+/// Coding-independent code points (cICP) specify the color space (primaries),
+/// transfer function, matrix coefficients and scaling factor of the image using
+/// the code points specified in [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273).
+///
+/// See https://www.w3.org/TR/png-3/#cICP-chunk for more details.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct CodingIndependentCodePoints {
+    /// Id number of the color primaries defined in
+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 2 -
+    /// Interpretation of colour primaries (ColourPrimaries) value".
+    pub color_primaries: u8,
+
+    /// Id number of the transfer characteristics defined in
+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 3 -
+    /// Interpretation of transfer characteristics (TransferCharacteristics)
+    /// value".
+    pub transfer_function: u8,
+
+    /// Id number of the matrix coefficients defined in
+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 4 -
+    /// Interpretation of matrix coefficients (MatrixCoefficients) value".
+    ///
+    /// This field is included to faithfully replicate the base
+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but matrix coefficients
+    /// will always be set to 0, because RGB is currently the only supported color mode in PNG.
+    pub matrix_coefficients: u8,
+
+    /// Whether the image is
+    /// [a full range image](https://www.w3.org/TR/png-3/#dfn-full-range-image)
+    /// or
+    /// [a narrow range image](https://www.w3.org/TR/png-3/#dfn-narrow-range-image).
+    ///
+    /// This field is included to faithfully replicate the base
+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but it has limited
+    /// practical application to PNG images, because narrow-range images are [quite
+    /// rare](https://github.com/w3c/png/issues/312#issuecomment-2327349614) in practice.
+    pub is_video_full_range_image: bool,
+}
+
 /// Mastering Display Color Volume (mDCv) used at the point of content creation,
 /// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899).
 ///
@@ -557,6 +596,8 @@ pub struct Info<'a> {
     pub srgb: Option<SrgbRenderingIntent>,
     /// The ICC profile for the image.
     pub icc_profile: Option<Cow<'a, [u8]>>,
+    /// The coding-independent code points for video signal type identification of the image.
+    pub coding_independent_code_points: Option<CodingIndependentCodePoints>,
     /// The mastering display color volume for the image.
     pub mastering_display_color_volume: Option<MasteringDisplayColorVolume>,
     /// The content light information for the image.
@@ -593,6 +634,7 @@ impl Default for Info<'_> {
             source_chromaticities: None,
             srgb: None,
             icc_profile: None,
+            coding_independent_code_points: None,
             mastering_display_color_volume: None,
             content_light_level: None,
             exif_metadata: None,
diff --git a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
index 68de12d..760d5fd 100644
--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
@@ -15,7 +15,7 @@ use crate::common::{
 };
 use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
 use crate::traits::ReadBytesExt;
-use crate::Limits;
+use crate::{CodingIndependentCodePoints, Limits};
 
 /// TODO check if these size are reasonable
 pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
@@ -959,6 +959,7 @@ impl StreamingDecoder {
             chunk::fcTL => self.parse_fctl(),
             chunk::cHRM => self.parse_chrm(),
             chunk::sRGB => self.parse_srgb(),
+            chunk::cICP => Ok(self.parse_cicp()),
             chunk::mDCv => Ok(self.parse_mdcv()),
             chunk::cLLi => Ok(self.parse_clli()),
             chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
@@ -1274,6 +1275,54 @@ impl StreamingDecoder {
         }
     }
 
+    // NOTE: This function cannot return `DecodingError` and handles parsing
+    // errors or spec violations as-if the chunk was missing.  See
+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
+    fn parse_cicp(&mut self) -> Decoded {
+        fn parse(mut buf: &[u8]) -> Result<CodingIndependentCodePoints, std::io::Error> {
+            let color_primaries: u8 = buf.read_be()?;
+            let transfer_function: u8 = buf.read_be()?;
+            let matrix_coefficients: u8 = buf.read_be()?;
+            let is_video_full_range_image = {
+                let flag: u8 = buf.read_be()?;
+                match flag {
+                    0 => false,
+                    1 => true,
+                    _ => {
+                        return Err(std::io::ErrorKind::InvalidData.into());
+                    }
+                }
+            };
+
+            // RGB is currently the only supported color model in PNG, and as
+            // such Matrix Coefficients shall be set to 0.
+            if matrix_coefficients != 0 {
+                return Err(std::io::ErrorKind::InvalidData.into());
+            }
+
+            if !buf.is_empty() {
+                return Err(std::io::ErrorKind::InvalidData.into());
+            }
+
+            Ok(CodingIndependentCodePoints {
+                color_primaries,
+                transfer_function,
+                matrix_coefficients,
+                is_video_full_range_image,
+            })
+        }
+
+        // The spec requires that the cICP chunk MUST come before the PLTE and IDAT chunks.
+        // Additionally, we ignore a second, duplicated cICP chunk (if any).
+        let info = self.info.as_mut().unwrap();
+        let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
+        if is_before_plte_and_idat && info.coding_independent_code_points.is_none() {
+            info.coding_independent_code_points = parse(&self.current_chunk.raw_bytes[..]).ok();
+        }
+
+        Decoded::Nothing
+    }
+
     // NOTE: This function cannot return `DecodingError` and handles parsing
     // errors or spec violations as-if the chunk was missing.  See
     // https://github.com/image-rs/image-png/issues/525 for more discussion.
-- 
2.47.0.199.ga7371fff76-goog

