/src/mp4san/webpsan/src/parse/lossless.rs
Line | Count | Source |
1 | | #![allow(missing_docs)] |
2 | | |
3 | | use std::fmt::Debug; |
4 | | use std::io::Read; |
5 | | use std::num::{NonZeroU32, NonZeroU8}; |
6 | | |
7 | | use bitstream_io::{Numeric, LE}; |
8 | | use derive_more::Display; |
9 | | use mediasan_common::{ensure_attach, ensure_matches_attach}; |
10 | | use num_integer::div_ceil; |
11 | | use num_traits::AsPrimitive; |
12 | | |
13 | | use crate::{Error, ResultExt}; |
14 | | |
15 | | use super::bitstream::{BitBufReader, CanonicalHuffmanTree, LZ77_MAX_LEN}; |
16 | | use super::ParseError; |
17 | | |
18 | | #[derive(Clone)] |
19 | | pub struct LosslessImage { |
20 | | _image: SpatiallyCodedImage, |
21 | | } |
22 | | |
23 | | // |
24 | | // private types |
25 | | // |
26 | | |
27 | | #[derive(Clone, Display, PartialEq, Eq)] |
28 | | enum Transform { |
29 | | #[display("predictor transform: block size {block_size}")] |
30 | | Predictor { block_size: u16, _image: EntropyCodedImage }, |
31 | | #[display("color transform: block size {block_size}")] |
32 | | Color { block_size: u16, _image: EntropyCodedImage }, |
33 | | #[display("subtract green transform")] |
34 | | SubtractGreen, |
35 | | #[display("color indexing transform: {} colors", "image.width")] |
36 | | ColorIndexing { image: EntropyCodedImage }, |
37 | | } |
38 | | |
39 | | #[repr(u8)] |
40 | | #[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord)] |
41 | | enum TransformType { |
42 | | #[display("predictor")] |
43 | | Predictor = 0b00, |
44 | | #[display("color")] |
45 | | Color = 0b01, |
46 | | #[display("subtract green")] |
47 | | SubtractGreen = 0b10, |
48 | | #[display("color indexing")] |
49 | | ColorIndexing = 0b11, |
50 | | } |
51 | | |
52 | | #[derive(Clone, PartialEq, Eq)] |
53 | | struct EntropyCodedImage { |
54 | | width: NonZeroU32, |
55 | | height: NonZeroU32, |
56 | | } |
57 | | |
58 | | #[derive(Clone, PartialEq, Eq)] |
59 | | struct SpatiallyCodedImage; |
60 | | |
61 | | #[derive(Clone, Copy, Debug, Display, PartialEq, Eq)] |
62 | | #[display("distance {dist} length {len}")] |
63 | | struct BackReference { |
64 | | dist: NonZeroU32, |
65 | | len: NonZeroU32, |
66 | | } |
67 | | |
68 | | #[derive(Clone, Copy, Debug, Default, Display, PartialEq, Eq)] |
69 | | #[display("({alpha}, {red}, {green}, {blue})")] |
70 | | struct Color { |
71 | | alpha: u8, |
72 | | red: u8, |
73 | | green: u8, |
74 | | blue: u8, |
75 | | } |
76 | | |
77 | | #[derive(Clone)] |
78 | | struct ColorCache { |
79 | | order: Option<NonZeroU8>, |
80 | | } |
81 | | |
82 | | #[derive(Clone, Display, PartialEq, Eq)] |
83 | | enum MetaPrefixCodes { |
84 | | #[display("single meta prefix code")] |
85 | | Single, |
86 | | #[display("multiple meta prefix codes: max code group {max_code_group}, block size {block_size}")] |
87 | | Multiple { |
88 | | block_size: u16, |
89 | | max_code_group: u16, |
90 | | _image: EntropyCodedImage, |
91 | | }, |
92 | | } |
93 | | |
94 | | trait PrefixCode { |
95 | | type Symbol: Numeric; |
96 | | |
97 | | fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self; |
98 | | |
99 | | fn alphabet_size(color_cache_len: u16) -> u16; |
100 | | } |
101 | | |
102 | | struct PrefixCodeGroup { |
103 | | green: GreenPrefixCode, |
104 | | red: ARBPrefixCode, |
105 | | blue: ARBPrefixCode, |
106 | | alpha: ARBPrefixCode, |
107 | | distance: DistancePrefixCode, |
108 | | } |
109 | | |
110 | | struct CodeLengthPrefixCode { |
111 | | tree: CanonicalHuffmanTree<LE, u8>, |
112 | | } |
113 | | |
114 | | struct GreenPrefixCode { |
115 | | tree: CanonicalHuffmanTree<LE, u16>, |
116 | | } |
117 | | |
118 | | struct ARBPrefixCode { |
119 | | tree: CanonicalHuffmanTree<LE, u8>, |
120 | | } |
121 | | |
122 | | struct DistancePrefixCode { |
123 | | tree: CanonicalHuffmanTree<LE, u8>, |
124 | | } |
125 | | |
126 | | #[derive(Clone, Copy, Debug, Display)] |
127 | | #[display("out-of-bounds color cache index `{_0}` >= `{_1}`")] |
128 | | struct ColorCacheIndexOutOfBounds(u16, u16); |
129 | | |
130 | | #[derive(Clone, Copy, Debug, Display)] |
131 | | #[display("invalid back-reference distance `{_0}` at pixel `{_1}`")] |
132 | | struct InvalidBackRefDistance(NonZeroU32, u32); |
133 | | |
134 | | #[derive(Clone, Copy, Debug, Display)] |
135 | | #[display("invalid back-reference length `{_0}` at pixel `{_1}` with image length `{_2}`")] |
136 | | struct InvalidBackRefLength(NonZeroU32, u32, u32); |
137 | | |
138 | | #[derive(Clone, Copy, Debug, Display)] |
139 | | #[display("invalid code length repetition `{_0}` at `{_1}` with max symbols `{_2}`")] |
140 | | struct InvalidCodeLengthRepetition(u8, usize, u16); |
141 | | |
142 | | #[derive(Clone, Copy, Debug, Display)] |
143 | | #[display("invalid color cache size `{_0}`")] |
144 | | struct InvalidColorCacheSize(u8); |
145 | | |
146 | | #[derive(Clone, Copy, Debug, Display)] |
147 | | #[display("invalid duplicate {_0} transform")] |
148 | | struct InvalidDuplicateTransform(TransformType); |
149 | | |
150 | | #[derive(Clone, Copy, Debug, Display)] |
151 | | #[display("invalid predictor `{_0}`")] |
152 | | struct InvalidPredictor(u8); |
153 | | |
154 | | #[derive(Clone, Copy, Debug, Display)] |
155 | | #[display("invalid symbol count `{_0}` >= `{_1}`")] |
156 | | struct InvalidSymbolCount(u16, u16); |
157 | | |
158 | | #[derive(Clone, Copy, Debug, Display)] |
159 | | #[display("while parsing {_0} transform")] |
160 | | struct WhileParsingTransform(TransformType); |
161 | | |
162 | | // |
163 | | // LosslessImage impls |
164 | | // |
165 | | |
166 | | impl LosslessImage { |
167 | 5.66k | pub fn read<R: Read>( |
168 | 5.66k | reader: &mut BitBufReader<R, LE>, |
169 | 5.66k | width: NonZeroU32, |
170 | 5.66k | height: NonZeroU32, |
171 | 5.66k | ) -> Result<Self, Error> { |
172 | 5.66k | let mut transformed_width = width; |
173 | 5.66k | let mut transforms = [false; TransformType::COUNT]; |
174 | 7.99k | while reader.read_bit()? { |
175 | 3.97k | let transform = Transform::read(reader, transformed_width, height).while_parsing_type()?; |
176 | | |
177 | 2.37k | transformed_width = transform.transformed_width(transformed_width); |
178 | | |
179 | 2.37k | ensure_attach!( |
180 | 2.37k | !transforms[transform.transform_type() as usize], |
181 | 33 | ParseError::InvalidInput, |
182 | 33 | InvalidDuplicateTransform(transform.transform_type()), |
183 | | ); |
184 | | |
185 | 2.33k | transforms[transform.transform_type() as usize] = true; |
186 | 2.33k | log::info!("{transform}"); |
187 | | } |
188 | | |
189 | 3.93k | let _image = SpatiallyCodedImage::read(reader, transformed_width, height).while_parsing_type()?; |
190 | | |
191 | 597 | Ok(Self { _image }) |
192 | 5.66k | } |
193 | | } |
194 | | |
195 | | // |
196 | | // Transform impls |
197 | | // |
198 | | |
199 | | impl Transform { |
200 | 3.97k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> { |
201 | 3.97k | match TransformType::read(reader)? { |
202 | 862 | transform @ TransformType::Predictor => { |
203 | 862 | let block_order = 2 + reader |
204 | 862 | .read::<u32>(3) |
205 | 862 | .attach_printable(WhileParsingTransform(transform))?; |
206 | 852 | let block_size = 2u16.pow(block_order); |
207 | 852 | let width_in_blocks = len_in_blocks(width, block_size); |
208 | 852 | let height_in_blocks = len_in_blocks(height, block_size); |
209 | 5.15M | let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |pixel| { |
210 | 32 | ensure_matches_attach!( |
211 | 5.15M | pixel.green, |
212 | 5.15M | 0..=13, |
213 | 32 | ParseError::InvalidInput, |
214 | 32 | InvalidPredictor(pixel.green), |
215 | | ); |
216 | 5.15M | Ok(()) |
217 | 5.15M | }) |
218 | 852 | .while_parsing_type() |
219 | 852 | .attach_printable(WhileParsingTransform(transform))?; |
220 | 189 | Ok(Self::Predictor { block_size, _image }) |
221 | | } |
222 | 783 | transform @ TransformType::Color => { |
223 | 783 | let block_order = 2 + reader |
224 | 783 | .read::<u32>(3) |
225 | 783 | .attach_printable(WhileParsingTransform(transform))?; |
226 | 778 | let block_size = 2u16.pow(block_order); |
227 | 778 | let width_in_blocks = len_in_blocks(width, block_size); |
228 | 778 | let height_in_blocks = len_in_blocks(height, block_size); |
229 | 21.2M | let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |_| Ok(())) |
230 | 778 | .while_parsing_type() |
231 | 778 | .attach_printable(WhileParsingTransform(transform))?; |
232 | 197 | Ok(Self::Color { block_size, _image }) |
233 | | } |
234 | 1.21k | TransformType::SubtractGreen => Ok(Self::SubtractGreen), |
235 | 1.08k | transform @ TransformType::ColorIndexing => { |
236 | 1.08k | let len_minus_one = reader.read(8).attach_printable(WhileParsingTransform(transform))?; |
237 | 1.06k | let len = NonZeroU32::MIN.saturating_add(len_minus_one); |
238 | 121k | let image = EntropyCodedImage::read(reader, len, NonZeroU32::MIN, |_| Ok(())) |
239 | 1.06k | .while_parsing_type() |
240 | 1.06k | .attach_printable(WhileParsingTransform(transform))?; |
241 | 770 | Ok(Self::ColorIndexing { image }) |
242 | | } |
243 | | } |
244 | 3.97k | } |
245 | | |
246 | 4.74k | fn transform_type(&self) -> TransformType { |
247 | 4.74k | match self { |
248 | 378 | Transform::Predictor { .. } => TransformType::Predictor, |
249 | 394 | Transform::Color { .. } => TransformType::Color, |
250 | 2.43k | Transform::SubtractGreen => TransformType::SubtractGreen, |
251 | 1.54k | Transform::ColorIndexing { .. } => TransformType::ColorIndexing, |
252 | | } |
253 | 4.74k | } |
254 | | |
255 | 2.37k | fn transformed_width(&self, width: NonZeroU32) -> NonZeroU32 { |
256 | 2.37k | match self { |
257 | 770 | Transform::ColorIndexing { image } => { |
258 | 770 | let block_size = match image.width.get() { |
259 | 770 | 0..=2 => 8, |
260 | 752 | 3..=4 => 4, |
261 | 736 | 5..=16 => 2, |
262 | 724 | 17.. => 1, |
263 | | }; |
264 | 770 | len_in_blocks(width, block_size) |
265 | | } |
266 | 1.60k | _ => width, |
267 | | } |
268 | 2.37k | } |
269 | | } |
270 | | |
271 | | impl TransformType { |
272 | | const PREDICTOR: u8 = TransformType::Predictor as u8; |
273 | | const COLOR: u8 = TransformType::Color as u8; |
274 | | const SUBTRACT_GREEN: u8 = TransformType::SubtractGreen as u8; |
275 | | const COLOR_INDEXING: u8 = TransformType::ColorIndexing as u8; |
276 | | |
277 | | const COUNT: usize = 4; |
278 | | |
279 | 3.97k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> { |
280 | 3.97k | match reader.read(2)? { |
281 | 862 | Self::PREDICTOR => Ok(Self::Predictor), |
282 | 783 | Self::COLOR => Ok(Self::Color), |
283 | 1.21k | Self::SUBTRACT_GREEN => Ok(Self::SubtractGreen), |
284 | 1.08k | Self::COLOR_INDEXING => Ok(Self::ColorIndexing), |
285 | 0 | 0b100.. => unreachable!(), |
286 | | } |
287 | 3.97k | } |
288 | | } |
289 | | |
290 | | // |
291 | | // EntropyCodedImage impls |
292 | | // |
293 | | |
294 | | impl EntropyCodedImage { |
295 | 4.97k | fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>( |
296 | 4.97k | reader: &mut BitBufReader<R, LE>, |
297 | 4.97k | width: NonZeroU32, |
298 | 4.97k | height: NonZeroU32, |
299 | 4.97k | mut fun: F, |
300 | 4.97k | ) -> Result<Self, Error> { |
301 | 4.97k | let color_cache = ColorCache::read(reader).while_parsing_type()?; |
302 | 4.88k | let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; |
303 | 4.09k | let green_readahead_bits = codes.green_readahead_bits(); |
304 | 4.09k | let arb_readahead_bits = codes.arb_readahead_bits(); |
305 | 4.09k | let backref_readahead_bits = codes.backref_readahead_bits(); |
306 | 4.09k | let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits); |
307 | | |
308 | 4.09k | let len = width.saturating_mul(height); |
309 | 4.09k | let mut pixel_idx = 0; |
310 | 44.5M | while pixel_idx < len.get() { |
311 | 44.5M | if reader.buf_bits() < u64::from(readahead_bits) { |
312 | 18.2k | reader.fill_buf()?; |
313 | 44.5M | } |
314 | 44.5M | match reader.buf_read_huffman(&codes.green.tree)? { |
315 | 44.5M | symbol @ 0..=255 => { |
316 | 38.3M | let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?; |
317 | 38.3M | log::debug!("color: {color}"); |
318 | 38.3M | fun(color)?; |
319 | 38.3M | if green_readahead_bits + arb_readahead_bits == 0 { |
320 | 1.50k | pixel_idx = len.get(); |
321 | 38.3M | } else { |
322 | 38.3M | pixel_idx += 1; |
323 | 38.3M | } |
324 | | } |
325 | 6.21M | symbol @ 256..=279 => { |
326 | 3.40M | let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?; |
327 | 3.40M | log::debug!("backref: {back_ref}"); |
328 | 148 | ensure_matches_attach!( |
329 | 3.40M | pixel_idx.checked_sub(back_ref.dist.get()), |
330 | | Some(_), |
331 | 148 | ParseError::InvalidInput, |
332 | 148 | InvalidBackRefDistance(back_ref.dist, pixel_idx), |
333 | | ); |
334 | 3.40M | ensure_attach!( |
335 | 3.40M | back_ref.len.get() <= len.get() - pixel_idx, |
336 | 80 | ParseError::InvalidInput, |
337 | 80 | InvalidBackRefLength(back_ref.len, pixel_idx, len.get()), |
338 | | ); |
339 | 3.40M | pixel_idx += back_ref.len.get(); |
340 | | } |
341 | 2.80M | symbol @ 280.. => { |
342 | 2.80M | let color_cache_index = symbol - 280; |
343 | 2.80M | log::debug!("cached: {color_cache_index}"); |
344 | 2.80M | ensure_attach!( |
345 | 2.80M | color_cache_index < color_cache.len(), |
346 | 0 | ParseError::InvalidInput, |
347 | 0 | ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()), |
348 | | ); |
349 | 2.80M | if green_readahead_bits == 0 { |
350 | 2 | pixel_idx = len.get(); |
351 | 2.80M | } else { |
352 | 2.80M | pixel_idx += 1; |
353 | 2.80M | } |
354 | | } |
355 | | } |
356 | | } |
357 | 2.75k | Ok(Self { width, height }) |
358 | 4.97k | } <webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::MetaPrefixCodes>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#0}> Line | Count | Source | 295 | 2.27k | fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>( | 296 | 2.27k | reader: &mut BitBufReader<R, LE>, | 297 | 2.27k | width: NonZeroU32, | 298 | 2.27k | height: NonZeroU32, | 299 | 2.27k | mut fun: F, | 300 | 2.27k | ) -> Result<Self, Error> { | 301 | 2.27k | let color_cache = ColorCache::read(reader).while_parsing_type()?; | 302 | 2.25k | let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; | 303 | 2.01k | let green_readahead_bits = codes.green_readahead_bits(); | 304 | 2.01k | let arb_readahead_bits = codes.arb_readahead_bits(); | 305 | 2.01k | let backref_readahead_bits = codes.backref_readahead_bits(); | 306 | 2.01k | let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits); | 307 | | | 308 | 2.01k | let len = width.saturating_mul(height); | 309 | 2.01k | let mut pixel_idx = 0; | 310 | 12.9M | while pixel_idx < len.get() { | 311 | 12.9M | if reader.buf_bits() < u64::from(readahead_bits) { | 312 | 5.90k | reader.fill_buf()?; | 313 | 12.9M | } | 314 | 12.9M | match reader.buf_read_huffman(&codes.green.tree)? { | 315 | 12.9M | symbol @ 0..=255 => { | 316 | 11.8M | let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?; | 317 | 11.8M | log::debug!("color: {color}"); | 318 | 11.8M | fun(color)?; | 319 | 11.8M | if green_readahead_bits + arb_readahead_bits == 0 { | 320 | 1.18k | pixel_idx = len.get(); | 321 | 11.8M | } else { | 322 | 11.8M | pixel_idx += 1; | 323 | 11.8M | } | 324 | | } | 325 | 1.18M | symbol @ 256..=279 => { | 326 | 1.17M | let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?; | 327 | 1.17M | log::debug!("backref: {back_ref}"); | 328 | 59 | ensure_matches_attach!( | 329 | 1.17M | pixel_idx.checked_sub(back_ref.dist.get()), | 330 | | Some(_), | 331 | 59 | ParseError::InvalidInput, | 332 | 59 | InvalidBackRefDistance(back_ref.dist, pixel_idx), | 333 | | ); | 334 | 1.17M | ensure_attach!( | 335 | 1.17M | back_ref.len.get() <= len.get() - pixel_idx, | 336 | 10 | ParseError::InvalidInput, | 337 | 10 | InvalidBackRefLength(back_ref.len, pixel_idx, len.get()), | 338 | | ); | 339 | 1.17M | pixel_idx += back_ref.len.get(); | 340 | | } | 341 | 2.08k | symbol @ 280.. => { | 342 | 2.08k | let color_cache_index = symbol - 280; | 343 | 2.08k | log::debug!("cached: {color_cache_index}"); | 344 | 2.08k | ensure_attach!( | 345 | 2.08k | color_cache_index < color_cache.len(), | 346 | 0 | ParseError::InvalidInput, | 347 | 0 | ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()), | 348 | | ); | 349 | 2.08k | if green_readahead_bits == 0 { | 350 | 2 | pixel_idx = len.get(); | 351 | 2.08k | } else { | 352 | 2.08k | pixel_idx += 1; | 353 | 2.08k | } | 354 | | } | 355 | | } | 356 | | } | 357 | 1.59k | Ok(Self { width, height }) | 358 | 2.27k | } |
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#0}> Line | Count | Source | 295 | 852 | fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>( | 296 | 852 | reader: &mut BitBufReader<R, LE>, | 297 | 852 | width: NonZeroU32, | 298 | 852 | height: NonZeroU32, | 299 | 852 | mut fun: F, | 300 | 852 | ) -> Result<Self, Error> { | 301 | 852 | let color_cache = ColorCache::read(reader).while_parsing_type()?; | 302 | 840 | let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; | 303 | 572 | let green_readahead_bits = codes.green_readahead_bits(); | 304 | 572 | let arb_readahead_bits = codes.arb_readahead_bits(); | 305 | 572 | let backref_readahead_bits = codes.backref_readahead_bits(); | 306 | 572 | let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits); | 307 | | | 308 | 572 | let len = width.saturating_mul(height); | 309 | 572 | let mut pixel_idx = 0; | 310 | 9.65M | while pixel_idx < len.get() { | 311 | 9.65M | if reader.buf_bits() < u64::from(readahead_bits) { | 312 | 4.36k | reader.fill_buf()?; | 313 | 9.64M | } | 314 | 9.65M | match reader.buf_read_huffman(&codes.green.tree)? { | 315 | 9.64M | symbol @ 0..=255 => { | 316 | 5.15M | let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?; | 317 | 5.15M | log::debug!("color: {color}"); | 318 | 5.15M | fun(color)?; | 319 | 5.15M | if green_readahead_bits + arb_readahead_bits == 0 { | 320 | 114 | pixel_idx = len.get(); | 321 | 5.15M | } else { | 322 | 5.15M | pixel_idx += 1; | 323 | 5.15M | } | 324 | | } | 325 | 4.49M | symbol @ 256..=279 => { | 326 | 1.68M | let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?; | 327 | 1.68M | log::debug!("backref: {back_ref}"); | 328 | 51 | ensure_matches_attach!( | 329 | 1.68M | pixel_idx.checked_sub(back_ref.dist.get()), | 330 | | Some(_), | 331 | 51 | ParseError::InvalidInput, | 332 | 51 | InvalidBackRefDistance(back_ref.dist, pixel_idx), | 333 | | ); | 334 | 1.68M | ensure_attach!( | 335 | 1.68M | back_ref.len.get() <= len.get() - pixel_idx, | 336 | 19 | ParseError::InvalidInput, | 337 | 19 | InvalidBackRefLength(back_ref.len, pixel_idx, len.get()), | 338 | | ); | 339 | 1.68M | pixel_idx += back_ref.len.get(); | 340 | | } | 341 | 2.80M | symbol @ 280.. => { | 342 | 2.80M | let color_cache_index = symbol - 280; | 343 | 2.80M | log::debug!("cached: {color_cache_index}"); | 344 | 2.80M | ensure_attach!( | 345 | 2.80M | color_cache_index < color_cache.len(), | 346 | 0 | ParseError::InvalidInput, | 347 | 0 | ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()), | 348 | | ); | 349 | 2.80M | if green_readahead_bits == 0 { | 350 | 0 | pixel_idx = len.get(); | 351 | 2.80M | } else { | 352 | 2.80M | pixel_idx += 1; | 353 | 2.80M | } | 354 | | } | 355 | | } | 356 | | } | 357 | 189 | Ok(Self { width, height }) | 358 | 852 | } |
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#2}> Line | Count | Source | 295 | 1.06k | fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>( | 296 | 1.06k | reader: &mut BitBufReader<R, LE>, | 297 | 1.06k | width: NonZeroU32, | 298 | 1.06k | height: NonZeroU32, | 299 | 1.06k | mut fun: F, | 300 | 1.06k | ) -> Result<Self, Error> { | 301 | 1.06k | let color_cache = ColorCache::read(reader).while_parsing_type()?; | 302 | 1.03k | let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; | 303 | 920 | let green_readahead_bits = codes.green_readahead_bits(); | 304 | 920 | let arb_readahead_bits = codes.arb_readahead_bits(); | 305 | 920 | let backref_readahead_bits = codes.backref_readahead_bits(); | 306 | 920 | let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits); | 307 | | | 308 | 920 | let len = width.saturating_mul(height); | 309 | 920 | let mut pixel_idx = 0; | 310 | 123k | while pixel_idx < len.get() { | 311 | 122k | if reader.buf_bits() < u64::from(readahead_bits) { | 312 | 2.09k | reader.fill_buf()?; | 313 | 120k | } | 314 | 122k | match reader.buf_read_huffman(&codes.green.tree)? { | 315 | 122k | symbol @ 0..=255 => { | 316 | 121k | let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?; | 317 | 121k | log::debug!("color: {color}"); | 318 | 121k | fun(color)?; | 319 | 121k | if green_readahead_bits + arb_readahead_bits == 0 { | 320 | 96 | pixel_idx = len.get(); | 321 | 121k | } else { | 322 | 121k | pixel_idx += 1; | 323 | 121k | } | 324 | | } | 325 | 1.38k | symbol @ 256..=279 => { | 326 | 606 | let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?; | 327 | 604 | log::debug!("backref: {back_ref}"); | 328 | 8 | ensure_matches_attach!( | 329 | 604 | pixel_idx.checked_sub(back_ref.dist.get()), | 330 | | Some(_), | 331 | 8 | ParseError::InvalidInput, | 332 | 8 | InvalidBackRefDistance(back_ref.dist, pixel_idx), | 333 | | ); | 334 | 596 | ensure_attach!( | 335 | 596 | back_ref.len.get() <= len.get() - pixel_idx, | 336 | 21 | ParseError::InvalidInput, | 337 | 21 | InvalidBackRefLength(back_ref.len, pixel_idx, len.get()), | 338 | | ); | 339 | 575 | pixel_idx += back_ref.len.get(); | 340 | | } | 341 | 781 | symbol @ 280.. => { | 342 | 781 | let color_cache_index = symbol - 280; | 343 | 781 | log::debug!("cached: {color_cache_index}"); | 344 | 781 | ensure_attach!( | 345 | 781 | color_cache_index < color_cache.len(), | 346 | 0 | ParseError::InvalidInput, | 347 | 0 | ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()), | 348 | | ); | 349 | 781 | if green_readahead_bits == 0 { | 350 | 0 | pixel_idx = len.get(); | 351 | 781 | } else { | 352 | 781 | pixel_idx += 1; | 353 | 781 | } | 354 | | } | 355 | | } | 356 | | } | 357 | 770 | Ok(Self { width, height }) | 358 | 1.06k | } |
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#1}> Line | Count | Source | 295 | 778 | fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>( | 296 | 778 | reader: &mut BitBufReader<R, LE>, | 297 | 778 | width: NonZeroU32, | 298 | 778 | height: NonZeroU32, | 299 | 778 | mut fun: F, | 300 | 778 | ) -> Result<Self, Error> { | 301 | 778 | let color_cache = ColorCache::read(reader).while_parsing_type()?; | 302 | 748 | let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; | 303 | 590 | let green_readahead_bits = codes.green_readahead_bits(); | 304 | 590 | let arb_readahead_bits = codes.arb_readahead_bits(); | 305 | 590 | let backref_readahead_bits = codes.backref_readahead_bits(); | 306 | 590 | let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits); | 307 | | | 308 | 590 | let len = width.saturating_mul(height); | 309 | 590 | let mut pixel_idx = 0; | 310 | 21.7M | while pixel_idx < len.get() { | 311 | 21.7M | if reader.buf_bits() < u64::from(readahead_bits) { | 312 | 5.87k | reader.fill_buf()?; | 313 | 21.7M | } | 314 | 21.7M | match reader.buf_read_huffman(&codes.green.tree)? { | 315 | 21.7M | symbol @ 0..=255 => { | 316 | 21.2M | let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?; | 317 | 21.2M | log::debug!("color: {color}"); | 318 | 21.2M | fun(color)?; | 319 | 21.2M | if green_readahead_bits + arb_readahead_bits == 0 { | 320 | 117 | pixel_idx = len.get(); | 321 | 21.2M | } else { | 322 | 21.2M | pixel_idx += 1; | 323 | 21.2M | } | 324 | | } | 325 | 544k | symbol @ 256..=279 => { | 326 | 539k | let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?; | 327 | 539k | log::debug!("backref: {back_ref}"); | 328 | 30 | ensure_matches_attach!( | 329 | 539k | pixel_idx.checked_sub(back_ref.dist.get()), | 330 | | Some(_), | 331 | 30 | ParseError::InvalidInput, | 332 | 30 | InvalidBackRefDistance(back_ref.dist, pixel_idx), | 333 | | ); | 334 | 539k | ensure_attach!( | 335 | 539k | back_ref.len.get() <= len.get() - pixel_idx, | 336 | 30 | ParseError::InvalidInput, | 337 | 30 | InvalidBackRefLength(back_ref.len, pixel_idx, len.get()), | 338 | | ); | 339 | 539k | pixel_idx += back_ref.len.get(); | 340 | | } | 341 | 4.34k | symbol @ 280.. => { | 342 | 4.34k | let color_cache_index = symbol - 280; | 343 | 4.34k | log::debug!("cached: {color_cache_index}"); | 344 | 4.34k | ensure_attach!( | 345 | 4.34k | color_cache_index < color_cache.len(), | 346 | 0 | ParseError::InvalidInput, | 347 | 0 | ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()), | 348 | | ); | 349 | 4.34k | if green_readahead_bits == 0 { | 350 | 0 | pixel_idx = len.get(); | 351 | 4.34k | } else { | 352 | 4.34k | pixel_idx += 1; | 353 | 4.34k | } | 354 | | } | 355 | | } | 356 | | } | 357 | 197 | Ok(Self { width, height }) | 358 | 778 | } |
|
359 | | } |
360 | | |
361 | | // |
362 | | // SpatiallyCodedImage impls |
363 | | // |
364 | | |
365 | | impl SpatiallyCodedImage { |
366 | 3.93k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> { |
367 | 3.93k | let color_cache = ColorCache::read(reader).while_parsing_type()?; |
368 | 3.91k | let meta = MetaPrefixCodes::read(reader, width, height).while_parsing_type()?; |
369 | 3.21k | log::info!("{meta}"); |
370 | | |
371 | 3.21k | for _ in 0..=meta.max_code_group() { |
372 | 207k | let _codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?; |
373 | | } |
374 | 597 | Ok(Self) |
375 | 3.93k | } |
376 | | } |
377 | | |
378 | | // |
379 | | // BackReference impls |
380 | | // |
381 | | |
382 | | impl BackReference { |
383 | | #[rustfmt::skip] |
384 | | const DISTANCE_MAP: [(i8, u8); 120] = [ |
385 | | (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), |
386 | | (-1, 2), (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), |
387 | | (1, 3), (-1, 3), (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), |
388 | | (-3, 2), (0, 4), (4, 0), (1, 4), (-1, 4), (4, 1), (-4, 1), |
389 | | (3, 3), (-3, 3), (2, 4), (-2, 4), (4, 2), (-4, 2), (0, 5), |
390 | | (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), (1, 5), (-1, 5), |
391 | | (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), (4, 4), |
392 | | (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), |
393 | | (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), |
394 | | (-6, 2), (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), |
395 | | (6, 3), (-6, 3), (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), |
396 | | (-5, 5), (7, 1), (-7, 1), (4, 6), (-4, 6), (6, 4), (-6, 4), |
397 | | (2, 7), (-2, 7), (7, 2), (-7, 2), (3, 7), (-3, 7), (7, 3), |
398 | | (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), (8, 0), (4, 7), |
399 | | (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), (-6, 6), |
400 | | (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), |
401 | | (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), |
402 | | (8, 7) |
403 | | ]; |
404 | | const DISTANCE_MAP_LEN: u32 = Self::DISTANCE_MAP.len() as u32; |
405 | | |
406 | 3.40M | fn buf_read<R: Read>( |
407 | 3.40M | reader: &mut BitBufReader<R, LE>, |
408 | 3.40M | len_symbol: u16, |
409 | 3.40M | codes: &PrefixCodeGroup, |
410 | 3.40M | width: NonZeroU32, |
411 | 3.40M | ) -> Result<Self, Error> { |
412 | 3.40M | let len = reader.buf_read_lz77(len_symbol)?; |
413 | 3.40M | let dist_symbol = reader.buf_read_huffman(&codes.distance.tree)?; |
414 | 3.40M | let dist_code = reader.buf_read_lz77(dist_symbol.into())?; |
415 | 3.40M | let dist = match dist_code.get() { |
416 | 0 | 0 => unreachable!(), |
417 | 3.40M | dist_code @ 1..=Self::DISTANCE_MAP_LEN => { |
418 | 3.38M | let (dx, dy) = Self::DISTANCE_MAP[dist_code as usize - 1]; |
419 | 3.38M | (u32::from(dy) * u32::from(width)) |
420 | 3.38M | .checked_add_signed(dx.into()) |
421 | 3.38M | .and_then(NonZeroU32::new) |
422 | 3.38M | .unwrap_or(NonZeroU32::MIN) |
423 | | } |
424 | 24.2k | _ => NonZeroU32::new(dist_code.get() - Self::DISTANCE_MAP_LEN).unwrap_or_else(|| unreachable!()), |
425 | | }; |
426 | 3.40M | Ok(Self { dist, len }) |
427 | 3.40M | } |
428 | | |
429 | 4.09k | fn readahead_bits(codes: &PrefixCodeGroup) -> u32 { |
430 | 4.09k | 2 * u32::from(LZ77_MAX_LEN) + codes.distance.tree.longest_code_len() |
431 | 4.09k | } |
432 | | } |
433 | | |
434 | | // |
435 | | // Color impls |
436 | | // |
437 | | |
438 | | impl Color { |
439 | 38.3M | fn buf_read<R: Read>(reader: &mut BitBufReader<R, LE>, green: u8, codes: &PrefixCodeGroup) -> Result<Self, Error> { |
440 | | Ok(Self { |
441 | 38.3M | green, |
442 | 38.3M | red: reader.buf_read_huffman(&codes.red.tree)?, |
443 | 38.3M | blue: reader.buf_read_huffman(&codes.blue.tree)?, |
444 | 38.3M | alpha: reader.buf_read_huffman(&codes.alpha.tree)?, |
445 | | }) |
446 | 38.3M | } |
447 | | } |
448 | | |
449 | | impl From<Color> for u32 { |
450 | 0 | fn from(color: Color) -> Self { |
451 | 0 | (color.alpha as u32) << 24 | (color.red as u32) << 16 | (color.green as u32) << 8 | color.blue as u32 |
452 | 0 | } |
453 | | } |
454 | | |
455 | | // |
456 | | // ColorCache impls |
457 | | // |
458 | | |
459 | | impl ColorCache { |
460 | 8.90k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> { |
461 | 8.90k | let has_color_cache = reader.read_bit()?; |
462 | 8.88k | if has_color_cache { |
463 | 2.52k | let order = reader.read::<u8>(4)?; |
464 | 2.47k | ensure_attach!(order <= 11, ParseError::InvalidInput, InvalidColorCacheSize(order)); |
465 | 9 | ensure_matches_attach!( |
466 | 2.44k | NonZeroU8::new(order), |
467 | 2.43k | Some(order), |
468 | 9 | ParseError::InvalidInput, |
469 | 9 | InvalidColorCacheSize(order), |
470 | | ); |
471 | 2.43k | Ok(Self { order: Some(order) }) |
472 | | } else { |
473 | 6.36k | Ok(Self { order: None }) |
474 | | } |
475 | 8.90k | } |
476 | | |
477 | 2.98M | fn len(&self) -> u16 { |
478 | 2.98M | self.order.map(|order| 2u16.pow(order.get().into())).unwrap_or_default() |
479 | 2.98M | } |
480 | | } |
481 | | |
482 | | // |
483 | | // MetaPrefixCodes impls |
484 | | // |
485 | | |
486 | | impl MetaPrefixCodes { |
487 | 3.91k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> { |
488 | 3.91k | let has_meta = reader.read_bit()?; |
489 | 3.90k | if has_meta { |
490 | 2.29k | let block_order = 2 + reader.read::<u32>(3)?; |
491 | 2.27k | let block_size = 2u16.pow(block_order); |
492 | 2.27k | let width_in_blocks = len_in_blocks(width, block_size); |
493 | 2.27k | let height_in_blocks = len_in_blocks(height, block_size); |
494 | 2.27k | let mut max_code_group = 0; |
495 | 11.8M | let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |color| { |
496 | 11.8M | max_code_group = max_code_group.max(u16::from(color.red) << 8 | u16::from(color.green)); |
497 | 11.8M | Ok(()) |
498 | 11.8M | }) |
499 | 2.27k | .while_parsing_type()?; |
500 | 1.59k | Ok(Self::Multiple { block_size, max_code_group, _image }) |
501 | | } else { |
502 | 1.61k | Ok(Self::Single) |
503 | | } |
504 | 3.91k | } |
505 | | |
506 | 3.21k | fn max_code_group(&self) -> u16 { |
507 | 3.21k | match self { |
508 | 1.61k | MetaPrefixCodes::Single => 0, |
509 | 1.59k | &MetaPrefixCodes::Multiple { max_code_group, .. } => max_code_group, |
510 | | } |
511 | 3.21k | } |
512 | | } |
513 | | |
514 | | // |
515 | | // PrefixCodeGroup impls |
516 | | // |
517 | | |
518 | | impl PrefixCodeGroup { |
519 | 212k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>, color_cache: &ColorCache) -> Result<Self, Error> { |
520 | 212k | let green = Self::read_prefix_code(reader, color_cache).while_parsing_type()?; |
521 | 211k | let red = Self::read_prefix_code(reader, color_cache).while_parsing_type()?; |
522 | 210k | let blue = Self::read_prefix_code(reader, color_cache).while_parsing_type()?; |
523 | 209k | let alpha = Self::read_prefix_code(reader, color_cache).while_parsing_type()?; |
524 | 209k | let distance = Self::read_prefix_code(reader, color_cache).while_parsing_type()?; |
525 | 208k | Ok(Self { green, red, blue, alpha, distance }) |
526 | 212k | } |
527 | | |
528 | 1.05M | fn read_prefix_code<R: Read, T: PrefixCode>( |
529 | 1.05M | reader: &mut BitBufReader<R, LE>, |
530 | 1.05M | color_cache: &ColorCache, |
531 | 1.05M | ) -> Result<T, Error> |
532 | 1.05M | where |
533 | 1.05M | usize: AsPrimitive<T::Symbol>, |
534 | 1.05M | T::Symbol: Copy + Ord + 'static, |
535 | | { |
536 | 1.05M | let simple_code_length_code = reader.read_bit()?; |
537 | 1.05M | let tree = if simple_code_length_code { |
538 | 877k | let has_second_symbol = reader.read_bit()?; |
539 | | |
540 | 877k | let is_first_symbol_8bits = reader.read_bit()?; |
541 | 876k | let first_symbol = if is_first_symbol_8bits { |
542 | 69.4k | reader.read(8)? |
543 | | } else { |
544 | 807k | Numeric::from_u8(reader.read_bit()? as u8) |
545 | | }; |
546 | 876k | let symbols = if has_second_symbol { |
547 | 332k | let second_symbol = reader.read(8)?; |
548 | 332k | vec![(first_symbol, vec![0]), (second_symbol, vec![1])] |
549 | | } else { |
550 | 544k | vec![(first_symbol, vec![])] |
551 | | }; |
552 | 876k | CanonicalHuffmanTree::from_symbols(symbols)? |
553 | | } else { |
554 | 175k | let code_length_code = CodeLengthPrefixCode::read(reader)?; |
555 | | |
556 | 174k | let max_symbol_count = T::alphabet_size(color_cache.len()); |
557 | 174k | let max_symbol_reads = if reader.read_bit()? { |
558 | 169k | let length_bit_len = 2 + 2 * reader.read::<u32>(3)?; |
559 | 169k | log::debug!("length_bit_len: {length_bit_len:?}"); |
560 | 169k | 2u16.saturating_add(reader.read(length_bit_len)?) |
561 | | } else { |
562 | 4.91k | max_symbol_count |
563 | | }; |
564 | 174k | log::debug!("max_symbol_count: {max_symbol_count:?}"); |
565 | 174k | log::debug!("max_symbol_reads: {max_symbol_reads:?}"); |
566 | | |
567 | 174k | ensure_attach!( |
568 | 174k | max_symbol_reads <= max_symbol_count, |
569 | 111 | ParseError::InvalidInput, |
570 | 111 | InvalidSymbolCount(max_symbol_reads, max_symbol_count), |
571 | | ); |
572 | | |
573 | 173k | let mut code_lengths = Vec::with_capacity(max_symbol_count as usize); |
574 | 173k | let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!()); Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode>::{closure#0} Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode>::{closure#0} Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode>::{closure#0} |
575 | 173k | for _ in 0..max_symbol_reads { |
576 | 1.06M | if code_lengths.len() == max_symbol_count.into() { |
577 | 5.47k | break; |
578 | 1.05M | } |
579 | | |
580 | 1.05M | let code_length_code = reader.read_huffman(&code_length_code.tree)?; |
581 | 1.05M | let (code_length, repeat_times) = match code_length_code { |
582 | 1.05M | 0..=15 => (code_length_code, 1), |
583 | 63.4k | 16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?), |
584 | 78.0k | 17 => (0, 3 + reader.read::<u8>(3)?), |
585 | 50.5k | 18 => (0, 11 + reader.read::<u8>(7)?), |
586 | 0 | 19.. => unreachable!(), |
587 | | }; |
588 | 1.05M | if let Some(non_zero_code_length) = NonZeroU8::new(code_length) { |
589 | 785k | last_non_zero_code_length = non_zero_code_length; |
590 | 785k | } |
591 | | |
592 | 1.05M | let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times); |
593 | 1.05M | ensure_attach!( |
594 | 1.05M | new_code_lengths_len <= usize::from(max_symbol_count), |
595 | 93 | ParseError::InvalidVp8lPrefixCode, |
596 | 93 | InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count) |
597 | | ); |
598 | 1.05M | let new_code_lengths = |
599 | 5.87M | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode>::{closure#1} Line | Count | Source | 599 | 3.21M | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); |
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode>::{closure#1} Line | Count | Source | 599 | 2.40M | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); |
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode>::{closure#1} Line | Count | Source | 599 | 256k | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); |
|
600 | 1.05M | code_lengths.extend(new_code_lengths); |
601 | | } |
602 | | |
603 | 173k | log::debug!("code_lengths: {code_lengths:?}"); |
604 | 173k | CanonicalHuffmanTree::new(&mut code_lengths)? |
605 | | }; |
606 | 1.04M | Ok(T::new(tree)) |
607 | 1.05M | } <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode> Line | Count | Source | 528 | 630k | fn read_prefix_code<R: Read, T: PrefixCode>( | 529 | 630k | reader: &mut BitBufReader<R, LE>, | 530 | 630k | color_cache: &ColorCache, | 531 | 630k | ) -> Result<T, Error> | 532 | 630k | where | 533 | 630k | usize: AsPrimitive<T::Symbol>, | 534 | 630k | T::Symbol: Copy + Ord + 'static, | 535 | | { | 536 | 630k | let simple_code_length_code = reader.read_bit()?; | 537 | 630k | let tree = if simple_code_length_code { | 538 | 527k | let has_second_symbol = reader.read_bit()?; | 539 | | | 540 | 527k | let is_first_symbol_8bits = reader.read_bit()?; | 541 | 527k | let first_symbol = if is_first_symbol_8bits { | 542 | 40.3k | reader.read(8)? | 543 | | } else { | 544 | 487k | Numeric::from_u8(reader.read_bit()? as u8) | 545 | | }; | 546 | 527k | let symbols = if has_second_symbol { | 547 | 199k | let second_symbol = reader.read(8)?; | 548 | 199k | vec![(first_symbol, vec![0]), (second_symbol, vec![1])] | 549 | | } else { | 550 | 328k | vec![(first_symbol, vec![])] | 551 | | }; | 552 | 527k | CanonicalHuffmanTree::from_symbols(symbols)? | 553 | | } else { | 554 | 102k | let code_length_code = CodeLengthPrefixCode::read(reader)?; | 555 | | | 556 | 102k | let max_symbol_count = T::alphabet_size(color_cache.len()); | 557 | 102k | let max_symbol_reads = if reader.read_bit()? { | 558 | 100k | let length_bit_len = 2 + 2 * reader.read::<u32>(3)?; | 559 | 100k | log::debug!("length_bit_len: {length_bit_len:?}"); | 560 | 100k | 2u16.saturating_add(reader.read(length_bit_len)?) | 561 | | } else { | 562 | 2.10k | max_symbol_count | 563 | | }; | 564 | 102k | log::debug!("max_symbol_count: {max_symbol_count:?}"); | 565 | 102k | log::debug!("max_symbol_reads: {max_symbol_reads:?}"); | 566 | | | 567 | 102k | ensure_attach!( | 568 | 102k | max_symbol_reads <= max_symbol_count, | 569 | 51 | ParseError::InvalidInput, | 570 | 51 | InvalidSymbolCount(max_symbol_reads, max_symbol_count), | 571 | | ); | 572 | | | 573 | 102k | let mut code_lengths = Vec::with_capacity(max_symbol_count as usize); | 574 | 102k | let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!()); | 575 | 102k | for _ in 0..max_symbol_reads { | 576 | 548k | if code_lengths.len() == max_symbol_count.into() { | 577 | 2.02k | break; | 578 | 546k | } | 579 | | | 580 | 546k | let code_length_code = reader.read_huffman(&code_length_code.tree)?; | 581 | 546k | let (code_length, repeat_times) = match code_length_code { | 582 | 546k | 0..=15 => (code_length_code, 1), | 583 | 31.3k | 16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?), | 584 | 41.9k | 17 => (0, 3 + reader.read::<u8>(3)?), | 585 | 28.3k | 18 => (0, 11 + reader.read::<u8>(7)?), | 586 | 0 | 19.. => unreachable!(), | 587 | | }; | 588 | 546k | if let Some(non_zero_code_length) = NonZeroU8::new(code_length) { | 589 | 400k | last_non_zero_code_length = non_zero_code_length; | 590 | 400k | } | 591 | | | 592 | 546k | let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times); | 593 | 546k | ensure_attach!( | 594 | 546k | new_code_lengths_len <= usize::from(max_symbol_count), | 595 | 31 | ParseError::InvalidVp8lPrefixCode, | 596 | 31 | InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count) | 597 | | ); | 598 | 546k | let new_code_lengths = | 599 | 546k | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); | 600 | 546k | code_lengths.extend(new_code_lengths); | 601 | | } | 602 | | | 603 | 102k | log::debug!("code_lengths: {code_lengths:?}"); | 604 | 102k | CanonicalHuffmanTree::new(&mut code_lengths)? | 605 | | }; | 606 | 629k | Ok(T::new(tree)) | 607 | 630k | } |
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode> Line | Count | Source | 528 | 212k | fn read_prefix_code<R: Read, T: PrefixCode>( | 529 | 212k | reader: &mut BitBufReader<R, LE>, | 530 | 212k | color_cache: &ColorCache, | 531 | 212k | ) -> Result<T, Error> | 532 | 212k | where | 533 | 212k | usize: AsPrimitive<T::Symbol>, | 534 | 212k | T::Symbol: Copy + Ord + 'static, | 535 | | { | 536 | 212k | let simple_code_length_code = reader.read_bit()?; | 537 | 212k | let tree = if simple_code_length_code { | 538 | 172k | let has_second_symbol = reader.read_bit()?; | 539 | | | 540 | 172k | let is_first_symbol_8bits = reader.read_bit()?; | 541 | 172k | let first_symbol = if is_first_symbol_8bits { | 542 | 12.0k | reader.read(8)? | 543 | | } else { | 544 | 160k | Numeric::from_u8(reader.read_bit()? as u8) | 545 | | }; | 546 | 172k | let symbols = if has_second_symbol { | 547 | 67.1k | let second_symbol = reader.read(8)?; | 548 | 67.0k | vec![(first_symbol, vec![0]), (second_symbol, vec![1])] | 549 | | } else { | 550 | 105k | vec![(first_symbol, vec![])] | 551 | | }; | 552 | 172k | CanonicalHuffmanTree::from_symbols(symbols)? | 553 | | } else { | 554 | 40.0k | let code_length_code = CodeLengthPrefixCode::read(reader)?; | 555 | | | 556 | 39.7k | let max_symbol_count = T::alphabet_size(color_cache.len()); | 557 | 39.7k | let max_symbol_reads = if reader.read_bit()? { | 558 | 37.3k | let length_bit_len = 2 + 2 * reader.read::<u32>(3)?; | 559 | 37.3k | log::debug!("length_bit_len: {length_bit_len:?}"); | 560 | 37.3k | 2u16.saturating_add(reader.read(length_bit_len)?) | 561 | | } else { | 562 | 2.37k | max_symbol_count | 563 | | }; | 564 | 39.6k | log::debug!("max_symbol_count: {max_symbol_count:?}"); | 565 | 39.6k | log::debug!("max_symbol_reads: {max_symbol_reads:?}"); | 566 | | | 567 | 39.6k | ensure_attach!( | 568 | 39.6k | max_symbol_reads <= max_symbol_count, | 569 | 25 | ParseError::InvalidInput, | 570 | 25 | InvalidSymbolCount(max_symbol_reads, max_symbol_count), | 571 | | ); | 572 | | | 573 | 39.6k | let mut code_lengths = Vec::with_capacity(max_symbol_count as usize); | 574 | 39.6k | let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!()); | 575 | 39.6k | for _ in 0..max_symbol_reads { | 576 | 372k | if code_lengths.len() == max_symbol_count.into() { | 577 | 2.11k | break; | 578 | 370k | } | 579 | | | 580 | 370k | let code_length_code = reader.read_huffman(&code_length_code.tree)?; | 581 | 370k | let (code_length, repeat_times) = match code_length_code { | 582 | 370k | 0..=15 => (code_length_code, 1), | 583 | 32.0k | 16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?), | 584 | 26.1k | 17 => (0, 3 + reader.read::<u8>(3)?), | 585 | 20.4k | 18 => (0, 11 + reader.read::<u8>(7)?), | 586 | 0 | 19.. => unreachable!(), | 587 | | }; | 588 | 369k | if let Some(non_zero_code_length) = NonZeroU8::new(code_length) { | 589 | 281k | last_non_zero_code_length = non_zero_code_length; | 590 | 281k | } | 591 | | | 592 | 369k | let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times); | 593 | 369k | ensure_attach!( | 594 | 369k | new_code_lengths_len <= usize::from(max_symbol_count), | 595 | 23 | ParseError::InvalidVp8lPrefixCode, | 596 | 23 | InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count) | 597 | | ); | 598 | 369k | let new_code_lengths = | 599 | 369k | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); | 600 | 369k | code_lengths.extend(new_code_lengths); | 601 | | } | 602 | | | 603 | 39.4k | log::debug!("code_lengths: {code_lengths:?}"); | 604 | 39.4k | CanonicalHuffmanTree::new(&mut code_lengths)? | 605 | | }; | 606 | 211k | Ok(T::new(tree)) | 607 | 212k | } |
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode> Line | Count | Source | 528 | 209k | fn read_prefix_code<R: Read, T: PrefixCode>( | 529 | 209k | reader: &mut BitBufReader<R, LE>, | 530 | 209k | color_cache: &ColorCache, | 531 | 209k | ) -> Result<T, Error> | 532 | 209k | where | 533 | 209k | usize: AsPrimitive<T::Symbol>, | 534 | 209k | T::Symbol: Copy + Ord + 'static, | 535 | | { | 536 | 209k | let simple_code_length_code = reader.read_bit()?; | 537 | 209k | let tree = if simple_code_length_code { | 538 | 177k | let has_second_symbol = reader.read_bit()?; | 539 | | | 540 | 177k | let is_first_symbol_8bits = reader.read_bit()?; | 541 | 177k | let first_symbol = if is_first_symbol_8bits { | 542 | 16.9k | reader.read(8)? | 543 | | } else { | 544 | 160k | Numeric::from_u8(reader.read_bit()? as u8) | 545 | | }; | 546 | 177k | let symbols = if has_second_symbol { | 547 | 65.8k | let second_symbol = reader.read(8)?; | 548 | 65.8k | vec![(first_symbol, vec![0]), (second_symbol, vec![1])] | 549 | | } else { | 550 | 111k | vec![(first_symbol, vec![])] | 551 | | }; | 552 | 177k | CanonicalHuffmanTree::from_symbols(symbols)? | 553 | | } else { | 554 | 32.0k | let code_length_code = CodeLengthPrefixCode::read(reader)?; | 555 | | | 556 | 31.9k | let max_symbol_count = T::alphabet_size(color_cache.len()); | 557 | 31.9k | let max_symbol_reads = if reader.read_bit()? { | 558 | 31.5k | let length_bit_len = 2 + 2 * reader.read::<u32>(3)?; | 559 | 31.5k | log::debug!("length_bit_len: {length_bit_len:?}"); | 560 | 31.5k | 2u16.saturating_add(reader.read(length_bit_len)?) | 561 | | } else { | 562 | 430 | max_symbol_count | 563 | | }; | 564 | 31.8k | log::debug!("max_symbol_count: {max_symbol_count:?}"); | 565 | 31.8k | log::debug!("max_symbol_reads: {max_symbol_reads:?}"); | 566 | | | 567 | 31.8k | ensure_attach!( | 568 | 31.8k | max_symbol_reads <= max_symbol_count, | 569 | 35 | ParseError::InvalidInput, | 570 | 35 | InvalidSymbolCount(max_symbol_reads, max_symbol_count), | 571 | | ); | 572 | | | 573 | 31.8k | let mut code_lengths = Vec::with_capacity(max_symbol_count as usize); | 574 | 31.8k | let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!()); | 575 | 31.8k | for _ in 0..max_symbol_reads { | 576 | 142k | if code_lengths.len() == max_symbol_count.into() { | 577 | 1.32k | break; | 578 | 141k | } | 579 | | | 580 | 141k | let code_length_code = reader.read_huffman(&code_length_code.tree)?; | 581 | 141k | let (code_length, repeat_times) = match code_length_code { | 582 | 141k | 0..=15 => (code_length_code, 1), | 583 | 78 | 16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?), | 584 | 9.97k | 17 => (0, 3 + reader.read::<u8>(3)?), | 585 | 1.72k | 18 => (0, 11 + reader.read::<u8>(7)?), | 586 | 0 | 19.. => unreachable!(), | 587 | | }; | 588 | 141k | if let Some(non_zero_code_length) = NonZeroU8::new(code_length) { | 589 | 104k | last_non_zero_code_length = non_zero_code_length; | 590 | 104k | } | 591 | | | 592 | 141k | let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times); | 593 | 141k | ensure_attach!( | 594 | 141k | new_code_lengths_len <= usize::from(max_symbol_count), | 595 | 39 | ParseError::InvalidVp8lPrefixCode, | 596 | 39 | InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count) | 597 | | ); | 598 | 141k | let new_code_lengths = | 599 | 141k | (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length)); | 600 | 141k | code_lengths.extend(new_code_lengths); | 601 | | } | 602 | | | 603 | 31.7k | log::debug!("code_lengths: {code_lengths:?}"); | 604 | 31.7k | CanonicalHuffmanTree::new(&mut code_lengths)? | 605 | | }; | 606 | 208k | Ok(T::new(tree)) | 607 | 209k | } |
|
608 | | |
609 | 4.09k | pub fn green_readahead_bits(&self) -> u32 { |
610 | 4.09k | self.green.tree.longest_code_len() |
611 | 4.09k | } |
612 | | |
613 | 4.09k | pub fn arb_readahead_bits(&self) -> u32 { |
614 | 4.09k | self.alpha.tree.longest_code_len() + self.red.tree.longest_code_len() + self.blue.tree.longest_code_len() |
615 | 4.09k | } |
616 | | |
617 | 4.09k | pub fn backref_readahead_bits(&self) -> u32 { |
618 | 4.09k | self.green.tree.longest_code_len() + BackReference::readahead_bits(self) |
619 | 4.09k | } |
620 | | } |
621 | | |
622 | | // |
623 | | // CodeLengthPrefixCode impls |
624 | | // |
625 | | |
626 | | impl CodeLengthPrefixCode { |
627 | 175k | fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> { |
628 | | const CODE_ORDER: [u8; 19] = [17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; |
629 | | |
630 | 175k | let code_length_count = 4 + usize::from(reader.read::<u8>(4)?); |
631 | | |
632 | 174k | let mut code_lengths = [Default::default(); CODE_ORDER.len()]; |
633 | 174k | let mut code_order_iter = CODE_ORDER.iter(); |
634 | 896k | for &code_length_idx in code_order_iter.by_ref().take(code_length_count) { |
635 | 896k | code_lengths[usize::from(code_length_idx)] = (code_length_idx, reader.read(3)?); |
636 | | } |
637 | 2.59M | for &code_length_idx in code_order_iter { |
638 | 2.42M | code_lengths[usize::from(code_length_idx)] = (code_length_idx, 0); |
639 | 2.42M | } |
640 | | |
641 | 174k | let tree = CanonicalHuffmanTree::new(&mut code_lengths).attach_printable("while parsing code length code")?; |
642 | 174k | Ok(Self { tree }) |
643 | 175k | } |
644 | | } |
645 | | |
646 | | // |
647 | | // GreenPrefixCode impls |
648 | | // |
649 | | |
650 | | impl PrefixCode for GreenPrefixCode { |
651 | | type Symbol = u16; |
652 | | |
653 | 211k | fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self { |
654 | 211k | Self { tree } |
655 | 211k | } |
656 | | |
657 | 39.7k | fn alphabet_size(color_cache_len: u16) -> u16 { |
658 | 39.7k | 256 + 24 + color_cache_len |
659 | 39.7k | } |
660 | | } |
661 | | |
662 | | // |
663 | | // ARBPrefixCode impls |
664 | | // |
665 | | |
666 | | impl PrefixCode for ARBPrefixCode { |
667 | | type Symbol = u8; |
668 | | |
669 | 629k | fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self { |
670 | 629k | Self { tree } |
671 | 629k | } |
672 | | |
673 | 102k | fn alphabet_size(_color_cache_len: u16) -> u16 { |
674 | 102k | 256 |
675 | 102k | } |
676 | | } |
677 | | |
678 | | // |
679 | | // DistancePrefixCode impls |
680 | | // |
681 | | |
682 | | impl PrefixCode for DistancePrefixCode { |
683 | | type Symbol = u8; |
684 | | |
685 | 208k | fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self { |
686 | 208k | Self { tree } |
687 | 208k | } |
688 | | |
689 | 31.9k | fn alphabet_size(_color_cache_len: u16) -> u16 { |
690 | 31.9k | 40 |
691 | 31.9k | } |
692 | | } |
693 | | |
694 | | // |
695 | | // private functions |
696 | | // |
697 | | |
698 | 8.58k | fn len_in_blocks(len: NonZeroU32, block_size: u16) -> NonZeroU32 { |
699 | 8.58k | NonZeroU32::new(div_ceil(len.get(), block_size.into())).unwrap_or_else(|| unreachable!()) |
700 | 8.58k | } |