/rust/registry/src/index.crates.io-1949cf8c6b5b557f/image-webp-0.2.4/src/lossless.rs
Line | Count | Source |
1 | | //! Decoding of lossless WebP images |
2 | | //! |
3 | | //! [Lossless spec](https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification) |
4 | | |
5 | | use std::io::BufRead; |
6 | | use std::mem; |
7 | | |
8 | | use crate::decoder::DecodingError; |
9 | | use crate::lossless_transform::{ |
10 | | apply_color_indexing_transform, apply_color_transform, apply_predictor_transform, |
11 | | apply_subtract_green_transform, |
12 | | }; |
13 | | |
14 | | use super::huffman::HuffmanTree; |
15 | | use super::lossless_transform::TransformType; |
16 | | |
17 | | const CODE_LENGTH_CODES: usize = 19; |
18 | | const CODE_LENGTH_CODE_ORDER: [usize; CODE_LENGTH_CODES] = [ |
19 | | 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
20 | | ]; |
21 | | |
22 | | #[rustfmt::skip] |
23 | | const DISTANCE_MAP: [(i8, i8); 120] = [ |
24 | | (0, 1), (1, 0), (1, 1), (-1, 1), (0, 2), (2, 0), (1, 2), (-1, 2), |
25 | | (2, 1), (-2, 1), (2, 2), (-2, 2), (0, 3), (3, 0), (1, 3), (-1, 3), |
26 | | (3, 1), (-3, 1), (2, 3), (-2, 3), (3, 2), (-3, 2), (0, 4), (4, 0), |
27 | | (1, 4), (-1, 4), (4, 1), (-4, 1), (3, 3), (-3, 3), (2, 4), (-2, 4), |
28 | | (4, 2), (-4, 2), (0, 5), (3, 4), (-3, 4), (4, 3), (-4, 3), (5, 0), |
29 | | (1, 5), (-1, 5), (5, 1), (-5, 1), (2, 5), (-2, 5), (5, 2), (-5, 2), |
30 | | (4, 4), (-4, 4), (3, 5), (-3, 5), (5, 3), (-5, 3), (0, 6), (6, 0), |
31 | | (1, 6), (-1, 6), (6, 1), (-6, 1), (2, 6), (-2, 6), (6, 2), (-6, 2), |
32 | | (4, 5), (-4, 5), (5, 4), (-5, 4), (3, 6), (-3, 6), (6, 3), (-6, 3), |
33 | | (0, 7), (7, 0), (1, 7), (-1, 7), (5, 5), (-5, 5), (7, 1), (-7, 1), |
34 | | (4, 6), (-4, 6), (6, 4), (-6, 4), (2, 7), (-2, 7), (7, 2), (-7, 2), |
35 | | (3, 7), (-3, 7), (7, 3), (-7, 3), (5, 6), (-5, 6), (6, 5), (-6, 5), |
36 | | (8, 0), (4, 7), (-4, 7), (7, 4), (-7, 4), (8, 1), (8, 2), (6, 6), |
37 | | (-6, 6), (8, 3), (5, 7), (-5, 7), (7, 5), (-7, 5), (8, 4), (6, 7), |
38 | | (-6, 7), (7, 6), (-7, 6), (8, 5), (7, 7), (-7, 7), (8, 6), (8, 7) |
39 | | ]; |
40 | | |
41 | | const GREEN: usize = 0; |
42 | | const RED: usize = 1; |
43 | | const BLUE: usize = 2; |
44 | | const ALPHA: usize = 3; |
45 | | const DIST: usize = 4; |
46 | | |
47 | | const HUFFMAN_CODES_PER_META_CODE: usize = 5; |
48 | | |
49 | | type HuffmanCodeGroup = [HuffmanTree; HUFFMAN_CODES_PER_META_CODE]; |
50 | | |
51 | | const ALPHABET_SIZE: [u16; HUFFMAN_CODES_PER_META_CODE] = [256 + 24, 256, 256, 256, 40]; |
52 | | |
53 | | #[inline] |
54 | 7.34k | pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { |
55 | 7.34k | ((u32::from(size) + (1u32 << bits) - 1) >> bits) |
56 | 7.34k | .try_into() |
57 | 7.34k | .unwrap() |
58 | 7.34k | } image_webp::lossless::subsample_size Line | Count | Source | 54 | 1.86k | pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { | 55 | 1.86k | ((u32::from(size) + (1u32 << bits) - 1) >> bits) | 56 | 1.86k | .try_into() | 57 | 1.86k | .unwrap() | 58 | 1.86k | } |
image_webp::lossless::subsample_size Line | Count | Source | 54 | 1.88k | pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { | 55 | 1.88k | ((u32::from(size) + (1u32 << bits) - 1) >> bits) | 56 | 1.88k | .try_into() | 57 | 1.88k | .unwrap() | 58 | 1.88k | } |
Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size image_webp::lossless::subsample_size Line | Count | Source | 54 | 3.59k | pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 { | 55 | 3.59k | ((u32::from(size) + (1u32 << bits) - 1) >> bits) | 56 | 3.59k | .try_into() | 57 | 3.59k | .unwrap() | 58 | 3.59k | } |
Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size Unexecuted instantiation: image_webp::lossless::subsample_size |
59 | | |
60 | | const NUM_TRANSFORM_TYPES: usize = 4; |
61 | | |
62 | | //Decodes lossless WebP images |
63 | | #[derive(Debug)] |
64 | | pub(crate) struct LosslessDecoder<R> { |
65 | | bit_reader: BitReader<R>, |
66 | | transforms: [Option<TransformType>; NUM_TRANSFORM_TYPES], |
67 | | transform_order: Vec<u8>, |
68 | | width: u16, |
69 | | height: u16, |
70 | | } |
71 | | |
72 | | impl<R: BufRead> LosslessDecoder<R> { |
73 | | /// Create a new decoder |
74 | 2.63k | pub(crate) const fn new(r: R) -> Self { |
75 | 2.63k | Self { |
76 | 2.63k | bit_reader: BitReader::new(r), |
77 | 2.63k | transforms: [None, None, None, None], |
78 | 2.63k | transform_order: Vec::new(), |
79 | 2.63k | width: 0, |
80 | 2.63k | height: 0, |
81 | 2.63k | } |
82 | 2.63k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 74 | 318 | pub(crate) const fn new(r: R) -> Self { | 75 | 318 | Self { | 76 | 318 | bit_reader: BitReader::new(r), | 77 | 318 | transforms: [None, None, None, None], | 78 | 318 | transform_order: Vec::new(), | 79 | 318 | width: 0, | 80 | 318 | height: 0, | 81 | 318 | } | 82 | 318 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 74 | 517 | pub(crate) const fn new(r: R) -> Self { | 75 | 517 | Self { | 76 | 517 | bit_reader: BitReader::new(r), | 77 | 517 | transforms: [None, None, None, None], | 78 | 517 | transform_order: Vec::new(), | 79 | 517 | width: 0, | 80 | 517 | height: 0, | 81 | 517 | } | 82 | 517 | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 74 | 1.79k | pub(crate) const fn new(r: R) -> Self { | 75 | 1.79k | Self { | 76 | 1.79k | bit_reader: BitReader::new(r), | 77 | 1.79k | transforms: [None, None, None, None], | 78 | 1.79k | transform_order: Vec::new(), | 79 | 1.79k | width: 0, | 80 | 1.79k | height: 0, | 81 | 1.79k | } | 82 | 1.79k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new |
83 | | |
84 | | /// Decodes a frame. |
85 | | /// |
86 | | /// In an alpha chunk the width and height are not included in the header, so they should be |
87 | | /// provided by setting the `implicit_dimensions` argument. Otherwise that argument should be |
88 | | /// `None` and the frame dimensions will be determined by reading the VP8L header. |
89 | 2.63k | pub(crate) fn decode_frame( |
90 | 2.63k | &mut self, |
91 | 2.63k | width: u32, |
92 | 2.63k | height: u32, |
93 | 2.63k | implicit_dimensions: bool, |
94 | 2.63k | buf: &mut [u8], |
95 | 2.63k | ) -> Result<(), DecodingError> { |
96 | 2.63k | if implicit_dimensions { |
97 | 517 | self.width = width as u16; |
98 | 517 | self.height = height as u16; |
99 | 517 | } else { |
100 | 2.11k | let signature = self.bit_reader.read_bits::<u8>(8)?; |
101 | 2.11k | if signature != 0x2f { |
102 | 0 | return Err(DecodingError::LosslessSignatureInvalid(signature)); |
103 | 2.11k | } |
104 | | |
105 | 2.11k | self.width = self.bit_reader.read_bits::<u16>(14)? + 1; |
106 | 2.10k | self.height = self.bit_reader.read_bits::<u16>(14)? + 1; |
107 | 2.10k | if u32::from(self.width) != width || u32::from(self.height) != height { |
108 | 2 | return Err(DecodingError::InconsistentImageSizes); |
109 | 2.10k | } |
110 | | |
111 | 2.10k | let _alpha_used = self.bit_reader.read_bits::<u8>(1)?; |
112 | 2.10k | let version_num = self.bit_reader.read_bits::<u8>(3)?; |
113 | 2.10k | if version_num != 0 { |
114 | 0 | return Err(DecodingError::VersionNumberInvalid(version_num)); |
115 | 2.10k | } |
116 | | } |
117 | | |
118 | 2.62k | let transformed_width = self.read_transforms()?; |
119 | 2.44k | let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4; |
120 | 2.44k | self.decode_image_stream( |
121 | 2.44k | transformed_width, |
122 | 2.44k | self.height, |
123 | | true, |
124 | 2.44k | &mut buf[..transformed_size], |
125 | 539 | )?; |
126 | | |
127 | 1.90k | let mut image_size = transformed_size; |
128 | 1.90k | let mut width = transformed_width; |
129 | 3.71k | for &trans_index in self.transform_order.iter().rev() { |
130 | 3.71k | let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap(); |
131 | 3.71k | match transform { |
132 | | TransformType::PredictorTransform { |
133 | 1.87k | size_bits, |
134 | 1.87k | predictor_data, |
135 | 1.87k | } => apply_predictor_transform( |
136 | 1.87k | &mut buf[..image_size], |
137 | 1.87k | width, |
138 | 1.87k | self.height, |
139 | 1.87k | *size_bits, |
140 | 1.87k | predictor_data, |
141 | 0 | )?, |
142 | | TransformType::ColorTransform { |
143 | 7 | size_bits, |
144 | 7 | transform_data, |
145 | 7 | } => { |
146 | 7 | apply_color_transform( |
147 | 7 | &mut buf[..image_size], |
148 | 7 | width, |
149 | 7 | *size_bits, |
150 | 7 | transform_data, |
151 | 7 | ); |
152 | 7 | } |
153 | 1.81k | TransformType::SubtractGreen => { |
154 | 1.81k | apply_subtract_green_transform(&mut buf[..image_size]); |
155 | 1.81k | } |
156 | | TransformType::ColorIndexingTransform { |
157 | 16 | table_size, |
158 | 16 | table_data, |
159 | 16 | } => { |
160 | 16 | width = self.width; |
161 | 16 | image_size = usize::from(width) * usize::from(self.height) * 4; |
162 | 16 | apply_color_indexing_transform( |
163 | 16 | buf, |
164 | 16 | width, |
165 | 16 | self.height, |
166 | 16 | *table_size, |
167 | 16 | table_data, |
168 | 16 | ); |
169 | 16 | } |
170 | | } |
171 | | } |
172 | | |
173 | 1.90k | Ok(()) |
174 | 2.63k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Line | Count | Source | 89 | 318 | pub(crate) fn decode_frame( | 90 | 318 | &mut self, | 91 | 318 | width: u32, | 92 | 318 | height: u32, | 93 | 318 | implicit_dimensions: bool, | 94 | 318 | buf: &mut [u8], | 95 | 318 | ) -> Result<(), DecodingError> { | 96 | 318 | if implicit_dimensions { | 97 | 0 | self.width = width as u16; | 98 | 0 | self.height = height as u16; | 99 | 0 | } else { | 100 | 318 | let signature = self.bit_reader.read_bits::<u8>(8)?; | 101 | 318 | if signature != 0x2f { | 102 | 0 | return Err(DecodingError::LosslessSignatureInvalid(signature)); | 103 | 318 | } | 104 | | | 105 | 318 | self.width = self.bit_reader.read_bits::<u16>(14)? + 1; | 106 | 312 | self.height = self.bit_reader.read_bits::<u16>(14)? + 1; | 107 | 312 | if u32::from(self.width) != width || u32::from(self.height) != height { | 108 | 2 | return Err(DecodingError::InconsistentImageSizes); | 109 | 310 | } | 110 | | | 111 | 310 | let _alpha_used = self.bit_reader.read_bits::<u8>(1)?; | 112 | 310 | let version_num = self.bit_reader.read_bits::<u8>(3)?; | 113 | 310 | if version_num != 0 { | 114 | 0 | return Err(DecodingError::VersionNumberInvalid(version_num)); | 115 | 310 | } | 116 | | } | 117 | | | 118 | 310 | let transformed_width = self.read_transforms()?; | 119 | 299 | let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4; | 120 | 299 | self.decode_image_stream( | 121 | 299 | transformed_width, | 122 | 299 | self.height, | 123 | | true, | 124 | 299 | &mut buf[..transformed_size], | 125 | 279 | )?; | 126 | | | 127 | 20 | let mut image_size = transformed_size; | 128 | 20 | let mut width = transformed_width; | 129 | 29 | for &trans_index in self.transform_order.iter().rev() { | 130 | 29 | let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap(); | 131 | 29 | match transform { | 132 | | TransformType::PredictorTransform { | 133 | 13 | size_bits, | 134 | 13 | predictor_data, | 135 | 13 | } => apply_predictor_transform( | 136 | 13 | &mut buf[..image_size], | 137 | 13 | width, | 138 | 13 | self.height, | 139 | 13 | *size_bits, | 140 | 13 | predictor_data, | 141 | 0 | )?, | 142 | | TransformType::ColorTransform { | 143 | 2 | size_bits, | 144 | 2 | transform_data, | 145 | 2 | } => { | 146 | 2 | apply_color_transform( | 147 | 2 | &mut buf[..image_size], | 148 | 2 | width, | 149 | 2 | *size_bits, | 150 | 2 | transform_data, | 151 | 2 | ); | 152 | 2 | } | 153 | 11 | TransformType::SubtractGreen => { | 154 | 11 | apply_subtract_green_transform(&mut buf[..image_size]); | 155 | 11 | } | 156 | | TransformType::ColorIndexingTransform { | 157 | 3 | table_size, | 158 | 3 | table_data, | 159 | 3 | } => { | 160 | 3 | width = self.width; | 161 | 3 | image_size = usize::from(width) * usize::from(self.height) * 4; | 162 | 3 | apply_color_indexing_transform( | 163 | 3 | buf, | 164 | 3 | width, | 165 | 3 | self.height, | 166 | 3 | *table_size, | 167 | 3 | table_data, | 168 | 3 | ); | 169 | 3 | } | 170 | | } | 171 | | } | 172 | | | 173 | 20 | Ok(()) | 174 | 318 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Line | Count | Source | 89 | 517 | pub(crate) fn decode_frame( | 90 | 517 | &mut self, | 91 | 517 | width: u32, | 92 | 517 | height: u32, | 93 | 517 | implicit_dimensions: bool, | 94 | 517 | buf: &mut [u8], | 95 | 517 | ) -> Result<(), DecodingError> { | 96 | 517 | if implicit_dimensions { | 97 | 517 | self.width = width as u16; | 98 | 517 | self.height = height as u16; | 99 | 517 | } else { | 100 | 0 | let signature = self.bit_reader.read_bits::<u8>(8)?; | 101 | 0 | if signature != 0x2f { | 102 | 0 | return Err(DecodingError::LosslessSignatureInvalid(signature)); | 103 | 0 | } | 104 | | | 105 | 0 | self.width = self.bit_reader.read_bits::<u16>(14)? + 1; | 106 | 0 | self.height = self.bit_reader.read_bits::<u16>(14)? + 1; | 107 | 0 | if u32::from(self.width) != width || u32::from(self.height) != height { | 108 | 0 | return Err(DecodingError::InconsistentImageSizes); | 109 | 0 | } | 110 | | | 111 | 0 | let _alpha_used = self.bit_reader.read_bits::<u8>(1)?; | 112 | 0 | let version_num = self.bit_reader.read_bits::<u8>(3)?; | 113 | 0 | if version_num != 0 { | 114 | 0 | return Err(DecodingError::VersionNumberInvalid(version_num)); | 115 | 0 | } | 116 | | } | 117 | | | 118 | 517 | let transformed_width = self.read_transforms()?; | 119 | 345 | let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4; | 120 | 345 | self.decode_image_stream( | 121 | 345 | transformed_width, | 122 | 345 | self.height, | 123 | | true, | 124 | 345 | &mut buf[..transformed_size], | 125 | 260 | )?; | 126 | | | 127 | 85 | let mut image_size = transformed_size; | 128 | 85 | let mut width = transformed_width; | 129 | 90 | for &trans_index in self.transform_order.iter().rev() { | 130 | 90 | let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap(); | 131 | 90 | match transform { | 132 | | TransformType::PredictorTransform { | 133 | 65 | size_bits, | 134 | 65 | predictor_data, | 135 | 65 | } => apply_predictor_transform( | 136 | 65 | &mut buf[..image_size], | 137 | 65 | width, | 138 | 65 | self.height, | 139 | 65 | *size_bits, | 140 | 65 | predictor_data, | 141 | 0 | )?, | 142 | | TransformType::ColorTransform { | 143 | 5 | size_bits, | 144 | 5 | transform_data, | 145 | 5 | } => { | 146 | 5 | apply_color_transform( | 147 | 5 | &mut buf[..image_size], | 148 | 5 | width, | 149 | 5 | *size_bits, | 150 | 5 | transform_data, | 151 | 5 | ); | 152 | 5 | } | 153 | 7 | TransformType::SubtractGreen => { | 154 | 7 | apply_subtract_green_transform(&mut buf[..image_size]); | 155 | 7 | } | 156 | | TransformType::ColorIndexingTransform { | 157 | 13 | table_size, | 158 | 13 | table_data, | 159 | 13 | } => { | 160 | 13 | width = self.width; | 161 | 13 | image_size = usize::from(width) * usize::from(self.height) * 4; | 162 | 13 | apply_color_indexing_transform( | 163 | 13 | buf, | 164 | 13 | width, | 165 | 13 | self.height, | 166 | 13 | *table_size, | 167 | 13 | table_data, | 168 | 13 | ); | 169 | 13 | } | 170 | | } | 171 | | } | 172 | | | 173 | 85 | Ok(()) | 174 | 517 | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Line | Count | Source | 89 | 1.79k | pub(crate) fn decode_frame( | 90 | 1.79k | &mut self, | 91 | 1.79k | width: u32, | 92 | 1.79k | height: u32, | 93 | 1.79k | implicit_dimensions: bool, | 94 | 1.79k | buf: &mut [u8], | 95 | 1.79k | ) -> Result<(), DecodingError> { | 96 | 1.79k | if implicit_dimensions { | 97 | 0 | self.width = width as u16; | 98 | 0 | self.height = height as u16; | 99 | 0 | } else { | 100 | 1.79k | let signature = self.bit_reader.read_bits::<u8>(8)?; | 101 | 1.79k | if signature != 0x2f { | 102 | 0 | return Err(DecodingError::LosslessSignatureInvalid(signature)); | 103 | 1.79k | } | 104 | | | 105 | 1.79k | self.width = self.bit_reader.read_bits::<u16>(14)? + 1; | 106 | 1.79k | self.height = self.bit_reader.read_bits::<u16>(14)? + 1; | 107 | 1.79k | if u32::from(self.width) != width || u32::from(self.height) != height { | 108 | 0 | return Err(DecodingError::InconsistentImageSizes); | 109 | 1.79k | } | 110 | | | 111 | 1.79k | let _alpha_used = self.bit_reader.read_bits::<u8>(1)?; | 112 | 1.79k | let version_num = self.bit_reader.read_bits::<u8>(3)?; | 113 | 1.79k | if version_num != 0 { | 114 | 0 | return Err(DecodingError::VersionNumberInvalid(version_num)); | 115 | 1.79k | } | 116 | | } | 117 | | | 118 | 1.79k | let transformed_width = self.read_transforms()?; | 119 | 1.79k | let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4; | 120 | 1.79k | self.decode_image_stream( | 121 | 1.79k | transformed_width, | 122 | 1.79k | self.height, | 123 | | true, | 124 | 1.79k | &mut buf[..transformed_size], | 125 | 0 | )?; | 126 | | | 127 | 1.79k | let mut image_size = transformed_size; | 128 | 1.79k | let mut width = transformed_width; | 129 | 3.59k | for &trans_index in self.transform_order.iter().rev() { | 130 | 3.59k | let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap(); | 131 | 3.59k | match transform { | 132 | | TransformType::PredictorTransform { | 133 | 1.79k | size_bits, | 134 | 1.79k | predictor_data, | 135 | 1.79k | } => apply_predictor_transform( | 136 | 1.79k | &mut buf[..image_size], | 137 | 1.79k | width, | 138 | 1.79k | self.height, | 139 | 1.79k | *size_bits, | 140 | 1.79k | predictor_data, | 141 | 0 | )?, | 142 | | TransformType::ColorTransform { | 143 | 0 | size_bits, | 144 | 0 | transform_data, | 145 | 0 | } => { | 146 | 0 | apply_color_transform( | 147 | 0 | &mut buf[..image_size], | 148 | 0 | width, | 149 | 0 | *size_bits, | 150 | 0 | transform_data, | 151 | 0 | ); | 152 | 0 | } | 153 | 1.79k | TransformType::SubtractGreen => { | 154 | 1.79k | apply_subtract_green_transform(&mut buf[..image_size]); | 155 | 1.79k | } | 156 | | TransformType::ColorIndexingTransform { | 157 | 0 | table_size, | 158 | 0 | table_data, | 159 | 0 | } => { | 160 | 0 | width = self.width; | 161 | 0 | image_size = usize::from(width) * usize::from(self.height) * 4; | 162 | 0 | apply_color_indexing_transform( | 163 | 0 | buf, | 164 | 0 | width, | 165 | 0 | self.height, | 166 | 0 | *table_size, | 167 | 0 | table_data, | 168 | 0 | ); | 169 | 0 | } | 170 | | } | 171 | | } | 172 | | | 173 | 1.79k | Ok(()) | 174 | 1.79k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame |
175 | | |
176 | | /// Reads Image data from the bitstream |
177 | | /// |
178 | | /// Can be in any of the 5 roles described in the Specification. ARGB Image role has different |
179 | | /// behaviour to the other 4. xsize and ysize describe the size of the blocks where each block |
180 | | /// has its own entropy code |
181 | 5.28k | fn decode_image_stream( |
182 | 5.28k | &mut self, |
183 | 5.28k | xsize: u16, |
184 | 5.28k | ysize: u16, |
185 | 5.28k | is_argb_img: bool, |
186 | 5.28k | data: &mut [u8], |
187 | 5.28k | ) -> Result<(), DecodingError> { |
188 | 5.28k | let color_cache_bits = self.read_color_cache()?; |
189 | 5.27k | let color_cache = color_cache_bits.map(|bits| ColorCache { |
190 | 634 | color_cache_bits: bits, |
191 | 634 | color_cache: vec![[0; 4]; 1 << bits], |
192 | 634 | }); <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Line | Count | Source | 190 | 295 | color_cache_bits: bits, | 191 | 295 | color_cache: vec![[0; 4]; 1 << bits], | 192 | 295 | }); |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Line | Count | Source | 190 | 339 | color_cache_bits: bits, | 191 | 339 | color_cache: vec![[0; 4]; 1 << bits], | 192 | 339 | }); |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0} |
193 | | |
194 | 5.27k | let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?; |
195 | 4.89k | self.decode_image_data(xsize, ysize, huffman_info, data) |
196 | 5.28k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Line | Count | Source | 181 | 621 | fn decode_image_stream( | 182 | 621 | &mut self, | 183 | 621 | xsize: u16, | 184 | 621 | ysize: u16, | 185 | 621 | is_argb_img: bool, | 186 | 621 | data: &mut [u8], | 187 | 621 | ) -> Result<(), DecodingError> { | 188 | 621 | let color_cache_bits = self.read_color_cache()?; | 189 | 621 | let color_cache = color_cache_bits.map(|bits| ColorCache { | 190 | | color_cache_bits: bits, | 191 | | color_cache: vec![[0; 4]; 1 << bits], | 192 | | }); | 193 | | | 194 | 621 | let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?; | 195 | 473 | self.decode_image_data(xsize, ysize, huffman_info, data) | 196 | 621 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Line | Count | Source | 181 | 1.06k | fn decode_image_stream( | 182 | 1.06k | &mut self, | 183 | 1.06k | xsize: u16, | 184 | 1.06k | ysize: u16, | 185 | 1.06k | is_argb_img: bool, | 186 | 1.06k | data: &mut [u8], | 187 | 1.06k | ) -> Result<(), DecodingError> { | 188 | 1.06k | let color_cache_bits = self.read_color_cache()?; | 189 | 1.05k | let color_cache = color_cache_bits.map(|bits| ColorCache { | 190 | | color_cache_bits: bits, | 191 | | color_cache: vec![[0; 4]; 1 << bits], | 192 | | }); | 193 | | | 194 | 1.05k | let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?; | 195 | 830 | self.decode_image_data(xsize, ysize, huffman_info, data) | 196 | 1.06k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Line | Count | Source | 181 | 3.59k | fn decode_image_stream( | 182 | 3.59k | &mut self, | 183 | 3.59k | xsize: u16, | 184 | 3.59k | ysize: u16, | 185 | 3.59k | is_argb_img: bool, | 186 | 3.59k | data: &mut [u8], | 187 | 3.59k | ) -> Result<(), DecodingError> { | 188 | 3.59k | let color_cache_bits = self.read_color_cache()?; | 189 | 3.59k | let color_cache = color_cache_bits.map(|bits| ColorCache { | 190 | | color_cache_bits: bits, | 191 | | color_cache: vec![[0; 4]; 1 << bits], | 192 | | }); | 193 | | | 194 | 3.59k | let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?; | 195 | 3.59k | self.decode_image_data(xsize, ysize, huffman_info, data) | 196 | 3.59k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream |
197 | | |
198 | | /// Reads transforms and their data from the bitstream |
199 | 2.62k | fn read_transforms(&mut self) -> Result<u16, DecodingError> { |
200 | 2.62k | let mut xsize = self.width; |
201 | | |
202 | 6.94k | while self.bit_reader.read_bits::<u8>(1)? == 1 { |
203 | 4.49k | let transform_type_val = self.bit_reader.read_bits::<u8>(2)?; |
204 | | |
205 | 4.49k | if self.transforms[usize::from(transform_type_val)].is_some() { |
206 | | //can only have one of each transform, error |
207 | 3 | return Err(DecodingError::TransformError); |
208 | 4.49k | } |
209 | | |
210 | 4.49k | self.transform_order.push(transform_type_val); |
211 | | |
212 | 4.49k | let transform_type = match transform_type_val { |
213 | | 0 => { |
214 | | //predictor |
215 | | |
216 | 2.25k | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
217 | | |
218 | 2.25k | let block_xsize = subsample_size(xsize, size_bits); |
219 | 2.25k | let block_ysize = subsample_size(self.height, size_bits); |
220 | | |
221 | 2.25k | let mut predictor_data = |
222 | 2.25k | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; |
223 | 2.25k | self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?; |
224 | | |
225 | 2.13k | TransformType::PredictorTransform { |
226 | 2.13k | size_bits, |
227 | 2.13k | predictor_data, |
228 | 2.13k | } |
229 | | } |
230 | | 1 => { |
231 | | //color transform |
232 | | |
233 | 64 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
234 | | |
235 | 63 | let block_xsize = subsample_size(xsize, size_bits); |
236 | 63 | let block_ysize = subsample_size(self.height, size_bits); |
237 | | |
238 | 63 | let mut transform_data = |
239 | 63 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; |
240 | 63 | self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?; |
241 | | |
242 | 33 | TransformType::ColorTransform { |
243 | 33 | size_bits, |
244 | 33 | transform_data, |
245 | 33 | } |
246 | | } |
247 | | 2 => { |
248 | | //subtract green |
249 | | |
250 | 1.98k | TransformType::SubtractGreen |
251 | | } |
252 | | 3 => { |
253 | 197 | let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1; |
254 | | |
255 | 196 | let mut color_map = vec![0; usize::from(color_table_size) * 4]; |
256 | 196 | self.decode_image_stream(color_table_size, 1, false, &mut color_map)?; |
257 | | |
258 | 166 | let bits = if color_table_size <= 2 { |
259 | 75 | 3 |
260 | 91 | } else if color_table_size <= 4 { |
261 | 14 | 2 |
262 | 77 | } else if color_table_size <= 16 { |
263 | 3 | 1 |
264 | | } else { |
265 | 74 | 0 |
266 | | }; |
267 | 166 | xsize = subsample_size(xsize, bits); |
268 | | |
269 | 166 | Self::adjust_color_map(&mut color_map); |
270 | | |
271 | 166 | TransformType::ColorIndexingTransform { |
272 | 166 | table_size: color_table_size, |
273 | 166 | table_data: color_map, |
274 | 166 | } |
275 | | } |
276 | 0 | _ => unreachable!(), |
277 | | }; |
278 | | |
279 | 4.31k | self.transforms[usize::from(transform_type_val)] = Some(transform_type); |
280 | | } |
281 | | |
282 | 2.44k | Ok(xsize) |
283 | 2.62k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Line | Count | Source | 199 | 310 | fn read_transforms(&mut self) -> Result<u16, DecodingError> { | 200 | 310 | let mut xsize = self.width; | 201 | | | 202 | 530 | while self.bit_reader.read_bits::<u8>(1)? == 1 { | 203 | 231 | let transform_type_val = self.bit_reader.read_bits::<u8>(2)?; | 204 | | | 205 | 231 | if self.transforms[usize::from(transform_type_val)].is_some() { | 206 | | //can only have one of each transform, error | 207 | 1 | return Err(DecodingError::TransformError); | 208 | 230 | } | 209 | | | 210 | 230 | self.transform_order.push(transform_type_val); | 211 | | | 212 | 230 | let transform_type = match transform_type_val { | 213 | | 0 => { | 214 | | //predictor | 215 | | | 216 | 104 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 217 | | | 218 | 104 | let block_xsize = subsample_size(xsize, size_bits); | 219 | 104 | let block_ysize = subsample_size(self.height, size_bits); | 220 | | | 221 | 104 | let mut predictor_data = | 222 | 104 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 223 | 104 | self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?; | 224 | | | 225 | 100 | TransformType::PredictorTransform { | 226 | 100 | size_bits, | 227 | 100 | predictor_data, | 228 | 100 | } | 229 | | } | 230 | | 1 => { | 231 | | //color transform | 232 | | | 233 | 25 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 234 | | | 235 | 25 | let block_xsize = subsample_size(xsize, size_bits); | 236 | 25 | let block_ysize = subsample_size(self.height, size_bits); | 237 | | | 238 | 25 | let mut transform_data = | 239 | 25 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 240 | 25 | self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?; | 241 | | | 242 | 23 | TransformType::ColorTransform { | 243 | 23 | size_bits, | 244 | 23 | transform_data, | 245 | 23 | } | 246 | | } | 247 | | 2 => { | 248 | | //subtract green | 249 | | | 250 | 60 | TransformType::SubtractGreen | 251 | | } | 252 | | 3 => { | 253 | 41 | let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1; | 254 | | | 255 | 40 | let mut color_map = vec![0; usize::from(color_table_size) * 4]; | 256 | 40 | self.decode_image_stream(color_table_size, 1, false, &mut color_map)?; | 257 | | | 258 | 37 | let bits = if color_table_size <= 2 { | 259 | 2 | 3 | 260 | 35 | } else if color_table_size <= 4 { | 261 | 0 | 2 | 262 | 35 | } else if color_table_size <= 16 { | 263 | 1 | 1 | 264 | | } else { | 265 | 34 | 0 | 266 | | }; | 267 | 37 | xsize = subsample_size(xsize, bits); | 268 | | | 269 | 37 | Self::adjust_color_map(&mut color_map); | 270 | | | 271 | 37 | TransformType::ColorIndexingTransform { | 272 | 37 | table_size: color_table_size, | 273 | 37 | table_data: color_map, | 274 | 37 | } | 275 | | } | 276 | 0 | _ => unreachable!(), | 277 | | }; | 278 | | | 279 | 220 | self.transforms[usize::from(transform_type_val)] = Some(transform_type); | 280 | | } | 281 | | | 282 | 299 | Ok(xsize) | 283 | 310 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Line | Count | Source | 199 | 517 | fn read_transforms(&mut self) -> Result<u16, DecodingError> { | 200 | 517 | let mut xsize = self.width; | 201 | | | 202 | 1.01k | while self.bit_reader.read_bits::<u8>(1)? == 1 { | 203 | 674 | let transform_type_val = self.bit_reader.read_bits::<u8>(2)?; | 204 | | | 205 | 674 | if self.transforms[usize::from(transform_type_val)].is_some() { | 206 | | //can only have one of each transform, error | 207 | 2 | return Err(DecodingError::TransformError); | 208 | 672 | } | 209 | | | 210 | 672 | self.transform_order.push(transform_type_val); | 211 | | | 212 | 672 | let transform_type = match transform_type_val { | 213 | | 0 => { | 214 | | //predictor | 215 | | | 216 | 352 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 217 | | | 218 | 351 | let block_xsize = subsample_size(xsize, size_bits); | 219 | 351 | let block_ysize = subsample_size(self.height, size_bits); | 220 | | | 221 | 351 | let mut predictor_data = | 222 | 351 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 223 | 351 | self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?; | 224 | | | 225 | 238 | TransformType::PredictorTransform { | 226 | 238 | size_bits, | 227 | 238 | predictor_data, | 228 | 238 | } | 229 | | } | 230 | | 1 => { | 231 | | //color transform | 232 | | | 233 | 39 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 234 | | | 235 | 38 | let block_xsize = subsample_size(xsize, size_bits); | 236 | 38 | let block_ysize = subsample_size(self.height, size_bits); | 237 | | | 238 | 38 | let mut transform_data = | 239 | 38 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 240 | 38 | self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?; | 241 | | | 242 | 10 | TransformType::ColorTransform { | 243 | 10 | size_bits, | 244 | 10 | transform_data, | 245 | 10 | } | 246 | | } | 247 | | 2 => { | 248 | | //subtract green | 249 | | | 250 | 125 | TransformType::SubtractGreen | 251 | | } | 252 | | 3 => { | 253 | 156 | let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1; | 254 | | | 255 | 156 | let mut color_map = vec![0; usize::from(color_table_size) * 4]; | 256 | 156 | self.decode_image_stream(color_table_size, 1, false, &mut color_map)?; | 257 | | | 258 | 129 | let bits = if color_table_size <= 2 { | 259 | 73 | 3 | 260 | 56 | } else if color_table_size <= 4 { | 261 | 14 | 2 | 262 | 42 | } else if color_table_size <= 16 { | 263 | 2 | 1 | 264 | | } else { | 265 | 40 | 0 | 266 | | }; | 267 | 129 | xsize = subsample_size(xsize, bits); | 268 | | | 269 | 129 | Self::adjust_color_map(&mut color_map); | 270 | | | 271 | 129 | TransformType::ColorIndexingTransform { | 272 | 129 | table_size: color_table_size, | 273 | 129 | table_data: color_map, | 274 | 129 | } | 275 | | } | 276 | 0 | _ => unreachable!(), | 277 | | }; | 278 | | | 279 | 502 | self.transforms[usize::from(transform_type_val)] = Some(transform_type); | 280 | | } | 281 | | | 282 | 345 | Ok(xsize) | 283 | 517 | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Line | Count | Source | 199 | 1.79k | fn read_transforms(&mut self) -> Result<u16, DecodingError> { | 200 | 1.79k | let mut xsize = self.width; | 201 | | | 202 | 5.39k | while self.bit_reader.read_bits::<u8>(1)? == 1 { | 203 | 3.59k | let transform_type_val = self.bit_reader.read_bits::<u8>(2)?; | 204 | | | 205 | 3.59k | if self.transforms[usize::from(transform_type_val)].is_some() { | 206 | | //can only have one of each transform, error | 207 | 0 | return Err(DecodingError::TransformError); | 208 | 3.59k | } | 209 | | | 210 | 3.59k | self.transform_order.push(transform_type_val); | 211 | | | 212 | 3.59k | let transform_type = match transform_type_val { | 213 | | 0 => { | 214 | | //predictor | 215 | | | 216 | 1.79k | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 217 | | | 218 | 1.79k | let block_xsize = subsample_size(xsize, size_bits); | 219 | 1.79k | let block_ysize = subsample_size(self.height, size_bits); | 220 | | | 221 | 1.79k | let mut predictor_data = | 222 | 1.79k | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 223 | 1.79k | self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?; | 224 | | | 225 | 1.79k | TransformType::PredictorTransform { | 226 | 1.79k | size_bits, | 227 | 1.79k | predictor_data, | 228 | 1.79k | } | 229 | | } | 230 | | 1 => { | 231 | | //color transform | 232 | | | 233 | 0 | let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 234 | | | 235 | 0 | let block_xsize = subsample_size(xsize, size_bits); | 236 | 0 | let block_ysize = subsample_size(self.height, size_bits); | 237 | | | 238 | 0 | let mut transform_data = | 239 | 0 | vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4]; | 240 | 0 | self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?; | 241 | | | 242 | 0 | TransformType::ColorTransform { | 243 | 0 | size_bits, | 244 | 0 | transform_data, | 245 | 0 | } | 246 | | } | 247 | | 2 => { | 248 | | //subtract green | 249 | | | 250 | 1.79k | TransformType::SubtractGreen | 251 | | } | 252 | | 3 => { | 253 | 0 | let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1; | 254 | | | 255 | 0 | let mut color_map = vec![0; usize::from(color_table_size) * 4]; | 256 | 0 | self.decode_image_stream(color_table_size, 1, false, &mut color_map)?; | 257 | | | 258 | 0 | let bits = if color_table_size <= 2 { | 259 | 0 | 3 | 260 | 0 | } else if color_table_size <= 4 { | 261 | 0 | 2 | 262 | 0 | } else if color_table_size <= 16 { | 263 | 0 | 1 | 264 | | } else { | 265 | 0 | 0 | 266 | | }; | 267 | 0 | xsize = subsample_size(xsize, bits); | 268 | | | 269 | 0 | Self::adjust_color_map(&mut color_map); | 270 | | | 271 | 0 | TransformType::ColorIndexingTransform { | 272 | 0 | table_size: color_table_size, | 273 | 0 | table_data: color_map, | 274 | 0 | } | 275 | | } | 276 | 0 | _ => unreachable!(), | 277 | | }; | 278 | | | 279 | 3.59k | self.transforms[usize::from(transform_type_val)] = Some(transform_type); | 280 | | } | 281 | | | 282 | 1.79k | Ok(xsize) | 283 | 1.79k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms |
284 | | |
285 | | /// Adjusts the color map since it's subtraction coded |
286 | 166 | fn adjust_color_map(color_map: &mut [u8]) { |
287 | 57.2k | for i in 4..color_map.len() { |
288 | 57.2k | color_map[i] = color_map[i].wrapping_add(color_map[i - 4]); |
289 | 57.2k | } |
290 | 166 | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Line | Count | Source | 286 | 37 | fn adjust_color_map(color_map: &mut [u8]) { | 287 | 23.6k | for i in 4..color_map.len() { | 288 | 23.6k | color_map[i] = color_map[i].wrapping_add(color_map[i - 4]); | 289 | 23.6k | } | 290 | 37 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Line | Count | Source | 286 | 129 | fn adjust_color_map(color_map: &mut [u8]) { | 287 | 33.6k | for i in 4..color_map.len() { | 288 | 33.6k | color_map[i] = color_map[i].wrapping_add(color_map[i - 4]); | 289 | 33.6k | } | 290 | 129 | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map |
291 | | |
292 | | /// Reads huffman codes associated with an image |
293 | 5.27k | fn read_huffman_codes( |
294 | 5.27k | &mut self, |
295 | 5.27k | read_meta: bool, |
296 | 5.27k | xsize: u16, |
297 | 5.27k | ysize: u16, |
298 | 5.27k | color_cache: Option<ColorCache>, |
299 | 5.27k | ) -> Result<HuffmanInfo, DecodingError> { |
300 | 5.27k | let mut num_huff_groups = 1u32; |
301 | | |
302 | 5.27k | let mut huffman_bits = 0; |
303 | 5.27k | let mut huffman_xsize = 1; |
304 | 5.27k | let mut huffman_ysize = 1; |
305 | 5.27k | let mut entropy_image = Vec::new(); |
306 | | |
307 | 5.27k | if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 { |
308 | | //meta huffman codes |
309 | 332 | huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2; |
310 | 332 | huffman_xsize = subsample_size(xsize, huffman_bits); |
311 | 332 | huffman_ysize = subsample_size(ysize, huffman_bits); |
312 | | |
313 | 332 | let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4]; |
314 | 332 | self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?; |
315 | | |
316 | 317 | entropy_image = data |
317 | 317 | .chunks_exact(4) |
318 | 1.69M | .map(|pixel| { |
319 | 1.69M | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); |
320 | 1.69M | if u32::from(meta_huff_code) >= num_huff_groups { |
321 | 406 | num_huff_groups = u32::from(meta_huff_code) + 1; |
322 | 1.69M | } |
323 | 1.69M | meta_huff_code |
324 | 1.69M | }) <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Line | Count | Source | 318 | 1.64M | .map(|pixel| { | 319 | 1.64M | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); | 320 | 1.64M | if u32::from(meta_huff_code) >= num_huff_groups { | 321 | 237 | num_huff_groups = u32::from(meta_huff_code) + 1; | 322 | 1.64M | } | 323 | 1.64M | meta_huff_code | 324 | 1.64M | }) |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Line | Count | Source | 318 | 44.0k | .map(|pixel| { | 319 | 44.0k | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); | 320 | 44.0k | if u32::from(meta_huff_code) >= num_huff_groups { | 321 | 169 | num_huff_groups = u32::from(meta_huff_code) + 1; | 322 | 43.8k | } | 323 | 44.0k | meta_huff_code | 324 | 44.0k | }) |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0} |
325 | 317 | .collect::<Vec<u16>>(); |
326 | 4.93k | } |
327 | | |
328 | 5.25k | let mut hufftree_groups = Vec::new(); |
329 | | |
330 | 21.3k | for _i in 0..num_huff_groups { |
331 | 21.3k | let mut group: HuffmanCodeGroup = Default::default(); |
332 | 126k | for j in 0..HUFFMAN_CODES_PER_META_CODE { |
333 | 105k | let mut alphabet_size = ALPHABET_SIZE[j]; |
334 | 105k | if j == 0 { |
335 | 21.3k | if let Some(color_cache) = color_cache.as_ref() { |
336 | 12.1k | alphabet_size += 1 << color_cache.color_cache_bits; |
337 | 12.1k | } |
338 | 84.5k | } |
339 | | |
340 | 105k | let tree = self.read_huffman_code(alphabet_size)?; |
341 | 105k | group[j] = tree; |
342 | | } |
343 | 20.9k | hufftree_groups.push(group); |
344 | | } |
345 | | |
346 | 4.89k | let huffman_mask = if huffman_bits == 0 { |
347 | 4.76k | !0 |
348 | | } else { |
349 | 129 | (1 << huffman_bits) - 1 |
350 | | }; |
351 | | |
352 | 4.89k | let info = HuffmanInfo { |
353 | 4.89k | xsize: huffman_xsize, |
354 | 4.89k | _ysize: huffman_ysize, |
355 | 4.89k | color_cache, |
356 | 4.89k | image: entropy_image, |
357 | 4.89k | bits: huffman_bits, |
358 | 4.89k | mask: huffman_mask, |
359 | 4.89k | huffman_code_groups: hufftree_groups, |
360 | 4.89k | }; |
361 | | |
362 | 4.89k | Ok(info) |
363 | 5.27k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Line | Count | Source | 293 | 621 | fn read_huffman_codes( | 294 | 621 | &mut self, | 295 | 621 | read_meta: bool, | 296 | 621 | xsize: u16, | 297 | 621 | ysize: u16, | 298 | 621 | color_cache: Option<ColorCache>, | 299 | 621 | ) -> Result<HuffmanInfo, DecodingError> { | 300 | 621 | let mut num_huff_groups = 1u32; | 301 | | | 302 | 621 | let mut huffman_bits = 0; | 303 | 621 | let mut huffman_xsize = 1; | 304 | 621 | let mut huffman_ysize = 1; | 305 | 621 | let mut entropy_image = Vec::new(); | 306 | | | 307 | 621 | if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 { | 308 | | //meta huffman codes | 309 | 153 | huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 310 | 153 | huffman_xsize = subsample_size(xsize, huffman_bits); | 311 | 153 | huffman_ysize = subsample_size(ysize, huffman_bits); | 312 | | | 313 | 153 | let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4]; | 314 | 153 | self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?; | 315 | | | 316 | 147 | entropy_image = data | 317 | 147 | .chunks_exact(4) | 318 | 147 | .map(|pixel| { | 319 | | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); | 320 | | if u32::from(meta_huff_code) >= num_huff_groups { | 321 | | num_huff_groups = u32::from(meta_huff_code) + 1; | 322 | | } | 323 | | meta_huff_code | 324 | | }) | 325 | 147 | .collect::<Vec<u16>>(); | 326 | 468 | } | 327 | | | 328 | 615 | let mut hufftree_groups = Vec::new(); | 329 | | | 330 | 13.3k | for _i in 0..num_huff_groups { | 331 | 13.3k | let mut group: HuffmanCodeGroup = Default::default(); | 332 | 79.8k | for j in 0..HUFFMAN_CODES_PER_META_CODE { | 333 | 66.6k | let mut alphabet_size = ALPHABET_SIZE[j]; | 334 | 66.6k | if j == 0 { | 335 | 13.3k | if let Some(color_cache) = color_cache.as_ref() { | 336 | 11.4k | alphabet_size += 1 << color_cache.color_cache_bits; | 337 | 11.4k | } | 338 | 53.2k | } | 339 | | | 340 | 66.6k | let tree = self.read_huffman_code(alphabet_size)?; | 341 | 66.4k | group[j] = tree; | 342 | | } | 343 | 13.2k | hufftree_groups.push(group); | 344 | | } | 345 | | | 346 | 473 | let huffman_mask = if huffman_bits == 0 { | 347 | 444 | !0 | 348 | | } else { | 349 | 29 | (1 << huffman_bits) - 1 | 350 | | }; | 351 | | | 352 | 473 | let info = HuffmanInfo { | 353 | 473 | xsize: huffman_xsize, | 354 | 473 | _ysize: huffman_ysize, | 355 | 473 | color_cache, | 356 | 473 | image: entropy_image, | 357 | 473 | bits: huffman_bits, | 358 | 473 | mask: huffman_mask, | 359 | 473 | huffman_code_groups: hufftree_groups, | 360 | 473 | }; | 361 | | | 362 | 473 | Ok(info) | 363 | 621 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Line | Count | Source | 293 | 1.05k | fn read_huffman_codes( | 294 | 1.05k | &mut self, | 295 | 1.05k | read_meta: bool, | 296 | 1.05k | xsize: u16, | 297 | 1.05k | ysize: u16, | 298 | 1.05k | color_cache: Option<ColorCache>, | 299 | 1.05k | ) -> Result<HuffmanInfo, DecodingError> { | 300 | 1.05k | let mut num_huff_groups = 1u32; | 301 | | | 302 | 1.05k | let mut huffman_bits = 0; | 303 | 1.05k | let mut huffman_xsize = 1; | 304 | 1.05k | let mut huffman_ysize = 1; | 305 | 1.05k | let mut entropy_image = Vec::new(); | 306 | | | 307 | 1.05k | if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 { | 308 | | //meta huffman codes | 309 | 179 | huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 310 | 179 | huffman_xsize = subsample_size(xsize, huffman_bits); | 311 | 179 | huffman_ysize = subsample_size(ysize, huffman_bits); | 312 | | | 313 | 179 | let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4]; | 314 | 179 | self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?; | 315 | | | 316 | 170 | entropy_image = data | 317 | 170 | .chunks_exact(4) | 318 | 170 | .map(|pixel| { | 319 | | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); | 320 | | if u32::from(meta_huff_code) >= num_huff_groups { | 321 | | num_huff_groups = u32::from(meta_huff_code) + 1; | 322 | | } | 323 | | meta_huff_code | 324 | | }) | 325 | 170 | .collect::<Vec<u16>>(); | 326 | 876 | } | 327 | | | 328 | 1.04k | let mut hufftree_groups = Vec::new(); | 329 | | | 330 | 4.37k | for _i in 0..num_huff_groups { | 331 | 4.37k | let mut group: HuffmanCodeGroup = Default::default(); | 332 | 25.4k | for j in 0..HUFFMAN_CODES_PER_META_CODE { | 333 | 21.2k | let mut alphabet_size = ALPHABET_SIZE[j]; | 334 | 21.2k | if j == 0 { | 335 | 4.37k | if let Some(color_cache) = color_cache.as_ref() { | 336 | 743 | alphabet_size += 1 << color_cache.color_cache_bits; | 337 | 3.62k | } | 338 | 16.9k | } | 339 | | | 340 | 21.2k | let tree = self.read_huffman_code(alphabet_size)?; | 341 | 21.0k | group[j] = tree; | 342 | | } | 343 | 4.15k | hufftree_groups.push(group); | 344 | | } | 345 | | | 346 | 830 | let huffman_mask = if huffman_bits == 0 { | 347 | 730 | !0 | 348 | | } else { | 349 | 100 | (1 << huffman_bits) - 1 | 350 | | }; | 351 | | | 352 | 830 | let info = HuffmanInfo { | 353 | 830 | xsize: huffman_xsize, | 354 | 830 | _ysize: huffman_ysize, | 355 | 830 | color_cache, | 356 | 830 | image: entropy_image, | 357 | 830 | bits: huffman_bits, | 358 | 830 | mask: huffman_mask, | 359 | 830 | huffman_code_groups: hufftree_groups, | 360 | 830 | }; | 361 | | | 362 | 830 | Ok(info) | 363 | 1.05k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Line | Count | Source | 293 | 3.59k | fn read_huffman_codes( | 294 | 3.59k | &mut self, | 295 | 3.59k | read_meta: bool, | 296 | 3.59k | xsize: u16, | 297 | 3.59k | ysize: u16, | 298 | 3.59k | color_cache: Option<ColorCache>, | 299 | 3.59k | ) -> Result<HuffmanInfo, DecodingError> { | 300 | 3.59k | let mut num_huff_groups = 1u32; | 301 | | | 302 | 3.59k | let mut huffman_bits = 0; | 303 | 3.59k | let mut huffman_xsize = 1; | 304 | 3.59k | let mut huffman_ysize = 1; | 305 | 3.59k | let mut entropy_image = Vec::new(); | 306 | | | 307 | 3.59k | if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 { | 308 | | //meta huffman codes | 309 | 0 | huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2; | 310 | 0 | huffman_xsize = subsample_size(xsize, huffman_bits); | 311 | 0 | huffman_ysize = subsample_size(ysize, huffman_bits); | 312 | | | 313 | 0 | let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4]; | 314 | 0 | self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?; | 315 | | | 316 | 0 | entropy_image = data | 317 | 0 | .chunks_exact(4) | 318 | 0 | .map(|pixel| { | 319 | | let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]); | 320 | | if u32::from(meta_huff_code) >= num_huff_groups { | 321 | | num_huff_groups = u32::from(meta_huff_code) + 1; | 322 | | } | 323 | | meta_huff_code | 324 | | }) | 325 | 0 | .collect::<Vec<u16>>(); | 326 | 3.59k | } | 327 | | | 328 | 3.59k | let mut hufftree_groups = Vec::new(); | 329 | | | 330 | 3.59k | for _i in 0..num_huff_groups { | 331 | 3.59k | let mut group: HuffmanCodeGroup = Default::default(); | 332 | 21.5k | for j in 0..HUFFMAN_CODES_PER_META_CODE { | 333 | 17.9k | let mut alphabet_size = ALPHABET_SIZE[j]; | 334 | 17.9k | if j == 0 { | 335 | 3.59k | if let Some(color_cache) = color_cache.as_ref() { | 336 | 0 | alphabet_size += 1 << color_cache.color_cache_bits; | 337 | 3.59k | } | 338 | 14.3k | } | 339 | | | 340 | 17.9k | let tree = self.read_huffman_code(alphabet_size)?; | 341 | 17.9k | group[j] = tree; | 342 | | } | 343 | 3.59k | hufftree_groups.push(group); | 344 | | } | 345 | | | 346 | 3.59k | let huffman_mask = if huffman_bits == 0 { | 347 | 3.59k | !0 | 348 | | } else { | 349 | 0 | (1 << huffman_bits) - 1 | 350 | | }; | 351 | | | 352 | 3.59k | let info = HuffmanInfo { | 353 | 3.59k | xsize: huffman_xsize, | 354 | 3.59k | _ysize: huffman_ysize, | 355 | 3.59k | color_cache, | 356 | 3.59k | image: entropy_image, | 357 | 3.59k | bits: huffman_bits, | 358 | 3.59k | mask: huffman_mask, | 359 | 3.59k | huffman_code_groups: hufftree_groups, | 360 | 3.59k | }; | 361 | | | 362 | 3.59k | Ok(info) | 363 | 3.59k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes |
364 | | |
365 | | /// Decodes and returns a single huffman tree |
366 | 105k | fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> { |
367 | 105k | let simple = self.bit_reader.read_bits::<u8>(1)? == 1; |
368 | | |
369 | 105k | if simple { |
370 | 94.8k | let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1; |
371 | | |
372 | 94.7k | let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?; |
373 | 94.7k | let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?; |
374 | | |
375 | 94.7k | if zero_symbol >= alphabet_size { |
376 | 8 | return Err(DecodingError::BitStreamError); |
377 | 94.7k | } |
378 | | |
379 | 94.7k | if num_symbols == 1 { |
380 | 80.7k | Ok(HuffmanTree::build_single_node(zero_symbol)) |
381 | | } else { |
382 | 14.0k | let one_symbol = self.bit_reader.read_bits::<u16>(8)?; |
383 | 13.9k | if one_symbol >= alphabet_size { |
384 | 8 | return Err(DecodingError::BitStreamError); |
385 | 13.9k | } |
386 | 13.9k | Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol)) |
387 | | } |
388 | | } else { |
389 | 11.0k | let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; |
390 | | |
391 | 11.0k | let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?; |
392 | 167k | for i in 0..num_code_lengths { |
393 | 166k | code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = |
394 | 167k | self.bit_reader.read_bits(3)?; |
395 | | } |
396 | | |
397 | 10.8k | let new_code_lengths = |
398 | 11.0k | self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; |
399 | | |
400 | 10.8k | HuffmanTree::build_implicit(new_code_lengths) |
401 | | } |
402 | 105k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Line | Count | Source | 366 | 66.6k | fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> { | 367 | 66.6k | let simple = self.bit_reader.read_bits::<u8>(1)? == 1; | 368 | | | 369 | 66.6k | if simple { | 370 | 63.7k | let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1; | 371 | | | 372 | 63.7k | let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?; | 373 | 63.7k | let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?; | 374 | | | 375 | 63.7k | if zero_symbol >= alphabet_size { | 376 | 4 | return Err(DecodingError::BitStreamError); | 377 | 63.7k | } | 378 | | | 379 | 63.7k | if num_symbols == 1 { | 380 | 51.7k | Ok(HuffmanTree::build_single_node(zero_symbol)) | 381 | | } else { | 382 | 11.9k | let one_symbol = self.bit_reader.read_bits::<u16>(8)?; | 383 | 11.9k | if one_symbol >= alphabet_size { | 384 | 2 | return Err(DecodingError::BitStreamError); | 385 | 11.9k | } | 386 | 11.9k | Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol)) | 387 | | } | 388 | | } else { | 389 | 2.88k | let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; | 390 | | | 391 | 2.88k | let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?; | 392 | 26.9k | for i in 0..num_code_lengths { | 393 | 26.9k | code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = | 394 | 26.9k | self.bit_reader.read_bits(3)?; | 395 | | } | 396 | | | 397 | 2.81k | let new_code_lengths = | 398 | 2.87k | self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; | 399 | | | 400 | 2.81k | HuffmanTree::build_implicit(new_code_lengths) | 401 | | } | 402 | 66.6k | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Line | Count | Source | 366 | 21.2k | fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> { | 367 | 21.2k | let simple = self.bit_reader.read_bits::<u8>(1)? == 1; | 368 | | | 369 | 21.2k | if simple { | 370 | 19.8k | let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1; | 371 | | | 372 | 19.8k | let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?; | 373 | 19.8k | let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?; | 374 | | | 375 | 19.8k | if zero_symbol >= alphabet_size { | 376 | 4 | return Err(DecodingError::BitStreamError); | 377 | 19.8k | } | 378 | | | 379 | 19.8k | if num_symbols == 1 { | 380 | 17.7k | Ok(HuffmanTree::build_single_node(zero_symbol)) | 381 | | } else { | 382 | 2.06k | let one_symbol = self.bit_reader.read_bits::<u16>(8)?; | 383 | 2.05k | if one_symbol >= alphabet_size { | 384 | 6 | return Err(DecodingError::BitStreamError); | 385 | 2.05k | } | 386 | 2.05k | Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol)) | 387 | | } | 388 | | } else { | 389 | 1.41k | let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; | 390 | | | 391 | 1.41k | let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?; | 392 | 11.4k | for i in 0..num_code_lengths { | 393 | 11.3k | code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = | 394 | 11.4k | self.bit_reader.read_bits(3)?; | 395 | | } | 396 | | | 397 | 1.25k | let new_code_lengths = | 398 | 1.38k | self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; | 399 | | | 400 | 1.25k | HuffmanTree::build_implicit(new_code_lengths) | 401 | | } | 402 | 21.2k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Line | Count | Source | 366 | 17.9k | fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> { | 367 | 17.9k | let simple = self.bit_reader.read_bits::<u8>(1)? == 1; | 368 | | | 369 | 17.9k | if simple { | 370 | 11.2k | let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1; | 371 | | | 372 | 11.2k | let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?; | 373 | 11.2k | let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?; | 374 | | | 375 | 11.2k | if zero_symbol >= alphabet_size { | 376 | 0 | return Err(DecodingError::BitStreamError); | 377 | 11.2k | } | 378 | | | 379 | 11.2k | if num_symbols == 1 { | 380 | 11.2k | Ok(HuffmanTree::build_single_node(zero_symbol)) | 381 | | } else { | 382 | 0 | let one_symbol = self.bit_reader.read_bits::<u16>(8)?; | 383 | 0 | if one_symbol >= alphabet_size { | 384 | 0 | return Err(DecodingError::BitStreamError); | 385 | 0 | } | 386 | 0 | Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol)) | 387 | | } | 388 | | } else { | 389 | 6.77k | let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES]; | 390 | | | 391 | 6.77k | let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?; | 392 | 128k | for i in 0..num_code_lengths { | 393 | 128k | code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] = | 394 | 128k | self.bit_reader.read_bits(3)?; | 395 | | } | 396 | | | 397 | 6.77k | let new_code_lengths = | 398 | 6.77k | self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?; | 399 | | | 400 | 6.77k | HuffmanTree::build_implicit(new_code_lengths) | 401 | | } | 402 | 17.9k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code |
403 | | |
404 | | /// Reads huffman code lengths |
405 | 11.0k | fn read_huffman_code_lengths( |
406 | 11.0k | &mut self, |
407 | 11.0k | code_length_code_lengths: Vec<u16>, |
408 | 11.0k | num_symbols: u16, |
409 | 11.0k | ) -> Result<Vec<u16>, DecodingError> { |
410 | 11.0k | let table = HuffmanTree::build_implicit(code_length_code_lengths)?; |
411 | | |
412 | 10.8k | let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 { |
413 | 7.17k | let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?; |
414 | 7.17k | let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?; |
415 | 7.16k | if max_minus_two > num_symbols - 2 { |
416 | 0 | return Err(DecodingError::BitStreamError); |
417 | 7.16k | } |
418 | 7.16k | 2 + max_minus_two |
419 | | } else { |
420 | 3.71k | num_symbols |
421 | | }; |
422 | | |
423 | 10.8k | let mut code_lengths = vec![0; usize::from(num_symbols)]; |
424 | 10.8k | let mut prev_code_len = 8; //default code length |
425 | | |
426 | 10.8k | let mut symbol = 0; |
427 | 1.87M | while symbol < num_symbols { |
428 | 1.86M | if max_symbol == 0 { |
429 | 2.09k | break; |
430 | 1.86M | } |
431 | 1.86M | max_symbol -= 1; |
432 | | |
433 | 1.86M | self.bit_reader.fill()?; |
434 | 1.86M | let code_len = table.read_symbol(&mut self.bit_reader)?; |
435 | | |
436 | 1.86M | if code_len < 16 { |
437 | 1.83M | code_lengths[usize::from(symbol)] = code_len; |
438 | 1.83M | symbol += 1; |
439 | 1.83M | if code_len != 0 { |
440 | 873k | prev_code_len = code_len; |
441 | 960k | } |
442 | | } else { |
443 | 26.0k | let use_prev = code_len == 16; |
444 | 26.0k | let slot = code_len - 16; |
445 | 26.0k | let extra_bits = match slot { |
446 | 15.7k | 0 => 2, |
447 | 4.41k | 1 => 3, |
448 | 5.94k | 2 => 7, |
449 | 0 | _ => return Err(DecodingError::BitStreamError), |
450 | | }; |
451 | 26.0k | let repeat_offset = match slot { |
452 | 20.1k | 0 | 1 => 3, |
453 | 5.94k | 2 => 11, |
454 | 0 | _ => return Err(DecodingError::BitStreamError), |
455 | | }; |
456 | | |
457 | 26.0k | let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset; |
458 | | |
459 | 26.0k | if symbol + repeat > num_symbols { |
460 | 16 | return Err(DecodingError::BitStreamError); |
461 | 26.0k | } |
462 | | |
463 | 26.0k | let length = if use_prev { prev_code_len } else { 0 }; |
464 | 544k | while repeat > 0 { |
465 | 518k | repeat -= 1; |
466 | 518k | code_lengths[usize::from(symbol)] = length; |
467 | 518k | symbol += 1; |
468 | 518k | } |
469 | | } |
470 | | } |
471 | | |
472 | 10.8k | Ok(code_lengths) |
473 | 11.0k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Line | Count | Source | 405 | 2.87k | fn read_huffman_code_lengths( | 406 | 2.87k | &mut self, | 407 | 2.87k | code_length_code_lengths: Vec<u16>, | 408 | 2.87k | num_symbols: u16, | 409 | 2.87k | ) -> Result<Vec<u16>, DecodingError> { | 410 | 2.87k | let table = HuffmanTree::build_implicit(code_length_code_lengths)?; | 411 | | | 412 | 2.83k | let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 { | 413 | 1.52k | let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?; | 414 | 1.52k | let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?; | 415 | 1.52k | if max_minus_two > num_symbols - 2 { | 416 | 0 | return Err(DecodingError::BitStreamError); | 417 | 1.52k | } | 418 | 1.52k | 2 + max_minus_two | 419 | | } else { | 420 | 1.31k | num_symbols | 421 | | }; | 422 | | | 423 | 2.83k | let mut code_lengths = vec![0; usize::from(num_symbols)]; | 424 | 2.83k | let mut prev_code_len = 8; //default code length | 425 | | | 426 | 2.83k | let mut symbol = 0; | 427 | 71.4k | while symbol < num_symbols { | 428 | 70.1k | if max_symbol == 0 { | 429 | 1.52k | break; | 430 | 68.6k | } | 431 | 68.6k | max_symbol -= 1; | 432 | | | 433 | 68.6k | self.bit_reader.fill()?; | 434 | 68.6k | let code_len = table.read_symbol(&mut self.bit_reader)?; | 435 | | | 436 | 68.6k | if code_len < 16 { | 437 | 48.2k | code_lengths[usize::from(symbol)] = code_len; | 438 | 48.2k | symbol += 1; | 439 | 48.2k | if code_len != 0 { | 440 | 44.4k | prev_code_len = code_len; | 441 | 44.4k | } | 442 | | } else { | 443 | 20.3k | let use_prev = code_len == 16; | 444 | 20.3k | let slot = code_len - 16; | 445 | 20.3k | let extra_bits = match slot { | 446 | 13.1k | 0 => 2, | 447 | 3.40k | 1 => 3, | 448 | 3.83k | 2 => 7, | 449 | 0 | _ => return Err(DecodingError::BitStreamError), | 450 | | }; | 451 | 20.3k | let repeat_offset = match slot { | 452 | 16.5k | 0 | 1 => 3, | 453 | 3.83k | 2 => 11, | 454 | 0 | _ => return Err(DecodingError::BitStreamError), | 455 | | }; | 456 | | | 457 | 20.3k | let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset; | 458 | | | 459 | 20.3k | if symbol + repeat > num_symbols { | 460 | 10 | return Err(DecodingError::BitStreamError); | 461 | 20.3k | } | 462 | | | 463 | 20.3k | let length = if use_prev { prev_code_len } else { 0 }; | 464 | 346k | while repeat > 0 { | 465 | 326k | repeat -= 1; | 466 | 326k | code_lengths[usize::from(symbol)] = length; | 467 | 326k | symbol += 1; | 468 | 326k | } | 469 | | } | 470 | | } | 471 | | | 472 | 2.81k | Ok(code_lengths) | 473 | 2.87k | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Line | Count | Source | 405 | 1.38k | fn read_huffman_code_lengths( | 406 | 1.38k | &mut self, | 407 | 1.38k | code_length_code_lengths: Vec<u16>, | 408 | 1.38k | num_symbols: u16, | 409 | 1.38k | ) -> Result<Vec<u16>, DecodingError> { | 410 | 1.38k | let table = HuffmanTree::build_implicit(code_length_code_lengths)?; | 411 | | | 412 | 1.27k | let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 { | 413 | 576 | let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?; | 414 | 576 | let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?; | 415 | 574 | if max_minus_two > num_symbols - 2 { | 416 | 0 | return Err(DecodingError::BitStreamError); | 417 | 574 | } | 418 | 574 | 2 + max_minus_two | 419 | | } else { | 420 | 696 | num_symbols | 421 | | }; | 422 | | | 423 | 1.27k | let mut code_lengths = vec![0; usize::from(num_symbols)]; | 424 | 1.27k | let mut prev_code_len = 8; //default code length | 425 | | | 426 | 1.27k | let mut symbol = 0; | 427 | 18.8k | while symbol < num_symbols { | 428 | 18.1k | if max_symbol == 0 { | 429 | 574 | break; | 430 | 17.6k | } | 431 | 17.6k | max_symbol -= 1; | 432 | | | 433 | 17.6k | self.bit_reader.fill()?; | 434 | 17.6k | let code_len = table.read_symbol(&mut self.bit_reader)?; | 435 | | | 436 | 17.6k | if code_len < 16 { | 437 | 11.9k | code_lengths[usize::from(symbol)] = code_len; | 438 | 11.9k | symbol += 1; | 439 | 11.9k | if code_len != 0 { | 440 | 11.2k | prev_code_len = code_len; | 441 | 11.2k | } | 442 | | } else { | 443 | 5.69k | let use_prev = code_len == 16; | 444 | 5.69k | let slot = code_len - 16; | 445 | 5.69k | let extra_bits = match slot { | 446 | 2.57k | 0 => 2, | 447 | 1.00k | 1 => 3, | 448 | 2.11k | 2 => 7, | 449 | 0 | _ => return Err(DecodingError::BitStreamError), | 450 | | }; | 451 | 5.69k | let repeat_offset = match slot { | 452 | 3.58k | 0 | 1 => 3, | 453 | 2.11k | 2 => 11, | 454 | 0 | _ => return Err(DecodingError::BitStreamError), | 455 | | }; | 456 | | | 457 | 5.69k | let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset; | 458 | | | 459 | 5.69k | if symbol + repeat > num_symbols { | 460 | 6 | return Err(DecodingError::BitStreamError); | 461 | 5.68k | } | 462 | | | 463 | 5.68k | let length = if use_prev { prev_code_len } else { 0 }; | 464 | 198k | while repeat > 0 { | 465 | 192k | repeat -= 1; | 466 | 192k | code_lengths[usize::from(symbol)] = length; | 467 | 192k | symbol += 1; | 468 | 192k | } | 469 | | } | 470 | | } | 471 | | | 472 | 1.25k | Ok(code_lengths) | 473 | 1.38k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Line | Count | Source | 405 | 6.77k | fn read_huffman_code_lengths( | 406 | 6.77k | &mut self, | 407 | 6.77k | code_length_code_lengths: Vec<u16>, | 408 | 6.77k | num_symbols: u16, | 409 | 6.77k | ) -> Result<Vec<u16>, DecodingError> { | 410 | 6.77k | let table = HuffmanTree::build_implicit(code_length_code_lengths)?; | 411 | | | 412 | 6.77k | let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 { | 413 | 5.06k | let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?; | 414 | 5.06k | let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?; | 415 | 5.06k | if max_minus_two > num_symbols - 2 { | 416 | 0 | return Err(DecodingError::BitStreamError); | 417 | 5.06k | } | 418 | 5.06k | 2 + max_minus_two | 419 | | } else { | 420 | 1.70k | num_symbols | 421 | | }; | 422 | | | 423 | 6.77k | let mut code_lengths = vec![0; usize::from(num_symbols)]; | 424 | 6.77k | let mut prev_code_len = 8; //default code length | 425 | | | 426 | 6.77k | let mut symbol = 0; | 427 | 1.78M | while symbol < num_symbols { | 428 | 1.77M | if max_symbol == 0 { | 429 | 0 | break; | 430 | 1.77M | } | 431 | 1.77M | max_symbol -= 1; | 432 | | | 433 | 1.77M | self.bit_reader.fill()?; | 434 | 1.77M | let code_len = table.read_symbol(&mut self.bit_reader)?; | 435 | | | 436 | 1.77M | if code_len < 16 { | 437 | 1.77M | code_lengths[usize::from(symbol)] = code_len; | 438 | 1.77M | symbol += 1; | 439 | 1.77M | if code_len != 0 { | 440 | 818k | prev_code_len = code_len; | 441 | 955k | } | 442 | | } else { | 443 | 0 | let use_prev = code_len == 16; | 444 | 0 | let slot = code_len - 16; | 445 | 0 | let extra_bits = match slot { | 446 | 0 | 0 => 2, | 447 | 0 | 1 => 3, | 448 | 0 | 2 => 7, | 449 | 0 | _ => return Err(DecodingError::BitStreamError), | 450 | | }; | 451 | 0 | let repeat_offset = match slot { | 452 | 0 | 0 | 1 => 3, | 453 | 0 | 2 => 11, | 454 | 0 | _ => return Err(DecodingError::BitStreamError), | 455 | | }; | 456 | | | 457 | 0 | let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset; | 458 | | | 459 | 0 | if symbol + repeat > num_symbols { | 460 | 0 | return Err(DecodingError::BitStreamError); | 461 | 0 | } | 462 | | | 463 | 0 | let length = if use_prev { prev_code_len } else { 0 }; | 464 | 0 | while repeat > 0 { | 465 | 0 | repeat -= 1; | 466 | 0 | code_lengths[usize::from(symbol)] = length; | 467 | 0 | symbol += 1; | 468 | 0 | } | 469 | | } | 470 | | } | 471 | | | 472 | 6.77k | Ok(code_lengths) | 473 | 6.77k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths |
474 | | |
475 | | /// Decodes the image data using the huffman trees and either of the 3 methods of decoding |
476 | 4.89k | fn decode_image_data( |
477 | 4.89k | &mut self, |
478 | 4.89k | width: u16, |
479 | 4.89k | height: u16, |
480 | 4.89k | mut huffman_info: HuffmanInfo, |
481 | 4.89k | data: &mut [u8], |
482 | 4.89k | ) -> Result<(), DecodingError> { |
483 | 4.89k | let num_values = usize::from(width) * usize::from(height); |
484 | | |
485 | 4.89k | let huff_index = huffman_info.get_huff_index(0, 0); |
486 | 4.89k | let mut tree = &huffman_info.huffman_code_groups[huff_index]; |
487 | 4.89k | let mut index = 0; |
488 | | |
489 | 4.89k | let mut next_block_start = 0; |
490 | 32.0M | while index < num_values { |
491 | 32.0M | self.bit_reader.fill()?; |
492 | | |
493 | 32.0M | if index >= next_block_start { |
494 | 1.80M | let x = index % usize::from(width); |
495 | 1.80M | let y = index / usize::from(width); |
496 | 1.80M | next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1)) |
497 | 1.80M | + y * usize::from(width) |
498 | 1.80M | + 1; |
499 | | |
500 | 1.80M | let huff_index = huffman_info.get_huff_index(x as u16, y as u16); |
501 | 1.80M | tree = &huffman_info.huffman_code_groups[huff_index]; |
502 | | |
503 | | // Fast path: If all the codes each contain only a single |
504 | | // symbol, then the pixel data isn't written to the bitstream |
505 | | // and we can just fill the output buffer with the symbol |
506 | | // directly. |
507 | 4.73M | if tree[..4].iter().all(|t| t.is_single_node()) {<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Line | Count | Source | 507 | 3.99M | if tree[..4].iter().all(|t| t.is_single_node()) { |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Line | Count | Source | 507 | 559k | if tree[..4].iter().all(|t| t.is_single_node()) { |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Line | Count | Source | 507 | 177k | if tree[..4].iter().all(|t| t.is_single_node()) { |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0}Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data::{closure#0} |
508 | 976k | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; |
509 | 976k | if code < 256 { |
510 | 976k | let n = if huffman_info.bits == 0 { |
511 | 2.05k | num_values |
512 | | } else { |
513 | 974k | next_block_start - index |
514 | | }; |
515 | | |
516 | 976k | let red = tree[RED].read_symbol(&mut self.bit_reader)?; |
517 | 976k | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; |
518 | 976k | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; |
519 | 976k | let value = [red as u8, code as u8, blue as u8, alpha as u8]; |
520 | | |
521 | 118M | for i in 0..n { |
522 | 118M | data[index * 4 + i * 4..][..4].copy_from_slice(&value); |
523 | 118M | } |
524 | | |
525 | 976k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { |
526 | 61 | color_cache.insert(value); |
527 | 976k | } |
528 | | |
529 | 976k | index += n; |
530 | 976k | continue; |
531 | 0 | } |
532 | 825k | } |
533 | 30.2M | } |
534 | | |
535 | 31.0M | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; |
536 | | |
537 | | //check code |
538 | 31.0M | if code < 256 { |
539 | | //literal, so just use huffman codes and read as argb |
540 | 20.6M | let green = code as u8; |
541 | 20.6M | let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8; |
542 | 20.6M | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8; |
543 | 20.6M | if self.bit_reader.nbits < 15 { |
544 | 4.91k | self.bit_reader.fill()?; |
545 | 20.6M | } |
546 | 20.6M | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8; |
547 | | |
548 | 20.6M | data[index * 4] = red; |
549 | 20.6M | data[index * 4 + 1] = green; |
550 | 20.6M | data[index * 4 + 2] = blue; |
551 | 20.6M | data[index * 4 + 3] = alpha; |
552 | | |
553 | 20.6M | if let Some(color_cache) = huffman_info.color_cache.as_mut() { |
554 | 4.53M | color_cache.insert([red, green, blue, alpha]); |
555 | 16.1M | } |
556 | 20.6M | index += 1; |
557 | 10.4M | } else if code < 256 + 24 { |
558 | | //backward reference, so go back and use that to add image data |
559 | 7.57M | let length_symbol = code - 256; |
560 | 7.57M | let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; |
561 | | |
562 | 7.57M | let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; |
563 | 7.57M | let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; |
564 | 7.57M | let dist = Self::plane_code_to_distance(width, dist_code); |
565 | | |
566 | 7.57M | if index < dist || num_values - index < length { |
567 | 57 | return Err(DecodingError::BitStreamError); |
568 | 7.57M | } |
569 | | |
570 | 7.57M | if dist == 1 { |
571 | 3.95M | let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap(); |
572 | 1.90G | for i in 0..length { |
573 | 1.90G | data[index * 4 + i * 4..][..4].copy_from_slice(&value); |
574 | 1.90G | } |
575 | | } else { |
576 | 3.61M | if index + length + 3 <= num_values { |
577 | 3.61M | let start = (index - dist) * 4; |
578 | 3.61M | data.copy_within(start..start + 16, index * 4); |
579 | | |
580 | 3.61M | if length > 4 || dist < 4 { |
581 | 250M | for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) { |
582 | 250M | data.copy_within(start + i..start + i + 16, index * 4 + i); |
583 | 250M | } |
584 | 9.68k | } |
585 | | } else { |
586 | 64.3k | for i in 0..length * 4 { |
587 | 64.3k | data[index * 4 + i] = data[index * 4 + i - dist * 4]; |
588 | 64.3k | } |
589 | | } |
590 | | |
591 | 3.61M | if let Some(color_cache) = huffman_info.color_cache.as_mut() { |
592 | 1.00G | for pixel in data[index * 4..][..length * 4].chunks_exact(4) { |
593 | 1.00G | color_cache.insert(pixel.try_into().unwrap()); |
594 | 1.00G | } |
595 | 29.8k | } |
596 | | } |
597 | 7.57M | index += length; |
598 | | } else { |
599 | | //color cache, so use previously stored pixels to get this pixel |
600 | 2.87M | let color_cache = huffman_info |
601 | 2.87M | .color_cache |
602 | 2.87M | .as_mut() |
603 | 2.87M | .ok_or(DecodingError::BitStreamError)?; |
604 | 2.87M | let color = color_cache.lookup((code - 280).into()); |
605 | 2.87M | data[index * 4..][..4].copy_from_slice(&color); |
606 | 2.87M | index += 1; |
607 | | |
608 | 2.87M | if index < next_block_start { |
609 | 2.87M | if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) { |
610 | 2.87M | if code >= 280 { |
611 | 794k | self.bit_reader.consume(bits)?; |
612 | 794k | data[index * 4..][..4] |
613 | 794k | .copy_from_slice(&color_cache.lookup((code - 280).into())); |
614 | 794k | index += 1; |
615 | 2.07M | } |
616 | 350 | } |
617 | 2.10k | } |
618 | | } |
619 | | } |
620 | | |
621 | 4.55k | Ok(()) |
622 | 4.89k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Line | Count | Source | 476 | 473 | fn decode_image_data( | 477 | 473 | &mut self, | 478 | 473 | width: u16, | 479 | 473 | height: u16, | 480 | 473 | mut huffman_info: HuffmanInfo, | 481 | 473 | data: &mut [u8], | 482 | 473 | ) -> Result<(), DecodingError> { | 483 | 473 | let num_values = usize::from(width) * usize::from(height); | 484 | | | 485 | 473 | let huff_index = huffman_info.get_huff_index(0, 0); | 486 | 473 | let mut tree = &huffman_info.huffman_code_groups[huff_index]; | 487 | 473 | let mut index = 0; | 488 | | | 489 | 473 | let mut next_block_start = 0; | 490 | 2.51M | while index < num_values { | 491 | 2.51M | self.bit_reader.fill()?; | 492 | | | 493 | 2.51M | if index >= next_block_start { | 494 | 1.12M | let x = index % usize::from(width); | 495 | 1.12M | let y = index / usize::from(width); | 496 | 1.12M | next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1)) | 497 | 1.12M | + y * usize::from(width) | 498 | 1.12M | + 1; | 499 | | | 500 | 1.12M | let huff_index = huffman_info.get_huff_index(x as u16, y as u16); | 501 | 1.12M | tree = &huffman_info.huffman_code_groups[huff_index]; | 502 | | | 503 | | // Fast path: If all the codes each contain only a single | 504 | | // symbol, then the pixel data isn't written to the bitstream | 505 | | // and we can just fill the output buffer with the symbol | 506 | | // directly. | 507 | 1.12M | if tree[..4].iter().all(|t| t.is_single_node()) { | 508 | 959k | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 509 | 959k | if code < 256 { | 510 | 959k | let n = if huffman_info.bits == 0 { | 511 | 36 | num_values | 512 | | } else { | 513 | 959k | next_block_start - index | 514 | | }; | 515 | | | 516 | 959k | let red = tree[RED].read_symbol(&mut self.bit_reader)?; | 517 | 959k | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; | 518 | 959k | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; | 519 | 959k | let value = [red as u8, code as u8, blue as u8, alpha as u8]; | 520 | | | 521 | 84.7M | for i in 0..n { | 522 | 84.7M | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 523 | 84.7M | } | 524 | | | 525 | 959k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 526 | 20 | color_cache.insert(value); | 527 | 959k | } | 528 | | | 529 | 959k | index += n; | 530 | 959k | continue; | 531 | 0 | } | 532 | 162k | } | 533 | 1.38M | } | 534 | | | 535 | 1.55M | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 536 | | | 537 | | //check code | 538 | 1.55M | if code < 256 { | 539 | | //literal, so just use huffman codes and read as argb | 540 | 859k | let green = code as u8; | 541 | 859k | let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8; | 542 | 859k | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8; | 543 | 859k | if self.bit_reader.nbits < 15 { | 544 | 325 | self.bit_reader.fill()?; | 545 | 858k | } | 546 | 859k | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8; | 547 | | | 548 | 859k | data[index * 4] = red; | 549 | 859k | data[index * 4 + 1] = green; | 550 | 859k | data[index * 4 + 2] = blue; | 551 | 859k | data[index * 4 + 3] = alpha; | 552 | | | 553 | 859k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 554 | 772k | color_cache.insert([red, green, blue, alpha]); | 555 | 772k | } | 556 | 859k | index += 1; | 557 | 691k | } else if code < 256 + 24 { | 558 | | //backward reference, so go back and use that to add image data | 559 | 646k | let length_symbol = code - 256; | 560 | 646k | let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; | 561 | | | 562 | 646k | let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; | 563 | 646k | let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; | 564 | 646k | let dist = Self::plane_code_to_distance(width, dist_code); | 565 | | | 566 | 646k | if index < dist || num_values - index < length { | 567 | 26 | return Err(DecodingError::BitStreamError); | 568 | 646k | } | 569 | | | 570 | 646k | if dist == 1 { | 571 | 455k | let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap(); | 572 | 1.48G | for i in 0..length { | 573 | 1.48G | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 574 | 1.48G | } | 575 | | } else { | 576 | 190k | if index + length + 3 <= num_values { | 577 | 190k | let start = (index - dist) * 4; | 578 | 190k | data.copy_within(start..start + 16, index * 4); | 579 | | | 580 | 190k | if length > 4 || dist < 4 { | 581 | 147M | for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) { | 582 | 147M | data.copy_within(start + i..start + i + 16, index * 4 + i); | 583 | 147M | } | 584 | 7.66k | } | 585 | | } else { | 586 | 6.17k | for i in 0..length * 4 { | 587 | 6.17k | data[index * 4 + i] = data[index * 4 + i - dist * 4]; | 588 | 6.17k | } | 589 | | } | 590 | | | 591 | 190k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 592 | 590M | for pixel in data[index * 4..][..length * 4].chunks_exact(4) { | 593 | 590M | color_cache.insert(pixel.try_into().unwrap()); | 594 | 590M | } | 595 | 3.75k | } | 596 | | } | 597 | 646k | index += length; | 598 | | } else { | 599 | | //color cache, so use previously stored pixels to get this pixel | 600 | 44.9k | let color_cache = huffman_info | 601 | 44.9k | .color_cache | 602 | 44.9k | .as_mut() | 603 | 44.9k | .ok_or(DecodingError::BitStreamError)?; | 604 | 44.9k | let color = color_cache.lookup((code - 280).into()); | 605 | 44.9k | data[index * 4..][..4].copy_from_slice(&color); | 606 | 44.9k | index += 1; | 607 | | | 608 | 44.9k | if index < next_block_start { | 609 | 44.5k | if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) { | 610 | 44.2k | if code >= 280 { | 611 | 26.2k | self.bit_reader.consume(bits)?; | 612 | 26.2k | data[index * 4..][..4] | 613 | 26.2k | .copy_from_slice(&color_cache.lookup((code - 280).into())); | 614 | 26.2k | index += 1; | 615 | 17.9k | } | 616 | 340 | } | 617 | 397 | } | 618 | | } | 619 | | } | 620 | | | 621 | 327 | Ok(()) | 622 | 473 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Line | Count | Source | 476 | 830 | fn decode_image_data( | 477 | 830 | &mut self, | 478 | 830 | width: u16, | 479 | 830 | height: u16, | 480 | 830 | mut huffman_info: HuffmanInfo, | 481 | 830 | data: &mut [u8], | 482 | 830 | ) -> Result<(), DecodingError> { | 483 | 830 | let num_values = usize::from(width) * usize::from(height); | 484 | | | 485 | 830 | let huff_index = huffman_info.get_huff_index(0, 0); | 486 | 830 | let mut tree = &huffman_info.huffman_code_groups[huff_index]; | 487 | 830 | let mut index = 0; | 488 | | | 489 | 830 | let mut next_block_start = 0; | 490 | 13.5M | while index < num_values { | 491 | 13.5M | self.bit_reader.fill()?; | 492 | | | 493 | 13.5M | if index >= next_block_start { | 494 | 510k | let x = index % usize::from(width); | 495 | 510k | let y = index / usize::from(width); | 496 | 510k | next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1)) | 497 | 510k | + y * usize::from(width) | 498 | 510k | + 1; | 499 | | | 500 | 510k | let huff_index = huffman_info.get_huff_index(x as u16, y as u16); | 501 | 510k | tree = &huffman_info.huffman_code_groups[huff_index]; | 502 | | | 503 | | // Fast path: If all the codes each contain only a single | 504 | | // symbol, then the pixel data isn't written to the bitstream | 505 | | // and we can just fill the output buffer with the symbol | 506 | | // directly. | 507 | 510k | if tree[..4].iter().all(|t| t.is_single_node()) { | 508 | 15.6k | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 509 | 15.6k | if code < 256 { | 510 | 15.6k | let n = if huffman_info.bits == 0 { | 511 | 185 | num_values | 512 | | } else { | 513 | 15.4k | next_block_start - index | 514 | | }; | 515 | | | 516 | 15.6k | let red = tree[RED].read_symbol(&mut self.bit_reader)?; | 517 | 15.6k | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; | 518 | 15.6k | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; | 519 | 15.6k | let value = [red as u8, code as u8, blue as u8, alpha as u8]; | 520 | | | 521 | 33.3M | for i in 0..n { | 522 | 33.3M | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 523 | 33.3M | } | 524 | | | 525 | 15.6k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 526 | 41 | color_cache.insert(value); | 527 | 15.6k | } | 528 | | | 529 | 15.6k | index += n; | 530 | 15.6k | continue; | 531 | 0 | } | 532 | 494k | } | 533 | 13.0M | } | 534 | | | 535 | 13.4M | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 536 | | | 537 | | //check code | 538 | 13.4M | if code < 256 { | 539 | | //literal, so just use huffman codes and read as argb | 540 | 3.86M | let green = code as u8; | 541 | 3.86M | let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8; | 542 | 3.86M | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8; | 543 | 3.86M | if self.bit_reader.nbits < 15 { | 544 | 271 | self.bit_reader.fill()?; | 545 | 3.86M | } | 546 | 3.86M | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8; | 547 | | | 548 | 3.86M | data[index * 4] = red; | 549 | 3.86M | data[index * 4 + 1] = green; | 550 | 3.86M | data[index * 4 + 2] = blue; | 551 | 3.86M | data[index * 4 + 3] = alpha; | 552 | | | 553 | 3.86M | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 554 | 3.75M | color_cache.insert([red, green, blue, alpha]); | 555 | 3.75M | } | 556 | 3.86M | index += 1; | 557 | 9.63M | } else if code < 256 + 24 { | 558 | | //backward reference, so go back and use that to add image data | 559 | 6.79M | let length_symbol = code - 256; | 560 | 6.79M | let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; | 561 | | | 562 | 6.79M | let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; | 563 | 6.79M | let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; | 564 | 6.79M | let dist = Self::plane_code_to_distance(width, dist_code); | 565 | | | 566 | 6.79M | if index < dist || num_values - index < length { | 567 | 31 | return Err(DecodingError::BitStreamError); | 568 | 6.79M | } | 569 | | | 570 | 6.79M | if dist == 1 { | 571 | 3.37M | let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap(); | 572 | 409M | for i in 0..length { | 573 | 409M | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 574 | 409M | } | 575 | | } else { | 576 | 3.42M | if index + length + 3 <= num_values { | 577 | 3.42M | let start = (index - dist) * 4; | 578 | 3.42M | data.copy_within(start..start + 16, index * 4); | 579 | | | 580 | 3.42M | if length > 4 || dist < 4 { | 581 | 103M | for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) { | 582 | 103M | data.copy_within(start + i..start + i + 16, index * 4 + i); | 583 | 103M | } | 584 | 2.02k | } | 585 | | } else { | 586 | 58.1k | for i in 0..length * 4 { | 587 | 58.1k | data[index * 4 + i] = data[index * 4 + i - dist * 4]; | 588 | 58.1k | } | 589 | | } | 590 | | | 591 | 3.42M | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 592 | 419M | for pixel in data[index * 4..][..length * 4].chunks_exact(4) { | 593 | 419M | color_cache.insert(pixel.try_into().unwrap()); | 594 | 419M | } | 595 | 26.1k | } | 596 | | } | 597 | 6.79M | index += length; | 598 | | } else { | 599 | | //color cache, so use previously stored pixels to get this pixel | 600 | 2.83M | let color_cache = huffman_info | 601 | 2.83M | .color_cache | 602 | 2.83M | .as_mut() | 603 | 2.83M | .ok_or(DecodingError::BitStreamError)?; | 604 | 2.83M | let color = color_cache.lookup((code - 280).into()); | 605 | 2.83M | data[index * 4..][..4].copy_from_slice(&color); | 606 | 2.83M | index += 1; | 607 | | | 608 | 2.83M | if index < next_block_start { | 609 | 2.82M | if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) { | 610 | 2.82M | if code >= 280 { | 611 | 768k | self.bit_reader.consume(bits)?; | 612 | 768k | data[index * 4..][..4] | 613 | 768k | .copy_from_slice(&color_cache.lookup((code - 280).into())); | 614 | 768k | index += 1; | 615 | 2.06M | } | 616 | 10 | } | 617 | 1.70k | } | 618 | | } | 619 | | } | 620 | | | 621 | 632 | Ok(()) | 622 | 830 | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Line | Count | Source | 476 | 3.59k | fn decode_image_data( | 477 | 3.59k | &mut self, | 478 | 3.59k | width: u16, | 479 | 3.59k | height: u16, | 480 | 3.59k | mut huffman_info: HuffmanInfo, | 481 | 3.59k | data: &mut [u8], | 482 | 3.59k | ) -> Result<(), DecodingError> { | 483 | 3.59k | let num_values = usize::from(width) * usize::from(height); | 484 | | | 485 | 3.59k | let huff_index = huffman_info.get_huff_index(0, 0); | 486 | 3.59k | let mut tree = &huffman_info.huffman_code_groups[huff_index]; | 487 | 3.59k | let mut index = 0; | 488 | | | 489 | 3.59k | let mut next_block_start = 0; | 490 | 16.0M | while index < num_values { | 491 | 16.0M | self.bit_reader.fill()?; | 492 | | | 493 | 16.0M | if index >= next_block_start { | 494 | 170k | let x = index % usize::from(width); | 495 | 170k | let y = index / usize::from(width); | 496 | 170k | next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1)) | 497 | 170k | + y * usize::from(width) | 498 | 170k | + 1; | 499 | | | 500 | 170k | let huff_index = huffman_info.get_huff_index(x as u16, y as u16); | 501 | 170k | tree = &huffman_info.huffman_code_groups[huff_index]; | 502 | | | 503 | | // Fast path: If all the codes each contain only a single | 504 | | // symbol, then the pixel data isn't written to the bitstream | 505 | | // and we can just fill the output buffer with the symbol | 506 | | // directly. | 507 | 170k | if tree[..4].iter().all(|t| t.is_single_node()) { | 508 | 1.83k | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 509 | 1.83k | if code < 256 { | 510 | 1.83k | let n = if huffman_info.bits == 0 { | 511 | 1.83k | num_values | 512 | | } else { | 513 | 0 | next_block_start - index | 514 | | }; | 515 | | | 516 | 1.83k | let red = tree[RED].read_symbol(&mut self.bit_reader)?; | 517 | 1.83k | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?; | 518 | 1.83k | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?; | 519 | 1.83k | let value = [red as u8, code as u8, blue as u8, alpha as u8]; | 520 | | | 521 | 1.83k | for i in 0..n { | 522 | 1.83k | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 523 | 1.83k | } | 524 | | | 525 | 1.83k | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 526 | 0 | color_cache.insert(value); | 527 | 1.83k | } | 528 | | | 529 | 1.83k | index += n; | 530 | 1.83k | continue; | 531 | 0 | } | 532 | 168k | } | 533 | 15.8M | } | 534 | | | 535 | 16.0M | let code = tree[GREEN].read_symbol(&mut self.bit_reader)?; | 536 | | | 537 | | //check code | 538 | 16.0M | if code < 256 { | 539 | | //literal, so just use huffman codes and read as argb | 540 | 15.9M | let green = code as u8; | 541 | 15.9M | let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8; | 542 | 15.9M | let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8; | 543 | 15.9M | if self.bit_reader.nbits < 15 { | 544 | 4.31k | self.bit_reader.fill()?; | 545 | 15.9M | } | 546 | 15.9M | let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8; | 547 | | | 548 | 15.9M | data[index * 4] = red; | 549 | 15.9M | data[index * 4 + 1] = green; | 550 | 15.9M | data[index * 4 + 2] = blue; | 551 | 15.9M | data[index * 4 + 3] = alpha; | 552 | | | 553 | 15.9M | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 554 | 0 | color_cache.insert([red, green, blue, alpha]); | 555 | 15.9M | } | 556 | 15.9M | index += 1; | 557 | 127k | } else if code < 256 + 24 { | 558 | | //backward reference, so go back and use that to add image data | 559 | 127k | let length_symbol = code - 256; | 560 | 127k | let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?; | 561 | | | 562 | 127k | let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?; | 563 | 127k | let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?; | 564 | 127k | let dist = Self::plane_code_to_distance(width, dist_code); | 565 | | | 566 | 127k | if index < dist || num_values - index < length { | 567 | 0 | return Err(DecodingError::BitStreamError); | 568 | 127k | } | 569 | | | 570 | 127k | if dist == 1 { | 571 | 127k | let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap(); | 572 | 1.35M | for i in 0..length { | 573 | 1.35M | data[index * 4 + i * 4..][..4].copy_from_slice(&value); | 574 | 1.35M | } | 575 | | } else { | 576 | 0 | if index + length + 3 <= num_values { | 577 | 0 | let start = (index - dist) * 4; | 578 | 0 | data.copy_within(start..start + 16, index * 4); | 579 | | | 580 | 0 | if length > 4 || dist < 4 { | 581 | 0 | for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) { | 582 | 0 | data.copy_within(start + i..start + i + 16, index * 4 + i); | 583 | 0 | } | 584 | 0 | } | 585 | | } else { | 586 | 0 | for i in 0..length * 4 { | 587 | 0 | data[index * 4 + i] = data[index * 4 + i - dist * 4]; | 588 | 0 | } | 589 | | } | 590 | | | 591 | 0 | if let Some(color_cache) = huffman_info.color_cache.as_mut() { | 592 | 0 | for pixel in data[index * 4..][..length * 4].chunks_exact(4) { | 593 | 0 | color_cache.insert(pixel.try_into().unwrap()); | 594 | 0 | } | 595 | 0 | } | 596 | | } | 597 | 127k | index += length; | 598 | | } else { | 599 | | //color cache, so use previously stored pixels to get this pixel | 600 | 0 | let color_cache = huffman_info | 601 | 0 | .color_cache | 602 | 0 | .as_mut() | 603 | 0 | .ok_or(DecodingError::BitStreamError)?; | 604 | 0 | let color = color_cache.lookup((code - 280).into()); | 605 | 0 | data[index * 4..][..4].copy_from_slice(&color); | 606 | 0 | index += 1; | 607 | | | 608 | 0 | if index < next_block_start { | 609 | 0 | if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) { | 610 | 0 | if code >= 280 { | 611 | 0 | self.bit_reader.consume(bits)?; | 612 | 0 | data[index * 4..][..4] | 613 | 0 | .copy_from_slice(&color_cache.lookup((code - 280).into())); | 614 | 0 | index += 1; | 615 | 0 | } | 616 | 0 | } | 617 | 0 | } | 618 | | } | 619 | | } | 620 | | | 621 | 3.59k | Ok(()) | 622 | 3.59k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data |
623 | | |
624 | | /// Reads color cache data from the bitstream |
625 | 5.28k | fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> { |
626 | 5.28k | if self.bit_reader.read_bits::<u8>(1)? == 1 { |
627 | 648 | let code_bits = self.bit_reader.read_bits::<u8>(4)?; |
628 | | |
629 | 647 | if !(1..=11).contains(&code_bits) { |
630 | 13 | return Err(DecodingError::InvalidColorCacheBits(code_bits)); |
631 | 634 | } |
632 | | |
633 | 634 | Ok(Some(code_bits)) |
634 | | } else { |
635 | 4.63k | Ok(None) |
636 | | } |
637 | 5.28k | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Line | Count | Source | 625 | 621 | fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> { | 626 | 621 | if self.bit_reader.read_bits::<u8>(1)? == 1 { | 627 | 295 | let code_bits = self.bit_reader.read_bits::<u8>(4)?; | 628 | | | 629 | 295 | if !(1..=11).contains(&code_bits) { | 630 | 0 | return Err(DecodingError::InvalidColorCacheBits(code_bits)); | 631 | 295 | } | 632 | | | 633 | 295 | Ok(Some(code_bits)) | 634 | | } else { | 635 | 326 | Ok(None) | 636 | | } | 637 | 621 | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Line | Count | Source | 625 | 1.06k | fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> { | 626 | 1.06k | if self.bit_reader.read_bits::<u8>(1)? == 1 { | 627 | 353 | let code_bits = self.bit_reader.read_bits::<u8>(4)?; | 628 | | | 629 | 352 | if !(1..=11).contains(&code_bits) { | 630 | 13 | return Err(DecodingError::InvalidColorCacheBits(code_bits)); | 631 | 339 | } | 632 | | | 633 | 339 | Ok(Some(code_bits)) | 634 | | } else { | 635 | 716 | Ok(None) | 636 | | } | 637 | 1.06k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Line | Count | Source | 625 | 3.59k | fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> { | 626 | 3.59k | if self.bit_reader.read_bits::<u8>(1)? == 1 { | 627 | 0 | let code_bits = self.bit_reader.read_bits::<u8>(4)?; | 628 | | | 629 | 0 | if !(1..=11).contains(&code_bits) { | 630 | 0 | return Err(DecodingError::InvalidColorCacheBits(code_bits)); | 631 | 0 | } | 632 | | | 633 | 0 | Ok(Some(code_bits)) | 634 | | } else { | 635 | 3.59k | Ok(None) | 636 | | } | 637 | 3.59k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache |
638 | | |
639 | | /// Gets the copy distance from the prefix code and bitstream |
640 | 15.1M | fn get_copy_distance( |
641 | 15.1M | bit_reader: &mut BitReader<R>, |
642 | 15.1M | prefix_code: u16, |
643 | 15.1M | ) -> Result<usize, DecodingError> { |
644 | 15.1M | if prefix_code < 4 { |
645 | 4.29M | return Ok(usize::from(prefix_code + 1)); |
646 | 10.8M | } |
647 | 10.8M | let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); |
648 | 10.8M | let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; |
649 | | |
650 | 10.8M | let bits = bit_reader.peek(extra_bits) as usize; |
651 | 10.8M | bit_reader.consume(extra_bits)?; |
652 | | |
653 | 10.8M | Ok(offset + bits + 1) |
654 | 15.1M | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Line | Count | Source | 640 | 1.29M | fn get_copy_distance( | 641 | 1.29M | bit_reader: &mut BitReader<R>, | 642 | 1.29M | prefix_code: u16, | 643 | 1.29M | ) -> Result<usize, DecodingError> { | 644 | 1.29M | if prefix_code < 4 { | 645 | 479k | return Ok(usize::from(prefix_code + 1)); | 646 | 813k | } | 647 | 813k | let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); | 648 | 813k | let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; | 649 | | | 650 | 813k | let bits = bit_reader.peek(extra_bits) as usize; | 651 | 813k | bit_reader.consume(extra_bits)?; | 652 | | | 653 | 813k | Ok(offset + bits + 1) | 654 | 1.29M | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Line | Count | Source | 640 | 13.5M | fn get_copy_distance( | 641 | 13.5M | bit_reader: &mut BitReader<R>, | 642 | 13.5M | prefix_code: u16, | 643 | 13.5M | ) -> Result<usize, DecodingError> { | 644 | 13.5M | if prefix_code < 4 { | 645 | 3.58M | return Ok(usize::from(prefix_code + 1)); | 646 | 10.0M | } | 647 | 10.0M | let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); | 648 | 10.0M | let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; | 649 | | | 650 | 10.0M | let bits = bit_reader.peek(extra_bits) as usize; | 651 | 10.0M | bit_reader.consume(extra_bits)?; | 652 | | | 653 | 10.0M | Ok(offset + bits + 1) | 654 | 13.5M | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Line | Count | Source | 640 | 254k | fn get_copy_distance( | 641 | 254k | bit_reader: &mut BitReader<R>, | 642 | 254k | prefix_code: u16, | 643 | 254k | ) -> Result<usize, DecodingError> { | 644 | 254k | if prefix_code < 4 { | 645 | 223k | return Ok(usize::from(prefix_code + 1)); | 646 | 31.8k | } | 647 | 31.8k | let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap(); | 648 | 31.8k | let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits; | 649 | | | 650 | 31.8k | let bits = bit_reader.peek(extra_bits) as usize; | 651 | 31.8k | bit_reader.consume(extra_bits)?; | 652 | | | 653 | 31.8k | Ok(offset + bits + 1) | 654 | 254k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance |
655 | | |
656 | | /// Gets distance to pixel |
657 | 7.57M | fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { |
658 | 7.57M | if plane_code > 120 { |
659 | 3.39M | plane_code - 120 |
660 | | } else { |
661 | 4.17M | let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; |
662 | | |
663 | 4.17M | let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); |
664 | 4.17M | if dist < 1 { |
665 | 0 | return 1; |
666 | 4.17M | } |
667 | 4.17M | dist.try_into().unwrap() |
668 | | } |
669 | 7.57M | } <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Line | Count | Source | 657 | 646k | fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { | 658 | 646k | if plane_code > 120 { | 659 | 186k | plane_code - 120 | 660 | | } else { | 661 | 460k | let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; | 662 | | | 663 | 460k | let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); | 664 | 460k | if dist < 1 { | 665 | 0 | return 1; | 666 | 460k | } | 667 | 460k | dist.try_into().unwrap() | 668 | | } | 669 | 646k | } |
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Line | Count | Source | 657 | 6.79M | fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { | 658 | 6.79M | if plane_code > 120 { | 659 | 3.21M | plane_code - 120 | 660 | | } else { | 661 | 3.58M | let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; | 662 | | | 663 | 3.58M | let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); | 664 | 3.58M | if dist < 1 { | 665 | 0 | return 1; | 666 | 3.58M | } | 667 | 3.58M | dist.try_into().unwrap() | 668 | | } | 669 | 6.79M | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Line | Count | Source | 657 | 127k | fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize { | 658 | 127k | if plane_code > 120 { | 659 | 0 | plane_code - 120 | 660 | | } else { | 661 | 127k | let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1]; | 662 | | | 663 | 127k | let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize); | 664 | 127k | if dist < 1 { | 665 | 0 | return 1; | 666 | 127k | } | 667 | 127k | dist.try_into().unwrap() | 668 | | } | 669 | 127k | } |
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance |
670 | | } |
671 | | |
672 | | #[derive(Debug, Clone)] |
673 | | struct HuffmanInfo { |
674 | | xsize: u16, |
675 | | _ysize: u16, |
676 | | color_cache: Option<ColorCache>, |
677 | | image: Vec<u16>, |
678 | | bits: u8, |
679 | | mask: u16, |
680 | | huffman_code_groups: Vec<HuffmanCodeGroup>, |
681 | | } |
682 | | |
683 | | impl HuffmanInfo { |
684 | 1.80M | fn get_huff_index(&self, x: u16, y: u16) -> usize { |
685 | 1.80M | if self.bits == 0 { |
686 | 813k | return 0; |
687 | 993k | } |
688 | 993k | let position = |
689 | 993k | usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits); |
690 | 993k | let meta_huff_code: usize = usize::from(self.image[position]); |
691 | 993k | meta_huff_code |
692 | 1.80M | } |
693 | | } |
694 | | |
695 | | #[derive(Debug, Clone)] |
696 | | struct ColorCache { |
697 | | color_cache_bits: u8, |
698 | | color_cache: Vec<[u8; 4]>, |
699 | | } |
700 | | |
701 | | impl ColorCache { |
702 | | #[inline(always)] |
703 | 1.01G | fn insert(&mut self, color: [u8; 4]) { |
704 | 1.01G | let [r, g, b, a] = color; |
705 | 1.01G | let color_u32 = |
706 | 1.01G | (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24); |
707 | 1.01G | let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits); |
708 | 1.01G | self.color_cache[index as usize] = color; |
709 | 1.01G | } |
710 | | |
711 | | #[inline(always)] |
712 | 3.67M | fn lookup(&self, index: usize) -> [u8; 4] { |
713 | 3.67M | self.color_cache[index] |
714 | 3.67M | } |
715 | | } |
716 | | |
717 | | #[derive(Debug, Clone)] |
718 | | pub(crate) struct BitReader<R> { |
719 | | reader: R, |
720 | | buffer: u64, |
721 | | nbits: u8, |
722 | | } |
723 | | |
724 | | impl<R: BufRead> BitReader<R> { |
725 | 2.63k | const fn new(reader: R) -> Self { |
726 | 2.63k | Self { |
727 | 2.63k | reader, |
728 | 2.63k | buffer: 0, |
729 | 2.63k | nbits: 0, |
730 | 2.63k | } |
731 | 2.63k | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 725 | 318 | const fn new(reader: R) -> Self { | 726 | 318 | Self { | 727 | 318 | reader, | 728 | 318 | buffer: 0, | 729 | 318 | nbits: 0, | 730 | 318 | } | 731 | 318 | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 725 | 517 | const fn new(reader: R) -> Self { | 726 | 517 | Self { | 727 | 517 | reader, | 728 | 517 | buffer: 0, | 729 | 517 | nbits: 0, | 730 | 517 | } | 731 | 517 | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Line | Count | Source | 725 | 1.79k | const fn new(reader: R) -> Self { | 726 | 1.79k | Self { | 727 | 1.79k | reader, | 728 | 1.79k | buffer: 0, | 729 | 1.79k | nbits: 0, | 730 | 1.79k | } | 731 | 1.79k | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new |
732 | | |
733 | | /// Fills the buffer with bits from the input stream. |
734 | | /// |
735 | | /// After this function, the internal buffer will contain 64-bits or have reached the end of |
736 | | /// the input stream. |
737 | 33.9M | pub(crate) fn fill(&mut self) -> Result<(), DecodingError> { |
738 | 33.9M | debug_assert!(self.nbits < 64); |
739 | | |
740 | 33.9M | let mut buf = self.reader.fill_buf()?; |
741 | 33.9M | if buf.len() >= 8 { |
742 | 33.8M | let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap()); |
743 | 33.8M | self.reader.consume(usize::from((63 - self.nbits) / 8)); |
744 | 33.8M | self.buffer |= lookahead << self.nbits; |
745 | 33.8M | self.nbits |= 56; |
746 | 33.8M | } else { |
747 | 69.1k | while !buf.is_empty() && self.nbits < 56 { |
748 | 14.7k | self.buffer |= u64::from(buf[0]) << self.nbits; |
749 | 14.7k | self.nbits += 8; |
750 | 14.7k | self.reader.consume(1); |
751 | 14.7k | buf = self.reader.fill_buf()?; |
752 | | } |
753 | | } |
754 | | |
755 | 33.9M | Ok(()) |
756 | 33.9M | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Line | Count | Source | 737 | 2.58M | pub(crate) fn fill(&mut self) -> Result<(), DecodingError> { | 738 | 2.58M | debug_assert!(self.nbits < 64); | 739 | | | 740 | 2.58M | let mut buf = self.reader.fill_buf()?; | 741 | 2.58M | if buf.len() >= 8 { | 742 | 2.57M | let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap()); | 743 | 2.57M | self.reader.consume(usize::from((63 - self.nbits) / 8)); | 744 | 2.57M | self.buffer |= lookahead << self.nbits; | 745 | 2.57M | self.nbits |= 56; | 746 | 2.57M | } else { | 747 | 9.03k | while !buf.is_empty() && self.nbits < 56 { | 748 | 1.28k | self.buffer |= u64::from(buf[0]) << self.nbits; | 749 | 1.28k | self.nbits += 8; | 750 | 1.28k | self.reader.consume(1); | 751 | 1.28k | buf = self.reader.fill_buf()?; | 752 | | } | 753 | | } | 754 | | | 755 | 2.58M | Ok(()) | 756 | 2.58M | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Line | Count | Source | 737 | 13.5M | pub(crate) fn fill(&mut self) -> Result<(), DecodingError> { | 738 | 13.5M | debug_assert!(self.nbits < 64); | 739 | | | 740 | 13.5M | let mut buf = self.reader.fill_buf()?; | 741 | 13.5M | if buf.len() >= 8 { | 742 | 13.5M | let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap()); | 743 | 13.5M | self.reader.consume(usize::from((63 - self.nbits) / 8)); | 744 | 13.5M | self.buffer |= lookahead << self.nbits; | 745 | 13.5M | self.nbits |= 56; | 746 | 13.5M | } else { | 747 | 21.5k | while !buf.is_empty() && self.nbits < 56 { | 748 | 2.78k | self.buffer |= u64::from(buf[0]) << self.nbits; | 749 | 2.78k | self.nbits += 8; | 750 | 2.78k | self.reader.consume(1); | 751 | 2.78k | buf = self.reader.fill_buf()?; | 752 | | } | 753 | | } | 754 | | | 755 | 13.5M | Ok(()) | 756 | 13.5M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Line | Count | Source | 737 | 17.8M | pub(crate) fn fill(&mut self) -> Result<(), DecodingError> { | 738 | 17.8M | debug_assert!(self.nbits < 64); | 739 | | | 740 | 17.8M | let mut buf = self.reader.fill_buf()?; | 741 | 17.8M | if buf.len() >= 8 { | 742 | 17.8M | let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap()); | 743 | 17.8M | self.reader.consume(usize::from((63 - self.nbits) / 8)); | 744 | 17.8M | self.buffer |= lookahead << self.nbits; | 745 | 17.8M | self.nbits |= 56; | 746 | 17.8M | } else { | 747 | 38.5k | while !buf.is_empty() && self.nbits < 56 { | 748 | 10.7k | self.buffer |= u64::from(buf[0]) << self.nbits; | 749 | 10.7k | self.nbits += 8; | 750 | 10.7k | self.reader.consume(1); | 751 | 10.7k | buf = self.reader.fill_buf()?; | 752 | | } | 753 | | } | 754 | | | 755 | 17.8M | Ok(()) | 756 | 17.8M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill |
757 | | |
758 | | /// Peeks at the next `num` bits in the buffer. |
759 | 11.5M | pub(crate) const fn peek(&self, num: u8) -> u64 { |
760 | 11.5M | self.buffer & ((1 << num) - 1) |
761 | 11.5M | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Line | Count | Source | 759 | 1.14M | pub(crate) const fn peek(&self, num: u8) -> u64 { | 760 | 1.14M | self.buffer & ((1 << num) - 1) | 761 | 1.14M | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Line | Count | Source | 759 | 10.1M | pub(crate) const fn peek(&self, num: u8) -> u64 { | 760 | 10.1M | self.buffer & ((1 << num) - 1) | 761 | 10.1M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Line | Count | Source | 759 | 260k | pub(crate) const fn peek(&self, num: u8) -> u64 { | 760 | 260k | self.buffer & ((1 << num) - 1) | 761 | 260k | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek |
762 | | |
763 | | /// Peeks at the full buffer. |
764 | 96.8M | pub(crate) const fn peek_full(&self) -> u64 { |
765 | 96.8M | self.buffer |
766 | 96.8M | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Line | Count | Source | 764 | 4.56M | pub(crate) const fn peek_full(&self) -> u64 { | 765 | 4.56M | self.buffer | 766 | 4.56M | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Line | Count | Source | 764 | 26.8M | pub(crate) const fn peek_full(&self) -> u64 { | 765 | 26.8M | self.buffer | 766 | 26.8M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Line | Count | Source | 764 | 65.5M | pub(crate) const fn peek_full(&self) -> u64 { | 765 | 65.5M | self.buffer | 766 | 65.5M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full |
767 | | |
768 | | /// Consumes `num` bits from the buffer returning an error if there are not enough bits. |
769 | 106M | pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> { |
770 | 106M | if self.nbits < num { |
771 | 437 | return Err(DecodingError::BitStreamError); |
772 | 106M | } |
773 | | |
774 | 106M | self.buffer >>= num; |
775 | 106M | self.nbits -= num; |
776 | 106M | Ok(()) |
777 | 106M | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Line | Count | Source | 769 | 5.69M | pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> { | 770 | 5.69M | if self.nbits < num { | 771 | 191 | return Err(DecodingError::BitStreamError); | 772 | 5.69M | } | 773 | | | 774 | 5.69M | self.buffer >>= num; | 775 | 5.69M | self.nbits -= num; | 776 | 5.69M | Ok(()) | 777 | 5.69M | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Line | Count | Source | 769 | 34.8M | pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> { | 770 | 34.8M | if self.nbits < num { | 771 | 246 | return Err(DecodingError::BitStreamError); | 772 | 34.8M | } | 773 | | | 774 | 34.8M | self.buffer >>= num; | 775 | 34.8M | self.nbits -= num; | 776 | 34.8M | Ok(()) | 777 | 34.8M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Line | Count | Source | 769 | 65.7M | pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> { | 770 | 65.7M | if self.nbits < num { | 771 | 0 | return Err(DecodingError::BitStreamError); | 772 | 65.7M | } | 773 | | | 774 | 65.7M | self.buffer >>= num; | 775 | 65.7M | self.nbits -= num; | 776 | 65.7M | Ok(()) | 777 | 65.7M | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume |
778 | | |
779 | | /// Convenience function to read a number of bits and convert them to a type. |
780 | 666k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { |
781 | 666k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); |
782 | 666k | debug_assert!(num <= 32); |
783 | | |
784 | 666k | if self.nbits < num { |
785 | 20.3k | self.fill()?; |
786 | 646k | } |
787 | 666k | let value = self.peek(num) as u32; |
788 | 666k | self.consume(num)?; |
789 | | |
790 | 666k | value.try_into().map_err(|_| { |
791 | 0 | debug_assert!(false, "Value too large to fit in type"); |
792 | 0 | DecodingError::BitStreamError |
793 | 0 | }) Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::read_bits::<_>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0} |
794 | 666k | } <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Line | Count | Source | 780 | 201k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 201k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 201k | debug_assert!(num <= 32); | 783 | | | 784 | 201k | if self.nbits < num { | 785 | 4.08k | self.fill()?; | 786 | 197k | } | 787 | 201k | let value = self.peek(num) as u32; | 788 | 201k | self.consume(num)?; | 789 | | | 790 | 201k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 201k | } |
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Line | Count | Source | 780 | 2.88k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 2.88k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 2.88k | debug_assert!(num <= 32); | 783 | | | 784 | 2.88k | if self.nbits < num { | 785 | 57 | self.fill()?; | 786 | 2.82k | } | 787 | 2.88k | let value = self.peek(num) as u32; | 788 | 2.88k | self.consume(num)?; | 789 | | | 790 | 2.88k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 2.88k | } |
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Line | Count | Source | 780 | 125k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 125k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 125k | debug_assert!(num <= 32); | 783 | | | 784 | 125k | if self.nbits < num { | 785 | 3.59k | self.fill()?; | 786 | 121k | } | 787 | 125k | let value = self.peek(num) as u32; | 788 | 125k | self.consume(num)?; | 789 | | | 790 | 125k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 125k | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Line | Count | Source | 780 | 66.8k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 66.8k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 66.8k | debug_assert!(num <= 32); | 783 | | | 784 | 66.8k | if self.nbits < num { | 785 | 1.42k | self.fill()?; | 786 | 65.4k | } | 787 | 66.8k | let value = self.peek(num) as u32; | 788 | 66.8k | self.consume(num)?; | 789 | | | 790 | 66.8k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 66.8k | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Line | Count | Source | 780 | 1.41k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 1.41k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 1.41k | debug_assert!(num <= 32); | 783 | | | 784 | 1.41k | if self.nbits < num { | 785 | 0 | self.fill()?; | 786 | 1.41k | } | 787 | 1.41k | let value = self.peek(num) as u32; | 788 | 1.41k | self.consume(num)?; | 789 | | | 790 | 1.41k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 1.41k | } |
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Line | Count | Source | 780 | 39.7k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 39.7k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 39.7k | debug_assert!(num <= 32); | 783 | | | 784 | 39.7k | if self.nbits < num { | 785 | 842 | self.fill()?; | 786 | 38.9k | } | 787 | 39.7k | let value = self.peek(num) as u32; | 788 | 39.7k | self.consume(num)?; | 789 | | | 790 | 39.6k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 39.7k | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::read_bits::<_> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Line | Count | Source | 780 | 73.7k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 73.7k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 73.7k | debug_assert!(num <= 32); | 783 | | | 784 | 73.7k | if self.nbits < num { | 785 | 2.06k | self.fill()?; | 786 | 71.7k | } | 787 | 73.7k | let value = self.peek(num) as u32; | 788 | 73.7k | self.consume(num)?; | 789 | | | 790 | 73.7k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 73.7k | } |
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Line | Count | Source | 780 | 6.77k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 6.77k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 6.77k | debug_assert!(num <= 32); | 783 | | | 784 | 6.77k | if self.nbits < num { | 785 | 0 | self.fill()?; | 786 | 6.77k | } | 787 | 6.77k | let value = self.peek(num) as u32; | 788 | 6.77k | self.consume(num)?; | 789 | | | 790 | 6.77k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 6.77k | } |
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Line | Count | Source | 780 | 148k | pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> { | 781 | 148k | debug_assert!(num as usize <= 8 * mem::size_of::<T>()); | 782 | 148k | debug_assert!(num <= 32); | 783 | | | 784 | 148k | if self.nbits < num { | 785 | 8.29k | self.fill()?; | 786 | 140k | } | 787 | 148k | let value = self.peek(num) as u32; | 788 | 148k | self.consume(num)?; | 789 | | | 790 | 148k | value.try_into().map_err(|_| { | 791 | | debug_assert!(false, "Value too large to fit in type"); | 792 | | DecodingError::BitStreamError | 793 | | }) | 794 | 148k | } |
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize> Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16> |
795 | | } |
796 | | |
797 | | #[cfg(test)] |
798 | | mod test { |
799 | | |
800 | | use std::io::Cursor; |
801 | | |
802 | | use super::BitReader; |
803 | | |
804 | | #[test] |
805 | | fn bit_read_test() { |
806 | | //10011100 01000001 11100001 |
807 | | let mut bit_reader = BitReader::new(Cursor::new(vec![0x9C, 0x41, 0xE1])); |
808 | | |
809 | | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 4); //100 |
810 | | assert_eq!(bit_reader.read_bits::<u8>(2).unwrap(), 3); //11 |
811 | | assert_eq!(bit_reader.read_bits::<u8>(6).unwrap(), 12); //001100 |
812 | | assert_eq!(bit_reader.read_bits::<u16>(10).unwrap(), 40); //0000101000 |
813 | | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 7); //111 |
814 | | } |
815 | | |
816 | | #[test] |
817 | | fn bit_read_error_test() { |
818 | | //01101010 |
819 | | let mut bit_reader = BitReader::new(Cursor::new(vec![0x6A])); |
820 | | |
821 | | assert_eq!(bit_reader.read_bits::<u8>(3).unwrap(), 2); //010 |
822 | | assert_eq!(bit_reader.read_bits::<u8>(5).unwrap(), 13); //01101 |
823 | | assert!(bit_reader.read_bits::<u8>(4).is_err()); //error |
824 | | } |
825 | | } |