Coverage Report

Created: 2026-01-22 07:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.92k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
7.92k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
7.92k
        .try_into()
57
7.92k
        .unwrap()
58
7.92k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
6.10k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
6.10k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
6.10k
        .try_into()
57
6.10k
        .unwrap()
58
6.10k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
1.82k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
1.82k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
1.82k
        .try_into()
57
1.82k
        .unwrap()
58
1.82k
}
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.97k
    pub(crate) const fn new(r: R) -> Self {
75
2.97k
        Self {
76
2.97k
            bit_reader: BitReader::new(r),
77
2.97k
            transforms: [None, None, None, None],
78
2.97k
            transform_order: Vec::new(),
79
2.97k
            width: 0,
80
2.97k
            height: 0,
81
2.97k
        }
82
2.97k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
2.30k
    pub(crate) const fn new(r: R) -> Self {
75
2.30k
        Self {
76
2.30k
            bit_reader: BitReader::new(r),
77
2.30k
            transforms: [None, None, None, None],
78
2.30k
            transform_order: Vec::new(),
79
2.30k
            width: 0,
80
2.30k
            height: 0,
81
2.30k
        }
82
2.30k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
666
    pub(crate) const fn new(r: R) -> Self {
75
666
        Self {
76
666
            bit_reader: BitReader::new(r),
77
666
            transforms: [None, None, None, None],
78
666
            transform_order: Vec::new(),
79
666
            width: 0,
80
666
            height: 0,
81
666
        }
82
666
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::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.97k
    pub(crate) fn decode_frame(
90
2.97k
        &mut self,
91
2.97k
        width: u32,
92
2.97k
        height: u32,
93
2.97k
        implicit_dimensions: bool,
94
2.97k
        buf: &mut [u8],
95
2.97k
    ) -> Result<(), DecodingError> {
96
2.97k
        if implicit_dimensions {
97
666
            self.width = width as u16;
98
666
            self.height = height as u16;
99
666
        } else {
100
2.30k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
2.30k
            if signature != 0x2f {
102
0
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
2.30k
            }
104
105
2.30k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
2.30k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
2.30k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
1
                return Err(DecodingError::InconsistentImageSizes);
109
2.29k
            }
110
111
2.29k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
2.29k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
2.29k
            if version_num != 0 {
114
0
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
2.29k
            }
116
        }
117
118
2.96k
        let transformed_width = self.read_transforms()?;
119
2.76k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
2.76k
        self.decode_image_stream(
121
2.76k
            transformed_width,
122
2.76k
            self.height,
123
            true,
124
2.76k
            &mut buf[..transformed_size],
125
818
        )?;
126
127
1.94k
        let mut image_size = transformed_size;
128
1.94k
        let mut width = transformed_width;
129
3.66k
        for &trans_index in self.transform_order.iter().rev() {
130
3.66k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
3.66k
            match transform {
132
                TransformType::PredictorTransform {
133
1.81k
                    size_bits,
134
1.81k
                    predictor_data,
135
1.81k
                } => apply_predictor_transform(
136
1.81k
                    &mut buf[..image_size],
137
1.81k
                    width,
138
1.81k
                    self.height,
139
1.81k
                    *size_bits,
140
1.81k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
9
                    size_bits,
144
9
                    transform_data,
145
9
                } => {
146
9
                    apply_color_transform(
147
9
                        &mut buf[..image_size],
148
9
                        width,
149
9
                        *size_bits,
150
9
                        transform_data,
151
9
                    );
152
9
                }
153
1.73k
                TransformType::SubtractGreen => {
154
1.73k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
1.73k
                }
156
                TransformType::ColorIndexingTransform {
157
104
                    table_size,
158
104
                    table_data,
159
104
                } => {
160
104
                    width = self.width;
161
104
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
104
                    apply_color_indexing_transform(
163
104
                        buf,
164
104
                        width,
165
104
                        self.height,
166
104
                        *table_size,
167
104
                        table_data,
168
104
                    );
169
104
                }
170
            }
171
        }
172
173
1.94k
        Ok(())
174
2.97k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
2.30k
    pub(crate) fn decode_frame(
90
2.30k
        &mut self,
91
2.30k
        width: u32,
92
2.30k
        height: u32,
93
2.30k
        implicit_dimensions: bool,
94
2.30k
        buf: &mut [u8],
95
2.30k
    ) -> Result<(), DecodingError> {
96
2.30k
        if implicit_dimensions {
97
0
            self.width = width as u16;
98
0
            self.height = height as u16;
99
0
        } else {
100
2.30k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
2.30k
            if signature != 0x2f {
102
0
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
2.30k
            }
104
105
2.30k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
2.30k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
2.30k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
1
                return Err(DecodingError::InconsistentImageSizes);
109
2.29k
            }
110
111
2.29k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
2.29k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
2.29k
            if version_num != 0 {
114
0
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
2.29k
            }
116
        }
117
118
2.29k
        let transformed_width = self.read_transforms()?;
119
2.27k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
2.27k
        self.decode_image_stream(
121
2.27k
            transformed_width,
122
2.27k
            self.height,
123
            true,
124
2.27k
            &mut buf[..transformed_size],
125
455
        )?;
126
127
1.81k
        let mut image_size = transformed_size;
128
1.81k
        let mut width = transformed_width;
129
3.54k
        for &trans_index in self.transform_order.iter().rev() {
130
3.54k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
3.54k
            match transform {
132
                TransformType::PredictorTransform {
133
1.74k
                    size_bits,
134
1.74k
                    predictor_data,
135
1.74k
                } => apply_predictor_transform(
136
1.74k
                    &mut buf[..image_size],
137
1.74k
                    width,
138
1.74k
                    self.height,
139
1.74k
                    *size_bits,
140
1.74k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
4
                    size_bits,
144
4
                    transform_data,
145
4
                } => {
146
4
                    apply_color_transform(
147
4
                        &mut buf[..image_size],
148
4
                        width,
149
4
                        *size_bits,
150
4
                        transform_data,
151
4
                    );
152
4
                }
153
1.73k
                TransformType::SubtractGreen => {
154
1.73k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
1.73k
                }
156
                TransformType::ColorIndexingTransform {
157
53
                    table_size,
158
53
                    table_data,
159
53
                } => {
160
53
                    width = self.width;
161
53
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
53
                    apply_color_indexing_transform(
163
53
                        buf,
164
53
                        width,
165
53
                        self.height,
166
53
                        *table_size,
167
53
                        table_data,
168
53
                    );
169
53
                }
170
            }
171
        }
172
173
1.81k
        Ok(())
174
2.30k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
666
    pub(crate) fn decode_frame(
90
666
        &mut self,
91
666
        width: u32,
92
666
        height: u32,
93
666
        implicit_dimensions: bool,
94
666
        buf: &mut [u8],
95
666
    ) -> Result<(), DecodingError> {
96
666
        if implicit_dimensions {
97
666
            self.width = width as u16;
98
666
            self.height = height as u16;
99
666
        } 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
666
        let transformed_width = self.read_transforms()?;
119
493
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
493
        self.decode_image_stream(
121
493
            transformed_width,
122
493
            self.height,
123
            true,
124
493
            &mut buf[..transformed_size],
125
363
        )?;
126
127
130
        let mut image_size = transformed_size;
128
130
        let mut width = transformed_width;
129
130
        for &trans_index in self.transform_order.iter().rev() {
130
123
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
123
            match transform {
132
                TransformType::PredictorTransform {
133
63
                    size_bits,
134
63
                    predictor_data,
135
63
                } => apply_predictor_transform(
136
63
                    &mut buf[..image_size],
137
63
                    width,
138
63
                    self.height,
139
63
                    *size_bits,
140
63
                    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
4
                TransformType::SubtractGreen => {
154
4
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
4
                }
156
                TransformType::ColorIndexingTransform {
157
51
                    table_size,
158
51
                    table_data,
159
51
                } => {
160
51
                    width = self.width;
161
51
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
51
                    apply_color_indexing_transform(
163
51
                        buf,
164
51
                        width,
165
51
                        self.height,
166
51
                        *table_size,
167
51
                        table_data,
168
51
                    );
169
51
                }
170
            }
171
        }
172
173
130
        Ok(())
174
666
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::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
6.03k
    fn decode_image_stream(
182
6.03k
        &mut self,
183
6.03k
        xsize: u16,
184
6.03k
        ysize: u16,
185
6.03k
        is_argb_img: bool,
186
6.03k
        data: &mut [u8],
187
6.03k
    ) -> Result<(), DecodingError> {
188
6.03k
        let color_cache_bits = self.read_color_cache()?;
189
6.02k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
823
            color_cache_bits: bits,
191
823
            color_cache: vec![[0; 4]; 1 << bits],
192
823
        });
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
459
            color_cache_bits: bits,
191
459
            color_cache: vec![[0; 4]; 1 << bits],
192
459
        });
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
364
            color_cache_bits: bits,
191
364
            color_cache: vec![[0; 4]; 1 << bits],
192
364
        });
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream::{closure#0}
193
194
6.02k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
5.46k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
6.03k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
4.63k
    fn decode_image_stream(
182
4.63k
        &mut self,
183
4.63k
        xsize: u16,
184
4.63k
        ysize: u16,
185
4.63k
        is_argb_img: bool,
186
4.63k
        data: &mut [u8],
187
4.63k
    ) -> Result<(), DecodingError> {
188
4.63k
        let color_cache_bits = self.read_color_cache()?;
189
4.63k
        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
4.63k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
4.37k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
4.63k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
1.40k
    fn decode_image_stream(
182
1.40k
        &mut self,
183
1.40k
        xsize: u16,
184
1.40k
        ysize: u16,
185
1.40k
        is_argb_img: bool,
186
1.40k
        data: &mut [u8],
187
1.40k
    ) -> Result<(), DecodingError> {
188
1.40k
        let color_cache_bits = self.read_color_cache()?;
189
1.39k
        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.39k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
1.09k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
1.40k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream
197
198
    /// Reads transforms and their data from the bitstream
199
2.96k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
2.96k
        let mut xsize = self.width;
201
202
7.47k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
4.70k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
4.70k
            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
4.70k
            }
209
210
4.70k
            self.transform_order.push(transform_type_val);
211
212
4.70k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.20k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.20k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.20k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.20k
                    let mut predictor_data =
222
2.20k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.20k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.07k
                    TransformType::PredictorTransform {
226
2.07k
                        size_bits,
227
2.07k
                        predictor_data,
228
2.07k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
135
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
135
                    let block_xsize = subsample_size(xsize, size_bits);
236
135
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
135
                    let mut transform_data =
239
135
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
135
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
106
                    TransformType::ColorTransform {
243
106
                        size_bits,
244
106
                        transform_data,
245
106
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
1.96k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
399
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
397
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
397
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
364
                    let bits = if color_table_size <= 2 {
259
109
                        3
260
255
                    } else if color_table_size <= 4 {
261
35
                        2
262
220
                    } else if color_table_size <= 16 {
263
12
                        1
264
                    } else {
265
208
                        0
266
                    };
267
364
                    xsize = subsample_size(xsize, bits);
268
269
364
                    Self::adjust_color_map(&mut color_map);
270
271
364
                    TransformType::ColorIndexingTransform {
272
364
                        table_size: color_table_size,
273
364
                        table_data: color_map,
274
364
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
4.51k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
2.76k
        Ok(xsize)
283
2.96k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
2.29k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
2.29k
        let mut xsize = self.width;
201
202
6.21k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
3.94k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
3.94k
            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
3.93k
            }
209
210
3.93k
            self.transform_order.push(transform_type_val);
211
212
3.93k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
1.88k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
1.88k
                    let block_xsize = subsample_size(xsize, size_bits);
219
1.88k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
1.88k
                    let mut predictor_data =
222
1.88k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
1.88k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
1.87k
                    TransformType::PredictorTransform {
226
1.87k
                        size_bits,
227
1.87k
                        predictor_data,
228
1.87k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
90
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
90
                    let block_xsize = subsample_size(xsize, size_bits);
236
90
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
90
                    let mut transform_data =
239
90
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
90
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
85
                    TransformType::ColorTransform {
243
85
                        size_bits,
244
85
                        transform_data,
245
85
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
1.86k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
97
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
96
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
96
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
88
                    let bits = if color_table_size <= 2 {
259
5
                        3
260
83
                    } else if color_table_size <= 4 {
261
1
                        2
262
82
                    } else if color_table_size <= 16 {
263
9
                        1
264
                    } else {
265
73
                        0
266
                    };
267
88
                    xsize = subsample_size(xsize, bits);
268
269
88
                    Self::adjust_color_map(&mut color_map);
270
271
88
                    TransformType::ColorIndexingTransform {
272
88
                        table_size: color_table_size,
273
88
                        table_data: color_map,
274
88
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
3.91k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
2.27k
        Ok(xsize)
283
2.29k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
666
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
666
        let mut xsize = self.width;
201
202
1.26k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
769
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
769
            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
768
            }
209
210
768
            self.transform_order.push(transform_type_val);
211
212
768
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
317
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
317
                    let block_xsize = subsample_size(xsize, size_bits);
219
317
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
317
                    let mut predictor_data =
222
317
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
317
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
195
                    TransformType::PredictorTransform {
226
195
                        size_bits,
227
195
                        predictor_data,
228
195
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
45
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
45
                    let block_xsize = subsample_size(xsize, size_bits);
236
45
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
45
                    let mut transform_data =
239
45
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
45
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
21
                    TransformType::ColorTransform {
243
21
                        size_bits,
244
21
                        transform_data,
245
21
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
104
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
302
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
301
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
301
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
276
                    let bits = if color_table_size <= 2 {
259
104
                        3
260
172
                    } else if color_table_size <= 4 {
261
34
                        2
262
138
                    } else if color_table_size <= 16 {
263
3
                        1
264
                    } else {
265
135
                        0
266
                    };
267
276
                    xsize = subsample_size(xsize, bits);
268
269
276
                    Self::adjust_color_map(&mut color_map);
270
271
276
                    TransformType::ColorIndexingTransform {
272
276
                        table_size: color_table_size,
273
276
                        table_data: color_map,
274
276
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
596
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
493
        Ok(xsize)
283
666
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_transforms
284
285
    /// Adjusts the color map since it's subtraction coded
286
364
    fn adjust_color_map(color_map: &mut [u8]) {
287
111k
        for i in 4..color_map.len() {
288
111k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
111k
        }
290
364
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
88
    fn adjust_color_map(color_map: &mut [u8]) {
287
53.5k
        for i in 4..color_map.len() {
288
53.5k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
53.5k
        }
290
88
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
276
    fn adjust_color_map(color_map: &mut [u8]) {
287
57.5k
        for i in 4..color_map.len() {
288
57.5k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
57.5k
        }
290
276
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::adjust_color_map
291
292
    /// Reads huffman codes associated with an image
293
6.02k
    fn read_huffman_codes(
294
6.02k
        &mut self,
295
6.02k
        read_meta: bool,
296
6.02k
        xsize: u16,
297
6.02k
        ysize: u16,
298
6.02k
        color_cache: Option<ColorCache>,
299
6.02k
    ) -> Result<HuffmanInfo, DecodingError> {
300
6.02k
        let mut num_huff_groups = 1u32;
301
302
6.02k
        let mut huffman_bits = 0;
303
6.02k
        let mut huffman_xsize = 1;
304
6.02k
        let mut huffman_ysize = 1;
305
6.02k
        let mut entropy_image = Vec::new();
306
307
6.02k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
532
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
532
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
532
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
532
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
532
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
502
            entropy_image = data
317
502
                .chunks_exact(4)
318
3.04M
                .map(|pixel| {
319
3.04M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
3.04M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
894
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
3.04M
                    }
323
3.04M
                    meta_huff_code
324
3.04M
                })
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
2.96M
                .map(|pixel| {
319
2.96M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
2.96M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
455
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
2.96M
                    }
323
2.96M
                    meta_huff_code
324
2.96M
                })
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
80.7k
                .map(|pixel| {
319
80.7k
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
80.7k
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
439
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
80.2k
                    }
323
80.7k
                    meta_huff_code
324
80.7k
                })
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes::{closure#0}
325
502
                .collect::<Vec<u16>>();
326
5.49k
        }
327
328
5.99k
        let mut hufftree_groups = Vec::new();
329
330
40.0k
        for _i in 0..num_huff_groups {
331
40.0k
            let mut group: HuffmanCodeGroup = Default::default();
332
238k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
199k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
199k
                if j == 0 {
335
40.0k
                    if let Some(color_cache) = color_cache.as_ref() {
336
15.3k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
24.7k
                    }
338
158k
                }
339
340
199k
                let tree = self.read_huffman_code(alphabet_size)?;
341
198k
                group[j] = tree;
342
            }
343
39.5k
            hufftree_groups.push(group);
344
        }
345
346
5.46k
        let huffman_mask = if huffman_bits == 0 {
347
5.26k
            !0
348
        } else {
349
194
            (1 << huffman_bits) - 1
350
        };
351
352
5.46k
        let info = HuffmanInfo {
353
5.46k
            xsize: huffman_xsize,
354
5.46k
            _ysize: huffman_ysize,
355
5.46k
            color_cache,
356
5.46k
            image: entropy_image,
357
5.46k
            bits: huffman_bits,
358
5.46k
            mask: huffman_mask,
359
5.46k
            huffman_code_groups: hufftree_groups,
360
5.46k
        };
361
362
5.46k
        Ok(info)
363
6.02k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
4.63k
    fn read_huffman_codes(
294
4.63k
        &mut self,
295
4.63k
        read_meta: bool,
296
4.63k
        xsize: u16,
297
4.63k
        ysize: u16,
298
4.63k
        color_cache: Option<ColorCache>,
299
4.63k
    ) -> Result<HuffmanInfo, DecodingError> {
300
4.63k
        let mut num_huff_groups = 1u32;
301
302
4.63k
        let mut huffman_bits = 0;
303
4.63k
        let mut huffman_xsize = 1;
304
4.63k
        let mut huffman_ysize = 1;
305
4.63k
        let mut entropy_image = Vec::new();
306
307
4.63k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
288
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
288
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
288
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
288
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
288
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
277
            entropy_image = data
317
277
                .chunks_exact(4)
318
277
                .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
277
                .collect::<Vec<u16>>();
326
4.34k
        }
327
328
4.62k
        let mut hufftree_groups = Vec::new();
329
330
32.1k
        for _i in 0..num_huff_groups {
331
32.1k
            let mut group: HuffmanCodeGroup = Default::default();
332
192k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
160k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
160k
                if j == 0 {
335
32.1k
                    if let Some(color_cache) = color_cache.as_ref() {
336
14.5k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
17.5k
                    }
338
128k
                }
339
340
160k
                let tree = self.read_huffman_code(alphabet_size)?;
341
159k
                group[j] = tree;
342
            }
343
31.8k
            hufftree_groups.push(group);
344
        }
345
346
4.37k
        let huffman_mask = if huffman_bits == 0 {
347
4.30k
            !0
348
        } else {
349
61
            (1 << huffman_bits) - 1
350
        };
351
352
4.37k
        let info = HuffmanInfo {
353
4.37k
            xsize: huffman_xsize,
354
4.37k
            _ysize: huffman_ysize,
355
4.37k
            color_cache,
356
4.37k
            image: entropy_image,
357
4.37k
            bits: huffman_bits,
358
4.37k
            mask: huffman_mask,
359
4.37k
            huffman_code_groups: hufftree_groups,
360
4.37k
        };
361
362
4.37k
        Ok(info)
363
4.63k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
1.39k
    fn read_huffman_codes(
294
1.39k
        &mut self,
295
1.39k
        read_meta: bool,
296
1.39k
        xsize: u16,
297
1.39k
        ysize: u16,
298
1.39k
        color_cache: Option<ColorCache>,
299
1.39k
    ) -> Result<HuffmanInfo, DecodingError> {
300
1.39k
        let mut num_huff_groups = 1u32;
301
302
1.39k
        let mut huffman_bits = 0;
303
1.39k
        let mut huffman_xsize = 1;
304
1.39k
        let mut huffman_ysize = 1;
305
1.39k
        let mut entropy_image = Vec::new();
306
307
1.39k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
244
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
244
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
244
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
244
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
244
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
225
            entropy_image = data
317
225
                .chunks_exact(4)
318
225
                .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
225
                .collect::<Vec<u16>>();
326
1.14k
        }
327
328
1.37k
        let mut hufftree_groups = Vec::new();
329
330
7.93k
        for _i in 0..num_huff_groups {
331
7.93k
            let mut group: HuffmanCodeGroup = Default::default();
332
46.5k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
38.8k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
38.8k
                if j == 0 {
335
7.93k
                    if let Some(color_cache) = color_cache.as_ref() {
336
755
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
7.17k
                    }
338
30.9k
                }
339
340
38.8k
                let tree = self.read_huffman_code(alphabet_size)?;
341
38.5k
                group[j] = tree;
342
            }
343
7.65k
            hufftree_groups.push(group);
344
        }
345
346
1.09k
        let huffman_mask = if huffman_bits == 0 {
347
957
            !0
348
        } else {
349
133
            (1 << huffman_bits) - 1
350
        };
351
352
1.09k
        let info = HuffmanInfo {
353
1.09k
            xsize: huffman_xsize,
354
1.09k
            _ysize: huffman_ysize,
355
1.09k
            color_cache,
356
1.09k
            image: entropy_image,
357
1.09k
            bits: huffman_bits,
358
1.09k
            mask: huffman_mask,
359
1.09k
            huffman_code_groups: hufftree_groups,
360
1.09k
        };
361
362
1.09k
        Ok(info)
363
1.39k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes
364
365
    /// Decodes and returns a single huffman tree
366
199k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
199k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
199k
        if simple {
370
184k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
184k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
184k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
184k
            if zero_symbol >= alphabet_size {
376
8
                return Err(DecodingError::BitStreamError);
377
184k
            }
378
379
184k
            if num_symbols == 1 {
380
169k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
14.6k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
14.6k
                if one_symbol >= alphabet_size {
384
4
                    return Err(DecodingError::BitStreamError);
385
14.6k
                }
386
14.6k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
14.3k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
14.3k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
189k
            for i in 0..num_code_lengths {
393
189k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
189k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
13.9k
            let new_code_lengths =
398
14.2k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
13.9k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
199k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
160k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
160k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
160k
        if simple {
370
147k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
147k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
147k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
147k
            if zero_symbol >= alphabet_size {
376
3
                return Err(DecodingError::BitStreamError);
377
147k
            }
378
379
147k
            if num_symbols == 1 {
380
134k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
12.6k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
12.6k
                if one_symbol >= alphabet_size {
384
2
                    return Err(DecodingError::BitStreamError);
385
12.6k
                }
386
12.6k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
12.5k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
12.5k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
173k
            for i in 0..num_code_lengths {
393
173k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
173k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
12.4k
            let new_code_lengths =
398
12.5k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
12.4k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
160k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
38.8k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
38.8k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
38.8k
        if simple {
370
37.1k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
37.0k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
37.0k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
37.0k
            if zero_symbol >= alphabet_size {
376
5
                return Err(DecodingError::BitStreamError);
377
37.0k
            }
378
379
37.0k
            if num_symbols == 1 {
380
35.0k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
2.03k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
2.02k
                if one_symbol >= alphabet_size {
384
2
                    return Err(DecodingError::BitStreamError);
385
2.02k
                }
386
2.02k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
1.77k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
1.77k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
15.7k
            for i in 0..num_code_lengths {
393
15.7k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
15.7k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
1.56k
            let new_code_lengths =
398
1.74k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
1.56k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
38.8k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code
403
404
    /// Reads huffman code lengths
405
14.2k
    fn read_huffman_code_lengths(
406
14.2k
        &mut self,
407
14.2k
        code_length_code_lengths: Vec<u16>,
408
14.2k
        num_symbols: u16,
409
14.2k
    ) -> Result<Vec<u16>, DecodingError> {
410
14.2k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
14.0k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
9.10k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
9.10k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
9.10k
            if max_minus_two > num_symbols - 2 {
416
1
                return Err(DecodingError::BitStreamError);
417
9.10k
            }
418
9.10k
            2 + max_minus_two
419
        } else {
420
4.92k
            num_symbols
421
        };
422
423
14.0k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
14.0k
        let mut prev_code_len = 8; //default code length
425
426
14.0k
        let mut symbol = 0;
427
1.84M
        while symbol < num_symbols {
428
1.83M
            if max_symbol == 0 {
429
4.33k
                break;
430
1.83M
            }
431
1.83M
            max_symbol -= 1;
432
433
1.83M
            self.bit_reader.fill()?;
434
1.83M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.83M
            if code_len < 16 {
437
1.78M
                code_lengths[usize::from(symbol)] = code_len;
438
1.78M
                symbol += 1;
439
1.78M
                if code_len != 0 {
440
861k
                    prev_code_len = code_len;
441
921k
                }
442
            } else {
443
47.9k
                let use_prev = code_len == 16;
444
47.9k
                let slot = code_len - 16;
445
47.9k
                let extra_bits = match slot {
446
27.0k
                    0 => 2,
447
6.93k
                    1 => 3,
448
14.0k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
47.9k
                let repeat_offset = match slot {
452
33.9k
                    0 | 1 => 3,
453
14.0k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
47.9k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
47.9k
                if symbol + repeat > num_symbols {
460
32
                    return Err(DecodingError::BitStreamError);
461
47.9k
                }
462
463
47.9k
                let length = if use_prev { prev_code_len } else { 0 };
464
1.15M
                while repeat > 0 {
465
1.10M
                    repeat -= 1;
466
1.10M
                    code_lengths[usize::from(symbol)] = length;
467
1.10M
                    symbol += 1;
468
1.10M
                }
469
            }
470
        }
471
472
13.9k
        Ok(code_lengths)
473
14.2k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
12.5k
    fn read_huffman_code_lengths(
406
12.5k
        &mut self,
407
12.5k
        code_length_code_lengths: Vec<u16>,
408
12.5k
        num_symbols: u16,
409
12.5k
    ) -> Result<Vec<u16>, DecodingError> {
410
12.5k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
12.4k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
8.48k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
8.48k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
8.48k
            if max_minus_two > num_symbols - 2 {
416
1
                return Err(DecodingError::BitStreamError);
417
8.47k
            }
418
8.47k
            2 + max_minus_two
419
        } else {
420
3.96k
            num_symbols
421
        };
422
423
12.4k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
12.4k
        let mut prev_code_len = 8; //default code length
425
426
12.4k
        let mut symbol = 0;
427
1.81M
        while symbol < num_symbols {
428
1.80M
            if max_symbol == 0 {
429
3.70k
                break;
430
1.79M
            }
431
1.79M
            max_symbol -= 1;
432
433
1.79M
            self.bit_reader.fill()?;
434
1.79M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.79M
            if code_len < 16 {
437
1.75M
                code_lengths[usize::from(symbol)] = code_len;
438
1.75M
                symbol += 1;
439
1.75M
                if code_len != 0 {
440
838k
                    prev_code_len = code_len;
441
919k
                }
442
            } else {
443
40.0k
                let use_prev = code_len == 16;
444
40.0k
                let slot = code_len - 16;
445
40.0k
                let extra_bits = match slot {
446
23.6k
                    0 => 2,
447
5.48k
                    1 => 3,
448
10.9k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
40.0k
                let repeat_offset = match slot {
452
29.0k
                    0 | 1 => 3,
453
10.9k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
40.0k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
40.0k
                if symbol + repeat > num_symbols {
460
20
                    return Err(DecodingError::BitStreamError);
461
40.0k
                }
462
463
40.0k
                let length = if use_prev { prev_code_len } else { 0 };
464
887k
                while repeat > 0 {
465
847k
                    repeat -= 1;
466
847k
                    code_lengths[usize::from(symbol)] = length;
467
847k
                    symbol += 1;
468
847k
                }
469
            }
470
        }
471
472
12.4k
        Ok(code_lengths)
473
12.5k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
1.74k
    fn read_huffman_code_lengths(
406
1.74k
        &mut self,
407
1.74k
        code_length_code_lengths: Vec<u16>,
408
1.74k
        num_symbols: u16,
409
1.74k
    ) -> Result<Vec<u16>, DecodingError> {
410
1.74k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
1.58k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
628
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
628
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
626
            if max_minus_two > num_symbols - 2 {
416
0
                return Err(DecodingError::BitStreamError);
417
626
            }
418
626
            2 + max_minus_two
419
        } else {
420
957
            num_symbols
421
        };
422
423
1.58k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
1.58k
        let mut prev_code_len = 8; //default code length
425
426
1.58k
        let mut symbol = 0;
427
34.7k
        while symbol < num_symbols {
428
33.7k
            if max_symbol == 0 {
429
624
                break;
430
33.1k
            }
431
33.1k
            max_symbol -= 1;
432
433
33.1k
            self.bit_reader.fill()?;
434
33.1k
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
33.1k
            if code_len < 16 {
437
25.2k
                code_lengths[usize::from(symbol)] = code_len;
438
25.2k
                symbol += 1;
439
25.2k
                if code_len != 0 {
440
22.9k
                    prev_code_len = code_len;
441
22.9k
                }
442
            } else {
443
7.91k
                let use_prev = code_len == 16;
444
7.91k
                let slot = code_len - 16;
445
7.91k
                let extra_bits = match slot {
446
3.41k
                    0 => 2,
447
1.44k
                    1 => 3,
448
3.05k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
7.91k
                let repeat_offset = match slot {
452
4.85k
                    0 | 1 => 3,
453
3.05k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
7.91k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
7.90k
                if symbol + repeat > num_symbols {
460
12
                    return Err(DecodingError::BitStreamError);
461
7.89k
                }
462
463
7.89k
                let length = if use_prev { prev_code_len } else { 0 };
464
267k
                while repeat > 0 {
465
259k
                    repeat -= 1;
466
259k
                    code_lengths[usize::from(symbol)] = length;
467
259k
                    symbol += 1;
468
259k
                }
469
            }
470
        }
471
472
1.56k
        Ok(code_lengths)
473
1.74k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code_lengths
474
475
    /// Decodes the image data using the huffman trees and either of the 3 methods of decoding
476
5.46k
    fn decode_image_data(
477
5.46k
        &mut self,
478
5.46k
        width: u16,
479
5.46k
        height: u16,
480
5.46k
        mut huffman_info: HuffmanInfo,
481
5.46k
        data: &mut [u8],
482
5.46k
    ) -> Result<(), DecodingError> {
483
5.46k
        let num_values = usize::from(width) * usize::from(height);
484
485
5.46k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
5.46k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
5.46k
        let mut index = 0;
488
489
5.46k
        let mut next_block_start = 0;
490
27.6M
        while index < num_values {
491
27.6M
            self.bit_reader.fill()?;
492
493
27.6M
            if index >= next_block_start {
494
1.03M
                let x = index % usize::from(width);
495
1.03M
                let y = index / usize::from(width);
496
1.03M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
1.03M
                    + y * usize::from(width)
498
1.03M
                    + 1;
499
500
1.03M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
1.03M
                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.94M
                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
1.19M
                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
746k
                if tree[..4].iter().all(|t| t.is_single_node()) {
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data::{closure#0}
508
294k
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
294k
                    if code < 256 {
510
294k
                        let n = if huffman_info.bits == 0 {
511
2.03k
                            num_values
512
                        } else {
513
292k
                            next_block_start - index
514
                        };
515
516
294k
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
294k
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
294k
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
294k
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
67.9M
                        for i in 0..n {
522
67.9M
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
67.9M
                        }
524
525
294k
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
143k
                            color_cache.insert(value);
527
150k
                        }
528
529
294k
                        index += n;
530
294k
                        continue;
531
0
                    }
532
738k
                }
533
26.6M
            }
534
535
27.3M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
27.3M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
18.7M
                let green = code as u8;
541
18.7M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
18.7M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
18.7M
                if self.bit_reader.nbits < 15 {
544
4.95k
                    self.bit_reader.fill()?;
545
18.7M
                }
546
18.7M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
18.7M
                data[index * 4] = red;
549
18.7M
                data[index * 4 + 1] = green;
550
18.7M
                data[index * 4 + 2] = blue;
551
18.7M
                data[index * 4 + 3] = alpha;
552
553
18.7M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
3.86M
                    color_cache.insert([red, green, blue, alpha]);
555
14.8M
                }
556
18.7M
                index += 1;
557
8.65M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
6.25M
                let length_symbol = code - 256;
560
6.25M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
6.25M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
6.25M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
6.25M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
6.25M
                if index < dist || num_values - index < length {
567
109
                    return Err(DecodingError::BitStreamError);
568
6.25M
                }
569
570
6.25M
                if dist == 1 {
571
3.50M
                    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
2.74M
                    if index + length + 3 <= num_values {
577
2.74M
                        let start = (index - dist) * 4;
578
2.74M
                        data.copy_within(start..start + 16, index * 4);
579
580
2.74M
                        if length > 4 || dist < 4 {
581
249M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
249M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
249M
                            }
584
11.5k
                        }
585
                    } else {
586
65.4k
                        for i in 0..length * 4 {
587
65.4k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
65.4k
                        }
589
                    }
590
591
2.74M
                    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
35.0k
                    }
596
                }
597
6.25M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
2.40M
                let color_cache = huffman_info
601
2.40M
                    .color_cache
602
2.40M
                    .as_mut()
603
2.40M
                    .ok_or(DecodingError::BitStreamError)?;
604
2.40M
                let color = color_cache.lookup((code - 280).into());
605
2.40M
                data[index * 4..][..4].copy_from_slice(&color);
606
2.40M
                index += 1;
607
608
2.40M
                if index < next_block_start {
609
2.39M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
2.39M
                        if code >= 280 {
611
694k
                            self.bit_reader.consume(bits)?;
612
694k
                            data[index * 4..][..4]
613
694k
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
694k
                            index += 1;
615
1.70M
                        }
616
590
                    }
617
3.76k
                }
618
            }
619
        }
620
621
4.99k
        Ok(())
622
5.46k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
4.37k
    fn decode_image_data(
477
4.37k
        &mut self,
478
4.37k
        width: u16,
479
4.37k
        height: u16,
480
4.37k
        mut huffman_info: HuffmanInfo,
481
4.37k
        data: &mut [u8],
482
4.37k
    ) -> Result<(), DecodingError> {
483
4.37k
        let num_values = usize::from(width) * usize::from(height);
484
485
4.37k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
4.37k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
4.37k
        let mut index = 0;
488
489
4.37k
        let mut next_block_start = 0;
490
18.5M
        while index < num_values {
491
18.5M
            self.bit_reader.fill()?;
492
493
18.5M
            if index >= next_block_start {
494
572k
                let x = index % usize::from(width);
495
572k
                let y = index / usize::from(width);
496
572k
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
572k
                    + y * usize::from(width)
498
572k
                    + 1;
499
500
572k
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
572k
                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
572k
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
208k
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
208k
                    if code < 256 {
510
208k
                        let n = if huffman_info.bits == 0 {
511
1.89k
                            num_values
512
                        } else {
513
206k
                            next_block_start - index
514
                        };
515
516
208k
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
208k
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
208k
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
208k
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
67.2M
                        for i in 0..n {
522
67.2M
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
67.2M
                        }
524
525
208k
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
143k
                            color_cache.insert(value);
527
143k
                        }
528
529
208k
                        index += n;
530
208k
                        continue;
531
0
                    }
532
364k
                }
533
17.9M
            }
534
535
18.3M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
18.3M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
16.0M
                let green = code as u8;
541
16.0M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
16.0M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
16.0M
                if self.bit_reader.nbits < 15 {
544
4.60k
                    self.bit_reader.fill()?;
545
16.0M
                }
546
16.0M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
16.0M
                data[index * 4] = red;
549
16.0M
                data[index * 4 + 1] = green;
550
16.0M
                data[index * 4 + 2] = blue;
551
16.0M
                data[index * 4 + 3] = alpha;
552
553
16.0M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
1.39M
                    color_cache.insert([red, green, blue, alpha]);
555
14.6M
                }
556
16.0M
                index += 1;
557
2.33M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
1.78M
                let length_symbol = code - 256;
560
1.78M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
1.78M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
1.78M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
1.78M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
1.78M
                if index < dist || num_values - index < length {
567
27
                    return Err(DecodingError::BitStreamError);
568
1.78M
                }
569
570
1.78M
                if dist == 1 {
571
1.02M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
1.56G
                    for i in 0..length {
573
1.56G
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
1.56G
                    }
575
                } else {
576
764k
                    if index + length + 3 <= num_values {
577
764k
                        let start = (index - dist) * 4;
578
764k
                        data.copy_within(start..start + 16, index * 4);
579
580
764k
                        if length > 4 || dist < 4 {
581
189M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
189M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
189M
                            }
584
8.97k
                        }
585
                    } else {
586
20.1k
                        for i in 0..length * 4 {
587
20.1k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
20.1k
                        }
589
                    }
590
591
764k
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
758M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
758M
                            color_cache.insert(pixel.try_into().unwrap());
594
758M
                        }
595
7.58k
                    }
596
                }
597
1.78M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
549k
                let color_cache = huffman_info
601
549k
                    .color_cache
602
549k
                    .as_mut()
603
549k
                    .ok_or(DecodingError::BitStreamError)?;
604
549k
                let color = color_cache.lookup((code - 280).into());
605
549k
                data[index * 4..][..4].copy_from_slice(&color);
606
549k
                index += 1;
607
608
549k
                if index < next_block_start {
609
546k
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
546k
                        if code >= 280 {
611
203k
                            self.bit_reader.consume(bits)?;
612
203k
                            data[index * 4..][..4]
613
203k
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
203k
                            index += 1;
615
342k
                        }
616
567
                    }
617
2.62k
                }
618
            }
619
        }
620
621
4.14k
        Ok(())
622
4.37k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
1.09k
    fn decode_image_data(
477
1.09k
        &mut self,
478
1.09k
        width: u16,
479
1.09k
        height: u16,
480
1.09k
        mut huffman_info: HuffmanInfo,
481
1.09k
        data: &mut [u8],
482
1.09k
    ) -> Result<(), DecodingError> {
483
1.09k
        let num_values = usize::from(width) * usize::from(height);
484
485
1.09k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
1.09k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
1.09k
        let mut index = 0;
488
489
1.09k
        let mut next_block_start = 0;
490
9.10M
        while index < num_values {
491
9.10M
            self.bit_reader.fill()?;
492
493
9.10M
            if index >= next_block_start {
494
460k
                let x = index % usize::from(width);
495
460k
                let y = index / usize::from(width);
496
460k
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
460k
                    + y * usize::from(width)
498
460k
                    + 1;
499
500
460k
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
460k
                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
460k
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
85.9k
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
85.9k
                    if code < 256 {
510
85.9k
                        let n = if huffman_info.bits == 0 {
511
147
                            num_values
512
                        } else {
513
85.8k
                            next_block_start - index
514
                        };
515
516
85.9k
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
85.9k
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
85.9k
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
85.9k
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
758k
                        for i in 0..n {
522
758k
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
758k
                        }
524
525
85.9k
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
56
                            color_cache.insert(value);
527
85.9k
                        }
528
529
85.9k
                        index += n;
530
85.9k
                        continue;
531
0
                    }
532
374k
                }
533
8.64M
            }
534
535
9.01M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
9.01M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
2.70M
                let green = code as u8;
541
2.70M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
2.70M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
2.70M
                if self.bit_reader.nbits < 15 {
544
348
                    self.bit_reader.fill()?;
545
2.70M
                }
546
2.70M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
2.70M
                data[index * 4] = red;
549
2.70M
                data[index * 4 + 1] = green;
550
2.70M
                data[index * 4 + 2] = blue;
551
2.70M
                data[index * 4 + 3] = alpha;
552
553
2.70M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
2.46M
                    color_cache.insert([red, green, blue, alpha]);
555
2.46M
                }
556
2.70M
                index += 1;
557
6.31M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
4.46M
                let length_symbol = code - 256;
560
4.46M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
4.46M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
4.46M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
4.46M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
4.46M
                if index < dist || num_values - index < length {
567
82
                    return Err(DecodingError::BitStreamError);
568
4.46M
                }
569
570
4.46M
                if dist == 1 {
571
2.47M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
341M
                    for i in 0..length {
573
341M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
341M
                    }
575
                } else {
576
1.98M
                    if index + length + 3 <= num_values {
577
1.98M
                        let start = (index - dist) * 4;
578
1.98M
                        data.copy_within(start..start + 16, index * 4);
579
580
1.98M
                        if length > 4 || dist < 4 {
581
59.5M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
59.5M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
59.5M
                            }
584
2.54k
                        }
585
                    } else {
586
45.2k
                        for i in 0..length * 4 {
587
45.2k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
45.2k
                        }
589
                    }
590
591
1.98M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
241M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
241M
                            color_cache.insert(pixel.try_into().unwrap());
594
241M
                        }
595
27.4k
                    }
596
                }
597
4.46M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
1.85M
                let color_cache = huffman_info
601
1.85M
                    .color_cache
602
1.85M
                    .as_mut()
603
1.85M
                    .ok_or(DecodingError::BitStreamError)?;
604
1.85M
                let color = color_cache.lookup((code - 280).into());
605
1.85M
                data[index * 4..][..4].copy_from_slice(&color);
606
1.85M
                index += 1;
607
608
1.85M
                if index < next_block_start {
609
1.85M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
1.85M
                        if code >= 280 {
611
491k
                            self.bit_reader.consume(bits)?;
612
491k
                            data[index * 4..][..4]
613
491k
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
491k
                            index += 1;
615
1.36M
                        }
616
23
                    }
617
1.13k
                }
618
            }
619
        }
620
621
847
        Ok(())
622
1.09k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data
623
624
    /// Reads color cache data from the bitstream
625
6.03k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
6.03k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
835
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
834
            if !(1..=11).contains(&code_bits) {
630
11
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
823
            }
632
633
823
            Ok(Some(code_bits))
634
        } else {
635
5.20k
            Ok(None)
636
        }
637
6.03k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
4.63k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
4.63k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
463
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
463
            if !(1..=11).contains(&code_bits) {
630
4
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
459
            }
632
633
459
            Ok(Some(code_bits))
634
        } else {
635
4.17k
            Ok(None)
636
        }
637
4.63k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
1.40k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
1.40k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
372
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
371
            if !(1..=11).contains(&code_bits) {
630
7
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
364
            }
632
633
364
            Ok(Some(code_bits))
634
        } else {
635
1.02k
            Ok(None)
636
        }
637
1.40k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_color_cache
638
639
    /// Gets the copy distance from the prefix code and bitstream
640
12.5M
    fn get_copy_distance(
641
12.5M
        bit_reader: &mut BitReader<R>,
642
12.5M
        prefix_code: u16,
643
12.5M
    ) -> Result<usize, DecodingError> {
644
12.5M
        if prefix_code < 4 {
645
3.80M
            return Ok(usize::from(prefix_code + 1));
646
8.70M
        }
647
8.70M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
8.70M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
8.70M
        let bits = bit_reader.peek(extra_bits) as usize;
651
8.70M
        bit_reader.consume(extra_bits)?;
652
653
8.70M
        Ok(offset + bits + 1)
654
12.5M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
3.57M
    fn get_copy_distance(
641
3.57M
        bit_reader: &mut BitReader<R>,
642
3.57M
        prefix_code: u16,
643
3.57M
    ) -> Result<usize, DecodingError> {
644
3.57M
        if prefix_code < 4 {
645
1.14M
            return Ok(usize::from(prefix_code + 1));
646
2.43M
        }
647
2.43M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
2.43M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
2.43M
        let bits = bit_reader.peek(extra_bits) as usize;
651
2.43M
        bit_reader.consume(extra_bits)?;
652
653
2.43M
        Ok(offset + bits + 1)
654
3.57M
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
8.92M
    fn get_copy_distance(
641
8.92M
        bit_reader: &mut BitReader<R>,
642
8.92M
        prefix_code: u16,
643
8.92M
    ) -> Result<usize, DecodingError> {
644
8.92M
        if prefix_code < 4 {
645
2.65M
            return Ok(usize::from(prefix_code + 1));
646
6.26M
        }
647
6.26M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
6.26M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
6.26M
        let bits = bit_reader.peek(extra_bits) as usize;
651
6.26M
        bit_reader.consume(extra_bits)?;
652
653
6.26M
        Ok(offset + bits + 1)
654
8.92M
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::get_copy_distance
655
656
    /// Gets distance to pixel
657
6.25M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
6.25M
        if plane_code > 120 {
659
2.56M
            plane_code - 120
660
        } else {
661
3.68M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
3.68M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
3.68M
            if dist < 1 {
665
0
                return 1;
666
3.68M
            }
667
3.68M
            dist.try_into().unwrap()
668
        }
669
6.25M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
1.78M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
1.78M
        if plane_code > 120 {
659
754k
            plane_code - 120
660
        } else {
661
1.03M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
1.03M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
1.03M
            if dist < 1 {
665
0
                return 1;
666
1.03M
            }
667
1.03M
            dist.try_into().unwrap()
668
        }
669
1.78M
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
4.46M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
4.46M
        if plane_code > 120 {
659
1.80M
            plane_code - 120
660
        } else {
661
2.65M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
2.65M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
2.65M
            if dist < 1 {
665
0
                return 1;
666
2.65M
            }
667
2.65M
            dist.try_into().unwrap()
668
        }
669
4.46M
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::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.03M
    fn get_huff_index(&self, x: u16, y: u16) -> usize {
685
1.03M
        if self.bits == 0 {
686
708k
            return 0;
687
329k
        }
688
329k
        let position =
689
329k
            usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits);
690
329k
        let meta_huff_code: usize = usize::from(self.image[position]);
691
329k
        meta_huff_code
692
1.03M
    }
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.00G
    fn insert(&mut self, color: [u8; 4]) {
704
1.00G
        let [r, g, b, a] = color;
705
1.00G
        let color_u32 =
706
1.00G
            (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24);
707
1.00G
        let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits);
708
1.00G
        self.color_cache[index as usize] = color;
709
1.00G
    }
710
711
    #[inline(always)]
712
3.09M
    fn lookup(&self, index: usize) -> [u8; 4] {
713
3.09M
        self.color_cache[index]
714
3.09M
    }
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.97k
    const fn new(reader: R) -> Self {
726
2.97k
        Self {
727
2.97k
            reader,
728
2.97k
            buffer: 0,
729
2.97k
            nbits: 0,
730
2.97k
        }
731
2.97k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
2.30k
    const fn new(reader: R) -> Self {
726
2.30k
        Self {
727
2.30k
            reader,
728
2.30k
            buffer: 0,
729
2.30k
            nbits: 0,
730
2.30k
        }
731
2.30k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
666
    const fn new(reader: R) -> Self {
726
666
        Self {
727
666
            reader,
728
666
            buffer: 0,
729
666
            nbits: 0,
730
666
        }
731
666
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::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
29.5M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
29.5M
        debug_assert!(self.nbits < 64);
739
740
29.5M
        let mut buf = self.reader.fill_buf()?;
741
29.5M
        if buf.len() >= 8 {
742
29.3M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
29.3M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
29.3M
            self.buffer |= lookahead << self.nbits;
745
29.3M
            self.nbits |= 56;
746
29.3M
        } else {
747
218k
            while !buf.is_empty() && self.nbits < 56 {
748
15.3k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
15.3k
                self.nbits += 8;
750
15.3k
                self.reader.consume(1);
751
15.3k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
29.5M
        Ok(())
756
29.5M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
20.3M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
20.3M
        debug_assert!(self.nbits < 64);
739
740
20.3M
        let mut buf = self.reader.fill_buf()?;
741
20.3M
        if buf.len() >= 8 {
742
20.1M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
20.1M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
20.1M
            self.buffer |= lookahead << self.nbits;
745
20.1M
            self.nbits |= 56;
746
20.1M
        } else {
747
193k
            while !buf.is_empty() && self.nbits < 56 {
748
12.2k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
12.2k
                self.nbits += 8;
750
12.2k
                self.reader.consume(1);
751
12.2k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
20.3M
        Ok(())
756
20.3M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
9.14M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
9.14M
        debug_assert!(self.nbits < 64);
739
740
9.14M
        let mut buf = self.reader.fill_buf()?;
741
9.14M
        if buf.len() >= 8 {
742
9.12M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
9.12M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
9.12M
            self.buffer |= lookahead << self.nbits;
745
9.12M
            self.nbits |= 56;
746
9.12M
        } else {
747
25.3k
            while !buf.is_empty() && self.nbits < 56 {
748
3.01k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
3.01k
                self.nbits += 8;
750
3.01k
                self.reader.consume(1);
751
3.01k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
9.14M
        Ok(())
756
9.14M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::fill
757
758
    /// Peeks at the next `num` bits in the buffer.
759
9.79M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
9.79M
        self.buffer & ((1 << num) - 1)
761
9.79M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
3.33M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
3.33M
        self.buffer & ((1 << num) - 1)
761
3.33M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
6.45M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
6.45M
        self.buffer & ((1 << num) - 1)
761
6.45M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek
762
763
    /// Peeks at the full buffer.
764
86.3M
    pub(crate) const fn peek_full(&self) -> u64 {
765
86.3M
        self.buffer
766
86.3M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
69.0M
    pub(crate) const fn peek_full(&self) -> u64 {
765
69.0M
        self.buffer
766
69.0M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
17.2M
    pub(crate) const fn peek_full(&self) -> u64 {
765
17.2M
        self.buffer
766
17.2M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek_full
767
768
    /// Consumes `num` bits from the buffer returning an error if there are not enough bits.
769
94.4M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
94.4M
        if self.nbits < num {
771
540
            return Err(DecodingError::BitStreamError);
772
94.4M
        }
773
774
94.4M
        self.buffer >>= num;
775
94.4M
        self.nbits -= num;
776
94.4M
        Ok(())
777
94.4M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
72.0M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
72.0M
        if self.nbits < num {
771
300
            return Err(DecodingError::BitStreamError);
772
72.0M
        }
773
774
72.0M
        self.buffer >>= num;
775
72.0M
        self.nbits -= num;
776
72.0M
        Ok(())
777
72.0M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
22.3M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
22.3M
        if self.nbits < num {
771
240
            return Err(DecodingError::BitStreamError);
772
22.3M
        }
773
774
22.3M
        self.buffer >>= num;
775
22.3M
        self.nbits -= num;
776
22.3M
        Ok(())
777
22.3M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::consume
778
779
    /// Convenience function to read a number of bits and convert them to a type.
780
1.08M
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
1.08M
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
1.08M
        debug_assert!(num <= 32);
783
784
1.08M
        if self.nbits < num {
785
28.3k
            self.fill()?;
786
1.06M
        }
787
1.08M
        let value = self.peek(num) as u32;
788
1.08M
        self.consume(num)?;
789
790
1.08M
        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}
794
1.08M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
502k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
502k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
502k
        debug_assert!(num <= 32);
783
784
502k
        if self.nbits < num {
785
10.7k
            self.fill()?;
786
492k
        }
787
502k
        let value = self.peek(num) as u32;
788
502k
        self.consume(num)?;
789
790
502k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
502k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
12.5k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
12.5k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
12.5k
        debug_assert!(num <= 32);
783
784
12.5k
        if self.nbits < num {
785
121
            self.fill()?;
786
12.4k
        }
787
12.5k
        let value = self.peek(num) as u32;
788
12.5k
        self.consume(num)?;
789
790
12.5k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
12.5k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
387k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
387k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
387k
        debug_assert!(num <= 32);
783
784
387k
        if self.nbits < num {
785
13.7k
            self.fill()?;
786
373k
        }
787
387k
        let value = self.peek(num) as u32;
788
387k
        self.consume(num)?;
789
790
387k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
387k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
120k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
120k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
120k
        debug_assert!(num <= 32);
783
784
120k
        if self.nbits < num {
785
2.75k
            self.fill()?;
786
117k
        }
787
120k
        let value = self.peek(num) as u32;
788
120k
        self.consume(num)?;
789
790
120k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
120k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
1.77k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
1.77k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
1.77k
        debug_assert!(num <= 32);
783
784
1.77k
        if self.nbits < num {
785
3
            self.fill()?;
786
1.76k
        }
787
1.77k
        let value = self.peek(num) as u32;
788
1.77k
        self.consume(num)?;
789
790
1.76k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
1.77k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
63.6k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
63.6k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
63.6k
        debug_assert!(num <= 32);
783
784
63.6k
        if self.nbits < num {
785
951
            self.fill()?;
786
62.7k
        }
787
63.6k
        let value = self.peek(num) as u32;
788
63.6k
        self.consume(num)?;
789
790
63.6k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
63.6k
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::read_bits::<_>
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
}