1From e912074417f5dd3eb9f4bc2dac41f22deae889b9 Mon Sep 17 00:00:00 2001
2From: Lukasz Anforowicz <[email protected]>
3Date: Fri, 1 Nov 2024 11:22:09 -0700
4Subject: [PATCH 302/302] Add support for parsing `cICP` chunks. (#529)
5
6---
7 src/chunk.rs          |  2 ++
8 src/common.rs         | 42 +++++++++++++++++++++++++++++++
9 src/decoder/stream.rs | 57 ++++++++++++++++++++++++++++++++++++++++++-
10 3 files changed, 100 insertions(+), 1 deletion(-)
11
12diff --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
13index 34a088f..b83ce54 100644
14--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
15+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/chunk.rs
16@@ -35,6 +35,8 @@ pub const gAMA: ChunkType = ChunkType(*b"gAMA");
17 pub const sRGB: ChunkType = ChunkType(*b"sRGB");
18 /// ICC profile chunk
19 pub const iCCP: ChunkType = ChunkType(*b"iCCP");
20+/// Coding-independent code points for video signal type identification chunk
21+pub const cICP: ChunkType = ChunkType(*b"cICP");
22 /// Mastering Display Color Volume chunk
23 pub const mDCv: ChunkType = ChunkType(*b"mDCv");
24 /// Content Light Level Information chunk
25diff --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
26index 4c06e3b..3d9dc13 100644
27--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
28+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/common.rs
29@@ -470,6 +470,45 @@ impl SrgbRenderingIntent {
30     }
31 }
32
33+/// Coding-independent code points (cICP) specify the color space (primaries),
34+/// transfer function, matrix coefficients and scaling factor of the image using
35+/// the code points specified in [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273).
36+///
37+/// See https://www.w3.org/TR/png-3/#cICP-chunk for more details.
38+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39+pub struct CodingIndependentCodePoints {
40+    /// Id number of the color primaries defined in
41+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 2 -
42+    /// Interpretation of colour primaries (ColourPrimaries) value".
43+    pub color_primaries: u8,
44+
45+    /// Id number of the transfer characteristics defined in
46+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 3 -
47+    /// Interpretation of transfer characteristics (TransferCharacteristics)
48+    /// value".
49+    pub transfer_function: u8,
50+
51+    /// Id number of the matrix coefficients defined in
52+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) in "Table 4 -
53+    /// Interpretation of matrix coefficients (MatrixCoefficients) value".
54+    ///
55+    /// This field is included to faithfully replicate the base
56+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but matrix coefficients
57+    /// will always be set to 0, because RGB is currently the only supported color mode in PNG.
58+    pub matrix_coefficients: u8,
59+
60+    /// Whether the image is
61+    /// [a full range image](https://www.w3.org/TR/png-3/#dfn-full-range-image)
62+    /// or
63+    /// [a narrow range image](https://www.w3.org/TR/png-3/#dfn-narrow-range-image).
64+    ///
65+    /// This field is included to faithfully replicate the base
66+    /// [ITU-T-H.273](https://www.itu.int/rec/T-REC-H.273) specification, but it has limited
67+    /// practical application to PNG images, because narrow-range images are [quite
68+    /// rare](https://github.com/w3c/png/issues/312#issuecomment-2327349614) in practice.
69+    pub is_video_full_range_image: bool,
70+}
71+
72 /// Mastering Display Color Volume (mDCv) used at the point of content creation,
73 /// as specified in [SMPTE-ST-2086](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=8353899).
74 ///
75@@ -557,6 +596,8 @@ pub struct Info<'a> {
76     pub srgb: Option<SrgbRenderingIntent>,
77     /// The ICC profile for the image.
78     pub icc_profile: Option<Cow<'a, [u8]>>,
79+    /// The coding-independent code points for video signal type identification of the image.
80+    pub coding_independent_code_points: Option<CodingIndependentCodePoints>,
81     /// The mastering display color volume for the image.
82     pub mastering_display_color_volume: Option<MasteringDisplayColorVolume>,
83     /// The content light information for the image.
84@@ -593,6 +634,7 @@ impl Default for Info<'_> {
85             source_chromaticities: None,
86             srgb: None,
87             icc_profile: None,
88+            coding_independent_code_points: None,
89             mastering_display_color_volume: None,
90             content_light_level: None,
91             exif_metadata: None,
92diff --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
93index 68de12d..760d5fd 100644
94--- a/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
95+++ b/third_party/rust/chromium_crates_io/vendor/png-0.17.14/src/decoder/stream.rs
96@@ -15,7 +15,7 @@ use crate::common::{
97 };
98 use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
99 use crate::traits::ReadBytesExt;
100-use crate::Limits;
101+use crate::{CodingIndependentCodePoints, Limits};
102
103 /// TODO check if these size are reasonable
104 pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
105@@ -959,6 +959,7 @@ impl StreamingDecoder {
106             chunk::fcTL => self.parse_fctl(),
107             chunk::cHRM => self.parse_chrm(),
108             chunk::sRGB => self.parse_srgb(),
109+            chunk::cICP => Ok(self.parse_cicp()),
110             chunk::mDCv => Ok(self.parse_mdcv()),
111             chunk::cLLi => Ok(self.parse_clli()),
112             chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
113@@ -1274,6 +1275,54 @@ impl StreamingDecoder {
114         }
115     }
116
117+    // NOTE: This function cannot return `DecodingError` and handles parsing
118+    // errors or spec violations as-if the chunk was missing.  See
119+    // https://github.com/image-rs/image-png/issues/525 for more discussion.
120+    fn parse_cicp(&mut self) -> Decoded {
121+        fn parse(mut buf: &[u8]) -> Result<CodingIndependentCodePoints, std::io::Error> {
122+            let color_primaries: u8 = buf.read_be()?;
123+            let transfer_function: u8 = buf.read_be()?;
124+            let matrix_coefficients: u8 = buf.read_be()?;
125+            let is_video_full_range_image = {
126+                let flag: u8 = buf.read_be()?;
127+                match flag {
128+                    0 => false,
129+                    1 => true,
130+                    _ => {
131+                        return Err(std::io::ErrorKind::InvalidData.into());
132+                    }
133+                }
134+            };
135+
136+            // RGB is currently the only supported color model in PNG, and as
137+            // such Matrix Coefficients shall be set to 0.
138+            if matrix_coefficients != 0 {
139+                return Err(std::io::ErrorKind::InvalidData.into());
140+            }
141+
142+            if !buf.is_empty() {
143+                return Err(std::io::ErrorKind::InvalidData.into());
144+            }
145+
146+            Ok(CodingIndependentCodePoints {
147+                color_primaries,
148+                transfer_function,
149+                matrix_coefficients,
150+                is_video_full_range_image,
151+            })
152+        }
153+
154+        // The spec requires that the cICP chunk MUST come before the PLTE and IDAT chunks.
155+        // Additionally, we ignore a second, duplicated cICP chunk (if any).
156+        let info = self.info.as_mut().unwrap();
157+        let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
158+        if is_before_plte_and_idat && info.coding_independent_code_points.is_none() {
159+            info.coding_independent_code_points = parse(&self.current_chunk.raw_bytes[..]).ok();
160+        }
161+
162+        Decoded::Nothing
163+    }
164+
165     // NOTE: This function cannot return `DecodingError` and handles parsing
166     // errors or spec violations as-if the chunk was missing.  See
167     // https://github.com/image-rs/image-png/issues/525 for more discussion.
168--
1692.47.0.199.ga7371fff76-goog
170
171