Coverage Report

Created: 2026-08-13 08:17

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
10.3k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
10.3k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
10.3k
        .try_into()
57
10.3k
        .unwrap()
58
10.3k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
8.12k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
8.12k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
8.12k
        .try_into()
57
8.12k
        .unwrap()
58
8.12k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
2.23k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
2.23k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
2.23k
        .try_into()
57
2.23k
        .unwrap()
58
2.23k
}
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
5.08k
    pub(crate) const fn new(r: R) -> Self {
75
5.08k
        Self {
76
5.08k
            bit_reader: BitReader::new(r),
77
5.08k
            transforms: [None, None, None, None],
78
5.08k
            transform_order: Vec::new(),
79
5.08k
            width: 0,
80
5.08k
            height: 0,
81
5.08k
        }
82
5.08k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
3.83k
    pub(crate) const fn new(r: R) -> Self {
75
3.83k
        Self {
76
3.83k
            bit_reader: BitReader::new(r),
77
3.83k
            transforms: [None, None, None, None],
78
3.83k
            transform_order: Vec::new(),
79
3.83k
            width: 0,
80
3.83k
            height: 0,
81
3.83k
        }
82
3.83k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
1.24k
    pub(crate) const fn new(r: R) -> Self {
75
1.24k
        Self {
76
1.24k
            bit_reader: BitReader::new(r),
77
1.24k
            transforms: [None, None, None, None],
78
1.24k
            transform_order: Vec::new(),
79
1.24k
            width: 0,
80
1.24k
            height: 0,
81
1.24k
        }
82
1.24k
    }
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
5.08k
    pub(crate) fn decode_frame(
90
5.08k
        &mut self,
91
5.08k
        width: u32,
92
5.08k
        height: u32,
93
5.08k
        implicit_dimensions: bool,
94
5.08k
        buf: &mut [u8],
95
5.08k
    ) -> Result<(), DecodingError> {
96
5.08k
        if implicit_dimensions {
97
1.24k
            self.width = width as u16;
98
1.24k
            self.height = height as u16;
99
1.24k
        } else {
100
3.83k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.83k
            if signature != 0x2f {
102
4
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.82k
            }
104
105
3.82k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.81k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.81k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
62
                return Err(DecodingError::InconsistentImageSizes);
109
3.75k
            }
110
111
3.75k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
3.75k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
3.75k
            if version_num != 0 {
114
1
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
3.75k
            }
116
        }
117
118
5.00k
        let transformed_width = self.read_transforms()?;
119
4.43k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
4.43k
        self.decode_image_stream(
121
4.43k
            transformed_width,
122
4.43k
            self.height,
123
            true,
124
4.43k
            &mut buf[..transformed_size],
125
1.75k
        )?;
126
127
2.67k
        let mut image_size = transformed_size;
128
2.67k
        let mut width = transformed_width;
129
4.42k
        for &trans_index in self.transform_order.iter().rev() {
130
4.42k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.42k
            match transform {
132
                TransformType::PredictorTransform {
133
2.16k
                    size_bits,
134
2.16k
                    predictor_data,
135
2.16k
                } => apply_predictor_transform(
136
2.16k
                    &mut buf[..image_size],
137
2.16k
                    width,
138
2.16k
                    self.height,
139
2.16k
                    *size_bits,
140
2.16k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
66
                    size_bits,
144
66
                    transform_data,
145
66
                } => {
146
66
                    apply_color_transform(
147
66
                        &mut buf[..image_size],
148
66
                        width,
149
66
                        *size_bits,
150
66
                        transform_data,
151
66
                    );
152
66
                }
153
1.95k
                TransformType::SubtractGreen => {
154
1.95k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
1.95k
                }
156
                TransformType::ColorIndexingTransform {
157
240
                    table_size,
158
240
                    table_data,
159
240
                } => {
160
240
                    width = self.width;
161
240
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
240
                    apply_color_indexing_transform(
163
240
                        buf,
164
240
                        width,
165
240
                        self.height,
166
240
                        *table_size,
167
240
                        table_data,
168
240
                    );
169
240
                }
170
            }
171
        }
172
173
2.67k
        Ok(())
174
5.08k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
3.83k
    pub(crate) fn decode_frame(
90
3.83k
        &mut self,
91
3.83k
        width: u32,
92
3.83k
        height: u32,
93
3.83k
        implicit_dimensions: bool,
94
3.83k
        buf: &mut [u8],
95
3.83k
    ) -> Result<(), DecodingError> {
96
3.83k
        if implicit_dimensions {
97
0
            self.width = width as u16;
98
0
            self.height = height as u16;
99
0
        } else {
100
3.83k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.83k
            if signature != 0x2f {
102
4
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.82k
            }
104
105
3.82k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.81k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.81k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
62
                return Err(DecodingError::InconsistentImageSizes);
109
3.75k
            }
110
111
3.75k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
3.75k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
3.75k
            if version_num != 0 {
114
1
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
3.75k
            }
116
        }
117
118
3.75k
        let transformed_width = self.read_transforms()?;
119
3.50k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
3.50k
        self.decode_image_stream(
121
3.50k
            transformed_width,
122
3.50k
            self.height,
123
            true,
124
3.50k
            &mut buf[..transformed_size],
125
1.03k
        )?;
126
127
2.47k
        let mut image_size = transformed_size;
128
2.47k
        let mut width = transformed_width;
129
4.30k
        for &trans_index in self.transform_order.iter().rev() {
130
4.30k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.30k
            match transform {
132
                TransformType::PredictorTransform {
133
2.10k
                    size_bits,
134
2.10k
                    predictor_data,
135
2.10k
                } => apply_predictor_transform(
136
2.10k
                    &mut buf[..image_size],
137
2.10k
                    width,
138
2.10k
                    self.height,
139
2.10k
                    *size_bits,
140
2.10k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
49
                    size_bits,
144
49
                    transform_data,
145
49
                } => {
146
49
                    apply_color_transform(
147
49
                        &mut buf[..image_size],
148
49
                        width,
149
49
                        *size_bits,
150
49
                        transform_data,
151
49
                    );
152
49
                }
153
1.93k
                TransformType::SubtractGreen => {
154
1.93k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
1.93k
                }
156
                TransformType::ColorIndexingTransform {
157
214
                    table_size,
158
214
                    table_data,
159
214
                } => {
160
214
                    width = self.width;
161
214
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
214
                    apply_color_indexing_transform(
163
214
                        buf,
164
214
                        width,
165
214
                        self.height,
166
214
                        *table_size,
167
214
                        table_data,
168
214
                    );
169
214
                }
170
            }
171
        }
172
173
2.47k
        Ok(())
174
3.83k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
1.24k
    pub(crate) fn decode_frame(
90
1.24k
        &mut self,
91
1.24k
        width: u32,
92
1.24k
        height: u32,
93
1.24k
        implicit_dimensions: bool,
94
1.24k
        buf: &mut [u8],
95
1.24k
    ) -> Result<(), DecodingError> {
96
1.24k
        if implicit_dimensions {
97
1.24k
            self.width = width as u16;
98
1.24k
            self.height = height as u16;
99
1.24k
        } 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
1.24k
        let transformed_width = self.read_transforms()?;
119
928
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
928
        self.decode_image_stream(
121
928
            transformed_width,
122
928
            self.height,
123
            true,
124
928
            &mut buf[..transformed_size],
125
724
        )?;
126
127
204
        let mut image_size = transformed_size;
128
204
        let mut width = transformed_width;
129
204
        for &trans_index in self.transform_order.iter().rev() {
130
124
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
124
            match transform {
132
                TransformType::PredictorTransform {
133
60
                    size_bits,
134
60
                    predictor_data,
135
60
                } => apply_predictor_transform(
136
60
                    &mut buf[..image_size],
137
60
                    width,
138
60
                    self.height,
139
60
                    *size_bits,
140
60
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
17
                    size_bits,
144
17
                    transform_data,
145
17
                } => {
146
17
                    apply_color_transform(
147
17
                        &mut buf[..image_size],
148
17
                        width,
149
17
                        *size_bits,
150
17
                        transform_data,
151
17
                    );
152
17
                }
153
21
                TransformType::SubtractGreen => {
154
21
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
21
                }
156
                TransformType::ColorIndexingTransform {
157
26
                    table_size,
158
26
                    table_data,
159
26
                } => {
160
26
                    width = self.width;
161
26
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
26
                    apply_color_indexing_transform(
163
26
                        buf,
164
26
                        width,
165
26
                        self.height,
166
26
                        *table_size,
167
26
                        table_data,
168
26
                    );
169
26
                }
170
            }
171
        }
172
173
204
        Ok(())
174
1.24k
    }
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
8.83k
    fn decode_image_stream(
182
8.83k
        &mut self,
183
8.83k
        xsize: u16,
184
8.83k
        ysize: u16,
185
8.83k
        is_argb_img: bool,
186
8.83k
        data: &mut [u8],
187
8.83k
    ) -> Result<(), DecodingError> {
188
8.83k
        let color_cache_bits = self.read_color_cache()?;
189
8.77k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
1.77k
            color_cache_bits: bits,
191
1.77k
            color_cache: vec![[0; 4]; 1 << bits],
192
1.77k
        });
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
954
            color_cache_bits: bits,
191
954
            color_cache: vec![[0; 4]; 1 << bits],
192
954
        });
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
816
            color_cache_bits: bits,
191
816
            color_cache: vec![[0; 4]; 1 << bits],
192
816
        });
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream::{closure#0}
193
194
8.77k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
7.22k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
8.83k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
6.76k
    fn decode_image_stream(
182
6.76k
        &mut self,
183
6.76k
        xsize: u16,
184
6.76k
        ysize: u16,
185
6.76k
        is_argb_img: bool,
186
6.76k
        data: &mut [u8],
187
6.76k
    ) -> Result<(), DecodingError> {
188
6.76k
        let color_cache_bits = self.read_color_cache()?;
189
6.72k
        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
6.72k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
5.91k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
6.76k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
2.07k
    fn decode_image_stream(
182
2.07k
        &mut self,
183
2.07k
        xsize: u16,
184
2.07k
        ysize: u16,
185
2.07k
        is_argb_img: bool,
186
2.07k
        data: &mut [u8],
187
2.07k
    ) -> Result<(), DecodingError> {
188
2.07k
        let color_cache_bits = self.read_color_cache()?;
189
2.04k
        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
2.04k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
1.30k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
2.07k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream
197
198
    /// Reads transforms and their data from the bitstream
199
5.00k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
5.00k
        let mut xsize = self.width;
201
202
10.3k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
5.87k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
5.85k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
7
                return Err(DecodingError::TransformError);
208
5.85k
            }
209
210
5.85k
            self.transform_order.push(transform_type_val);
211
212
5.85k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.73k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.72k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.72k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.72k
                    let mut predictor_data =
222
2.72k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.72k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.46k
                    TransformType::PredictorTransform {
226
2.46k
                        size_bits,
227
2.46k
                        predictor_data,
228
2.46k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
246
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
239
                    let block_xsize = subsample_size(xsize, size_bits);
236
239
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
239
                    let mut transform_data =
239
239
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
239
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
151
                    TransformType::ColorTransform {
243
151
                        size_bits,
244
151
                        transform_data,
245
151
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.29k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
575
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
568
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
568
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
459
                    let bits = if color_table_size <= 2 {
259
162
                        3
260
297
                    } else if color_table_size <= 4 {
261
102
                        2
262
195
                    } else if color_table_size <= 16 {
263
86
                        1
264
                    } else {
265
109
                        0
266
                    };
267
459
                    xsize = subsample_size(xsize, bits);
268
269
459
                    Self::adjust_color_map(&mut color_map);
270
271
459
                    TransformType::ColorIndexingTransform {
272
459
                        table_size: color_table_size,
273
459
                        table_data: color_map,
274
459
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
5.37k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
4.43k
        Ok(xsize)
283
5.00k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
3.75k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
3.75k
        let mut xsize = self.width;
201
202
8.46k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
4.89k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
4.87k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
4
                return Err(DecodingError::TransformError);
208
4.87k
            }
209
210
4.87k
            self.transform_order.push(transform_type_val);
211
212
4.87k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.34k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.33k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.33k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.33k
                    let mut predictor_data =
222
2.33k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.33k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.25k
                    TransformType::PredictorTransform {
226
2.25k
                        size_bits,
227
2.25k
                        predictor_data,
228
2.25k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
124
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
121
                    let block_xsize = subsample_size(xsize, size_bits);
236
121
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
121
                    let mut transform_data =
239
121
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
121
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
95
                    TransformType::ColorTransform {
243
95
                        size_bits,
244
95
                        transform_data,
245
95
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.07k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
332
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
327
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
327
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
286
                    let bits = if color_table_size <= 2 {
259
59
                        3
260
227
                    } else if color_table_size <= 4 {
261
68
                        2
262
159
                    } else if color_table_size <= 16 {
263
78
                        1
264
                    } else {
265
81
                        0
266
                    };
267
286
                    xsize = subsample_size(xsize, bits);
268
269
286
                    Self::adjust_color_map(&mut color_map);
270
271
286
                    TransformType::ColorIndexingTransform {
272
286
                        table_size: color_table_size,
273
286
                        table_data: color_map,
274
286
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
4.70k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
3.50k
        Ok(xsize)
283
3.75k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
1.24k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
1.24k
        let mut xsize = self.width;
201
202
1.91k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
984
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
982
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
3
                return Err(DecodingError::TransformError);
208
979
            }
209
210
979
            self.transform_order.push(transform_type_val);
211
212
979
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
390
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
387
                    let block_xsize = subsample_size(xsize, size_bits);
219
387
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
387
                    let mut predictor_data =
222
387
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
387
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
212
                    TransformType::PredictorTransform {
226
212
                        size_bits,
227
212
                        predictor_data,
228
212
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
122
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
118
                    let block_xsize = subsample_size(xsize, size_bits);
236
118
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
118
                    let mut transform_data =
239
118
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
118
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
56
                    TransformType::ColorTransform {
243
56
                        size_bits,
244
56
                        transform_data,
245
56
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
224
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
243
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
241
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
241
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
173
                    let bits = if color_table_size <= 2 {
259
103
                        3
260
70
                    } else if color_table_size <= 4 {
261
34
                        2
262
36
                    } else if color_table_size <= 16 {
263
8
                        1
264
                    } else {
265
28
                        0
266
                    };
267
173
                    xsize = subsample_size(xsize, bits);
268
269
173
                    Self::adjust_color_map(&mut color_map);
270
271
173
                    TransformType::ColorIndexingTransform {
272
173
                        table_size: color_table_size,
273
173
                        table_data: color_map,
274
173
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
665
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
928
        Ok(xsize)
283
1.24k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_transforms
284
285
    /// Adjusts the color map since it's subtraction coded
286
459
    fn adjust_color_map(color_map: &mut [u8]) {
287
69.1k
        for i in 4..color_map.len() {
288
69.1k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
69.1k
        }
290
459
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
286
    fn adjust_color_map(color_map: &mut [u8]) {
287
54.0k
        for i in 4..color_map.len() {
288
54.0k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
54.0k
        }
290
286
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
173
    fn adjust_color_map(color_map: &mut [u8]) {
287
15.0k
        for i in 4..color_map.len() {
288
15.0k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
15.0k
        }
290
173
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::adjust_color_map
291
292
    /// Reads huffman codes associated with an image
293
8.77k
    fn read_huffman_codes(
294
8.77k
        &mut self,
295
8.77k
        read_meta: bool,
296
8.77k
        xsize: u16,
297
8.77k
        ysize: u16,
298
8.77k
        color_cache: Option<ColorCache>,
299
8.77k
    ) -> Result<HuffmanInfo, DecodingError> {
300
8.77k
        let mut num_huff_groups = 1u32;
301
302
8.77k
        let mut huffman_bits = 0;
303
8.77k
        let mut huffman_xsize = 1;
304
8.77k
        let mut huffman_ysize = 1;
305
8.77k
        let mut entropy_image = Vec::new();
306
307
8.77k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
884
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
870
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
870
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
870
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
870
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
619
            entropy_image = data
317
619
                .chunks_exact(4)
318
49.1M
                .map(|pixel| {
319
49.1M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
49.1M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
670
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
49.1M
                    }
323
49.1M
                    meta_huff_code
324
49.1M
                })
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
43.6M
                .map(|pixel| {
319
43.6M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
43.6M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
427
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
43.6M
                    }
323
43.6M
                    meta_huff_code
324
43.6M
                })
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
5.56M
                .map(|pixel| {
319
5.56M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
5.56M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
243
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
5.56M
                    }
323
5.56M
                    meta_huff_code
324
5.56M
                })
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes::{closure#0}
325
619
                .collect::<Vec<u16>>();
326
7.88k
        }
327
328
8.50k
        let mut hufftree_groups = Vec::new();
329
330
22.3k
        for _i in 0..num_huff_groups {
331
22.3k
            let mut group: HuffmanCodeGroup = Default::default();
332
129k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
108k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
108k
                if j == 0 {
335
22.3k
                    if let Some(color_cache) = color_cache.as_ref() {
336
9.48k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
12.8k
                    }
338
85.7k
                }
339
340
108k
                let tree = self.read_huffman_code(alphabet_size)?;
341
106k
                group[j] = tree;
342
            }
343
21.0k
            hufftree_groups.push(group);
344
        }
345
346
7.22k
        let huffman_mask = if huffman_bits == 0 {
347
7.06k
            !0
348
        } else {
349
159
            (1 << huffman_bits) - 1
350
        };
351
352
7.22k
        let info = HuffmanInfo {
353
7.22k
            xsize: huffman_xsize,
354
7.22k
            _ysize: huffman_ysize,
355
7.22k
            color_cache,
356
7.22k
            image: entropy_image,
357
7.22k
            bits: huffman_bits,
358
7.22k
            mask: huffman_mask,
359
7.22k
            huffman_code_groups: hufftree_groups,
360
7.22k
        };
361
362
7.22k
        Ok(info)
363
8.77k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
6.72k
    fn read_huffman_codes(
294
6.72k
        &mut self,
295
6.72k
        read_meta: bool,
296
6.72k
        xsize: u16,
297
6.72k
        ysize: u16,
298
6.72k
        color_cache: Option<ColorCache>,
299
6.72k
    ) -> Result<HuffmanInfo, DecodingError> {
300
6.72k
        let mut num_huff_groups = 1u32;
301
302
6.72k
        let mut huffman_bits = 0;
303
6.72k
        let mut huffman_xsize = 1;
304
6.72k
        let mut huffman_ysize = 1;
305
6.72k
        let mut entropy_image = Vec::new();
306
307
6.72k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
487
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
474
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
474
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
474
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
474
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
360
            entropy_image = data
317
360
                .chunks_exact(4)
318
360
                .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
360
                .collect::<Vec<u16>>();
326
6.24k
        }
327
328
6.60k
        let mut hufftree_groups = Vec::new();
329
330
16.3k
        for _i in 0..num_huff_groups {
331
16.3k
            let mut group: HuffmanCodeGroup = Default::default();
332
95.2k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
79.6k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
79.6k
                if j == 0 {
335
16.3k
                    if let Some(color_cache) = color_cache.as_ref() {
336
8.39k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
8.39k
                    }
338
63.3k
                }
339
340
79.6k
                let tree = self.read_huffman_code(alphabet_size)?;
341
78.9k
                group[j] = tree;
342
            }
343
15.6k
            hufftree_groups.push(group);
344
        }
345
346
5.91k
        let huffman_mask = if huffman_bits == 0 {
347
5.85k
            !0
348
        } else {
349
62
            (1 << huffman_bits) - 1
350
        };
351
352
5.91k
        let info = HuffmanInfo {
353
5.91k
            xsize: huffman_xsize,
354
5.91k
            _ysize: huffman_ysize,
355
5.91k
            color_cache,
356
5.91k
            image: entropy_image,
357
5.91k
            bits: huffman_bits,
358
5.91k
            mask: huffman_mask,
359
5.91k
            huffman_code_groups: hufftree_groups,
360
5.91k
        };
361
362
5.91k
        Ok(info)
363
6.72k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
2.04k
    fn read_huffman_codes(
294
2.04k
        &mut self,
295
2.04k
        read_meta: bool,
296
2.04k
        xsize: u16,
297
2.04k
        ysize: u16,
298
2.04k
        color_cache: Option<ColorCache>,
299
2.04k
    ) -> Result<HuffmanInfo, DecodingError> {
300
2.04k
        let mut num_huff_groups = 1u32;
301
302
2.04k
        let mut huffman_bits = 0;
303
2.04k
        let mut huffman_xsize = 1;
304
2.04k
        let mut huffman_ysize = 1;
305
2.04k
        let mut entropy_image = Vec::new();
306
307
2.04k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
397
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
396
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
396
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
396
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
396
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
259
            entropy_image = data
317
259
                .chunks_exact(4)
318
259
                .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
259
                .collect::<Vec<u16>>();
326
1.64k
        }
327
328
1.90k
        let mut hufftree_groups = Vec::new();
329
330
6.00k
        for _i in 0..num_huff_groups {
331
6.00k
            let mut group: HuffmanCodeGroup = Default::default();
332
33.8k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
28.4k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
28.4k
                if j == 0 {
335
6.00k
                    if let Some(color_cache) = color_cache.as_ref() {
336
1.08k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
4.91k
                    }
338
22.4k
                }
339
340
28.4k
                let tree = self.read_huffman_code(alphabet_size)?;
341
27.8k
                group[j] = tree;
342
            }
343
5.41k
            hufftree_groups.push(group);
344
        }
345
346
1.30k
        let huffman_mask = if huffman_bits == 0 {
347
1.20k
            !0
348
        } else {
349
97
            (1 << huffman_bits) - 1
350
        };
351
352
1.30k
        let info = HuffmanInfo {
353
1.30k
            xsize: huffman_xsize,
354
1.30k
            _ysize: huffman_ysize,
355
1.30k
            color_cache,
356
1.30k
            image: entropy_image,
357
1.30k
            bits: huffman_bits,
358
1.30k
            mask: huffman_mask,
359
1.30k
            huffman_code_groups: hufftree_groups,
360
1.30k
        };
361
362
1.30k
        Ok(info)
363
2.04k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes
364
365
    /// Decodes and returns a single huffman tree
366
108k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
108k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
108k
        if simple {
370
95.2k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
95.0k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
95.0k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
94.9k
            if zero_symbol >= alphabet_size {
376
12
                return Err(DecodingError::BitStreamError);
377
94.9k
            }
378
379
94.9k
            if num_symbols == 1 {
380
85.8k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
9.09k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
9.05k
                if one_symbol >= alphabet_size {
384
26
                    return Err(DecodingError::BitStreamError);
385
9.03k
                }
386
9.03k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
12.8k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
12.8k
            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.1k
            let new_code_lengths =
398
12.6k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
12.1k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
108k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
79.6k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
79.6k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
79.6k
        if simple {
370
68.7k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
68.7k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
68.6k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
68.6k
            if zero_symbol >= alphabet_size {
376
5
                return Err(DecodingError::BitStreamError);
377
68.6k
            }
378
379
68.6k
            if num_symbols == 1 {
380
61.9k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
6.72k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
6.69k
                if one_symbol >= alphabet_size {
384
12
                    return Err(DecodingError::BitStreamError);
385
6.68k
                }
386
6.68k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
10.8k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
10.8k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
157k
            for i in 0..num_code_lengths {
393
157k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
157k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
10.4k
            let new_code_lengths =
398
10.6k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
10.4k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
79.6k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
28.4k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
28.4k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
28.4k
        if simple {
370
26.4k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
26.3k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
26.3k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
26.3k
            if zero_symbol >= alphabet_size {
376
7
                return Err(DecodingError::BitStreamError);
377
26.3k
            }
378
379
26.3k
            if num_symbols == 1 {
380
23.9k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
2.37k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
2.35k
                if one_symbol >= alphabet_size {
384
14
                    return Err(DecodingError::BitStreamError);
385
2.34k
                }
386
2.34k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
2.06k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
2.06k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
15.9k
            for i in 0..num_code_lengths {
393
15.8k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
15.9k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
1.65k
            let new_code_lengths =
398
1.95k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
1.65k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
28.4k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code
403
404
    /// Reads huffman code lengths
405
12.6k
    fn read_huffman_code_lengths(
406
12.6k
        &mut self,
407
12.6k
        code_length_code_lengths: Vec<u16>,
408
12.6k
        num_symbols: u16,
409
12.6k
    ) -> Result<Vec<u16>, DecodingError> {
410
12.6k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
12.3k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
8.59k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
8.58k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
8.56k
            if max_minus_two > num_symbols - 2 {
416
8
                return Err(DecodingError::BitStreamError);
417
8.55k
            }
418
8.55k
            2 + max_minus_two
419
        } else {
420
3.75k
            num_symbols
421
        };
422
423
12.3k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
12.3k
        let mut prev_code_len = 8; //default code length
425
426
12.3k
        let mut symbol = 0;
427
1.75M
        while symbol < num_symbols {
428
1.74M
            if max_symbol == 0 {
429
3.90k
                break;
430
1.73M
            }
431
1.73M
            max_symbol -= 1;
432
433
1.73M
            self.bit_reader.fill()?;
434
1.73M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.73M
            if code_len < 16 {
437
1.71M
                code_lengths[usize::from(symbol)] = code_len;
438
1.71M
                symbol += 1;
439
1.71M
                if code_len != 0 {
440
718k
                    prev_code_len = code_len;
441
992k
                }
442
            } else {
443
28.2k
                let use_prev = code_len == 16;
444
28.2k
                let slot = code_len - 16;
445
28.2k
                let extra_bits = match slot {
446
14.3k
                    0 => 2,
447
5.72k
                    1 => 3,
448
8.24k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
28.2k
                let repeat_offset = match slot {
452
20.0k
                    0 | 1 => 3,
453
8.24k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
28.2k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
28.1k
                if symbol + repeat > num_symbols {
460
37
                    return Err(DecodingError::BitStreamError);
461
28.1k
                }
462
463
28.1k
                let length = if use_prev { prev_code_len } else { 0 };
464
743k
                while repeat > 0 {
465
715k
                    repeat -= 1;
466
715k
                    code_lengths[usize::from(symbol)] = length;
467
715k
                    symbol += 1;
468
715k
                }
469
            }
470
        }
471
472
12.1k
        Ok(code_lengths)
473
12.6k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
10.6k
    fn read_huffman_code_lengths(
406
10.6k
        &mut self,
407
10.6k
        code_length_code_lengths: Vec<u16>,
408
10.6k
        num_symbols: u16,
409
10.6k
    ) -> Result<Vec<u16>, DecodingError> {
410
10.6k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
10.5k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
7.58k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
7.58k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
7.56k
            if max_minus_two > num_symbols - 2 {
416
4
                return Err(DecodingError::BitStreamError);
417
7.56k
            }
418
7.56k
            2 + max_minus_two
419
        } else {
420
3.00k
            num_symbols
421
        };
422
423
10.5k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
10.5k
        let mut prev_code_len = 8; //default code length
425
426
10.5k
        let mut symbol = 0;
427
1.72M
        while symbol < num_symbols {
428
1.71M
            if max_symbol == 0 {
429
2.92k
                break;
430
1.71M
            }
431
1.71M
            max_symbol -= 1;
432
433
1.71M
            self.bit_reader.fill()?;
434
1.71M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.71M
            if code_len < 16 {
437
1.69M
                code_lengths[usize::from(symbol)] = code_len;
438
1.69M
                symbol += 1;
439
1.69M
                if code_len != 0 {
440
700k
                    prev_code_len = code_len;
441
991k
                }
442
            } else {
443
21.2k
                let use_prev = code_len == 16;
444
21.2k
                let slot = code_len - 16;
445
21.2k
                let extra_bits = match slot {
446
12.1k
                    0 => 2,
447
4.26k
                    1 => 3,
448
4.87k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
21.2k
                let repeat_offset = match slot {
452
16.4k
                    0 | 1 => 3,
453
4.87k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
21.2k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
21.2k
                if symbol + repeat > num_symbols {
460
17
                    return Err(DecodingError::BitStreamError);
461
21.2k
                }
462
463
21.2k
                let length = if use_prev { prev_code_len } else { 0 };
464
440k
                while repeat > 0 {
465
419k
                    repeat -= 1;
466
419k
                    code_lengths[usize::from(symbol)] = length;
467
419k
                    symbol += 1;
468
419k
                }
469
            }
470
        }
471
472
10.4k
        Ok(code_lengths)
473
10.6k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
1.95k
    fn read_huffman_code_lengths(
406
1.95k
        &mut self,
407
1.95k
        code_length_code_lengths: Vec<u16>,
408
1.95k
        num_symbols: u16,
409
1.95k
    ) -> Result<Vec<u16>, DecodingError> {
410
1.95k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
1.75k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
1.00k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
1.00k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
996
            if max_minus_two > num_symbols - 2 {
416
4
                return Err(DecodingError::BitStreamError);
417
992
            }
418
992
            2 + max_minus_two
419
        } else {
420
749
            num_symbols
421
        };
422
423
1.74k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
1.74k
        let mut prev_code_len = 8; //default code length
425
426
1.74k
        let mut symbol = 0;
427
28.4k
        while symbol < num_symbols {
428
27.7k
            if max_symbol == 0 {
429
981
                break;
430
26.7k
            }
431
26.7k
            max_symbol -= 1;
432
433
26.7k
            self.bit_reader.fill()?;
434
26.7k
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
26.7k
            if code_len < 16 {
437
19.7k
                code_lengths[usize::from(symbol)] = code_len;
438
19.7k
                symbol += 1;
439
19.7k
                if code_len != 0 {
440
18.3k
                    prev_code_len = code_len;
441
18.3k
                }
442
            } else {
443
6.98k
                let use_prev = code_len == 16;
444
6.98k
                let slot = code_len - 16;
445
6.98k
                let extra_bits = match slot {
446
2.15k
                    0 => 2,
447
1.45k
                    1 => 3,
448
3.37k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
6.98k
                let repeat_offset = match slot {
452
3.61k
                    0 | 1 => 3,
453
3.37k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
6.98k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
6.94k
                if symbol + repeat > num_symbols {
460
20
                    return Err(DecodingError::BitStreamError);
461
6.92k
                }
462
463
6.92k
                let length = if use_prev { prev_code_len } else { 0 };
464
302k
                while repeat > 0 {
465
296k
                    repeat -= 1;
466
296k
                    code_lengths[usize::from(symbol)] = length;
467
296k
                    symbol += 1;
468
296k
                }
469
            }
470
        }
471
472
1.65k
        Ok(code_lengths)
473
1.95k
    }
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
7.22k
    fn decode_image_data(
477
7.22k
        &mut self,
478
7.22k
        width: u16,
479
7.22k
        height: u16,
480
7.22k
        mut huffman_info: HuffmanInfo,
481
7.22k
        data: &mut [u8],
482
7.22k
    ) -> Result<(), DecodingError> {
483
7.22k
        let num_values = usize::from(width) * usize::from(height);
484
485
7.22k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
7.22k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
7.22k
        let mut index = 0;
488
489
7.22k
        let mut next_block_start = 0;
490
210M
        while index < num_values {
491
210M
            self.bit_reader.fill()?;
492
493
210M
            if index >= next_block_start {
494
86.2M
                let x = index % usize::from(width);
495
86.2M
                let y = index / usize::from(width);
496
86.2M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
86.2M
                    + y * usize::from(width)
498
86.2M
                    + 1;
499
500
86.2M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
86.2M
                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
343M
                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
271M
                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
72.0M
                if tree[..4].iter().all(|t| t.is_single_node()) {
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data::{closure#0}
508
85.5M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
85.5M
                    if code < 256 {
510
85.5M
                        let n = if huffman_info.bits == 0 {
511
3.33k
                            num_values
512
                        } else {
513
85.5M
                            next_block_start - index
514
                        };
515
516
85.5M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
85.5M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
85.5M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
85.5M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
5.82G
                        for i in 0..n {
522
5.82G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
5.82G
                        }
524
525
85.5M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
36.8M
                            color_cache.insert(value);
527
48.7M
                        }
528
529
85.5M
                        index += n;
530
85.5M
                        continue;
531
40.3k
                    }
532
673k
                }
533
124M
            }
534
535
125M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
125M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
15.8M
                let green = code as u8;
541
15.8M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
15.8M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
15.8M
                if self.bit_reader.nbits < 15 {
544
7.46k
                    self.bit_reader.fill()?;
545
15.7M
                }
546
15.8M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
15.8M
                data[index * 4] = red;
549
15.8M
                data[index * 4 + 1] = green;
550
15.8M
                data[index * 4 + 2] = blue;
551
15.8M
                data[index * 4 + 3] = alpha;
552
553
15.8M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
2.84M
                    color_cache.insert([red, green, blue, alpha]);
555
12.9M
                }
556
15.8M
                index += 1;
557
109M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
4.20M
                let length_symbol = code - 256;
560
4.20M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
4.20M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
4.20M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
4.20M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
4.20M
                if index < dist || num_values - index < length {
567
78
                    return Err(DecodingError::BitStreamError);
568
4.20M
                }
569
570
4.20M
                if dist == 1 {
571
2.14M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
942M
                    for i in 0..length {
573
942M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
942M
                    }
575
                } else {
576
2.05M
                    if index + length + 3 <= num_values {
577
2.05M
                        let start = (index - dist) * 4;
578
2.05M
                        data.copy_within(start..start + 16, index * 4);
579
580
2.05M
                        if length > 4 || dist < 4 {
581
226M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
226M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
226M
                            }
584
8.87k
                        }
585
                    } else {
586
62.0k
                        for i in 0..length * 4 {
587
62.0k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
62.0k
                        }
589
                    }
590
591
2.05M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
893M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
893M
                            color_cache.insert(pixel.try_into().unwrap());
594
893M
                        }
595
25.5k
                    }
596
                }
597
4.20M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
105M
                let color_cache = huffman_info
601
105M
                    .color_cache
602
105M
                    .as_mut()
603
105M
                    .ok_or(DecodingError::BitStreamError)?;
604
105M
                let color = color_cache.lookup((code - 280).into());
605
105M
                data[index * 4..][..4].copy_from_slice(&color);
606
105M
                index += 1;
607
608
105M
                if index < next_block_start {
609
105M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
105M
                        if code >= 280 {
611
104M
                            self.bit_reader.consume(bits)?;
612
104M
                            data[index * 4..][..4]
613
104M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
104M
                            index += 1;
615
1.09M
                        }
616
280
                    }
617
55.5k
                }
618
            }
619
        }
620
621
6.37k
        Ok(())
622
7.22k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
5.91k
    fn decode_image_data(
477
5.91k
        &mut self,
478
5.91k
        width: u16,
479
5.91k
        height: u16,
480
5.91k
        mut huffman_info: HuffmanInfo,
481
5.91k
        data: &mut [u8],
482
5.91k
    ) -> Result<(), DecodingError> {
483
5.91k
        let num_values = usize::from(width) * usize::from(height);
484
485
5.91k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
5.91k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
5.91k
        let mut index = 0;
488
489
5.91k
        let mut next_block_start = 0;
490
184M
        while index < num_values {
491
184M
            self.bit_reader.fill()?;
492
493
184M
            if index >= next_block_start {
494
68.0M
                let x = index % usize::from(width);
495
68.0M
                let y = index / usize::from(width);
496
68.0M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
68.0M
                    + y * usize::from(width)
498
68.0M
                    + 1;
499
500
68.0M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
68.0M
                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
68.0M
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
67.6M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
67.6M
                    if code < 256 {
510
67.6M
                        let n = if huffman_info.bits == 0 {
511
2.99k
                            num_values
512
                        } else {
513
67.6M
                            next_block_start - index
514
                        };
515
516
67.6M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
67.6M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
67.6M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
67.6M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
5.32G
                        for i in 0..n {
522
5.32G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
5.32G
                        }
524
525
67.6M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
36.8M
                            color_cache.insert(value);
527
36.8M
                        }
528
529
67.6M
                        index += n;
530
67.6M
                        continue;
531
25.3k
                    }
532
355k
                }
533
116M
            }
534
535
116M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
116M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
13.1M
                let green = code as u8;
541
13.1M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
13.1M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
13.1M
                if self.bit_reader.nbits < 15 {
544
5.88k
                    self.bit_reader.fill()?;
545
13.1M
                }
546
13.1M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
13.1M
                data[index * 4] = red;
549
13.1M
                data[index * 4 + 1] = green;
550
13.1M
                data[index * 4 + 2] = blue;
551
13.1M
                data[index * 4 + 3] = alpha;
552
553
13.1M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
358k
                    color_cache.insert([red, green, blue, alpha]);
555
12.8M
                }
556
13.1M
                index += 1;
557
103M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
527k
                let length_symbol = code - 256;
560
527k
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
527k
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
527k
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
527k
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
527k
                if index < dist || num_values - index < length {
567
44
                    return Err(DecodingError::BitStreamError);
568
526k
                }
569
570
526k
                if dist == 1 {
571
355k
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
601M
                    for i in 0..length {
573
601M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
601M
                    }
575
                } else {
576
171k
                    if index + length + 3 <= num_values {
577
171k
                        let start = (index - dist) * 4;
578
171k
                        data.copy_within(start..start + 16, index * 4);
579
580
171k
                        if length > 4 || dist < 4 {
581
134M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
134M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
134M
                            }
584
6.95k
                        }
585
                    } else {
586
28.8k
                        for i in 0..length * 4 {
587
28.8k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
28.8k
                        }
589
                    }
590
591
171k
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
520M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
520M
                            color_cache.insert(pixel.try_into().unwrap());
594
520M
                        }
595
7.98k
                    }
596
                }
597
526k
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
103M
                let color_cache = huffman_info
601
103M
                    .color_cache
602
103M
                    .as_mut()
603
103M
                    .ok_or(DecodingError::BitStreamError)?;
604
103M
                let color = color_cache.lookup((code - 280).into());
605
103M
                data[index * 4..][..4].copy_from_slice(&color);
606
103M
                index += 1;
607
608
103M
                if index < next_block_start {
609
103M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
103M
                        if code >= 280 {
611
103M
                            self.bit_reader.consume(bits)?;
612
103M
                            data[index * 4..][..4]
613
103M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
103M
                            index += 1;
615
6.44k
                        }
616
260
                    }
617
28.9k
                }
618
            }
619
        }
620
621
5.46k
        Ok(())
622
5.91k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
1.30k
    fn decode_image_data(
477
1.30k
        &mut self,
478
1.30k
        width: u16,
479
1.30k
        height: u16,
480
1.30k
        mut huffman_info: HuffmanInfo,
481
1.30k
        data: &mut [u8],
482
1.30k
    ) -> Result<(), DecodingError> {
483
1.30k
        let num_values = usize::from(width) * usize::from(height);
484
485
1.30k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
1.30k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
1.30k
        let mut index = 0;
488
489
1.30k
        let mut next_block_start = 0;
490
26.4M
        while index < num_values {
491
26.4M
            self.bit_reader.fill()?;
492
493
26.4M
            if index >= next_block_start {
494
18.2M
                let x = index % usize::from(width);
495
18.2M
                let y = index / usize::from(width);
496
18.2M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
18.2M
                    + y * usize::from(width)
498
18.2M
                    + 1;
499
500
18.2M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
18.2M
                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
18.2M
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
17.9M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
17.9M
                    if code < 256 {
510
17.9M
                        let n = if huffman_info.bits == 0 {
511
341
                            num_values
512
                        } else {
513
17.9M
                            next_block_start - index
514
                        };
515
516
17.9M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
17.9M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
17.9M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
17.9M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
504M
                        for i in 0..n {
522
504M
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
504M
                        }
524
525
17.9M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
1.85k
                            color_cache.insert(value);
527
17.9M
                        }
528
529
17.9M
                        index += n;
530
17.9M
                        continue;
531
14.9k
                    }
532
317k
                }
533
8.21M
            }
534
535
8.54M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
8.54M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
2.62M
                let green = code as u8;
541
2.62M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
2.62M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
2.62M
                if self.bit_reader.nbits < 15 {
544
1.57k
                    self.bit_reader.fill()?;
545
2.62M
                }
546
2.62M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
2.62M
                data[index * 4] = red;
549
2.62M
                data[index * 4 + 1] = green;
550
2.62M
                data[index * 4 + 2] = blue;
551
2.62M
                data[index * 4 + 3] = alpha;
552
553
2.62M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
2.49M
                    color_cache.insert([red, green, blue, alpha]);
555
2.49M
                }
556
2.62M
                index += 1;
557
5.92M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
3.67M
                let length_symbol = code - 256;
560
3.67M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
3.67M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
3.67M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
3.67M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
3.67M
                if index < dist || num_values - index < length {
567
34
                    return Err(DecodingError::BitStreamError);
568
3.67M
                }
569
570
3.67M
                if dist == 1 {
571
1.79M
                    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.88M
                    if index + length + 3 <= num_values {
577
1.88M
                        let start = (index - dist) * 4;
578
1.88M
                        data.copy_within(start..start + 16, index * 4);
579
580
1.88M
                        if length > 4 || dist < 4 {
581
92.2M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
92.2M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
92.2M
                            }
584
1.91k
                        }
585
                    } else {
586
33.2k
                        for i in 0..length * 4 {
587
33.2k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
33.2k
                        }
589
                    }
590
591
1.88M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
372M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
372M
                            color_cache.insert(pixel.try_into().unwrap());
594
372M
                        }
595
17.5k
                    }
596
                }
597
3.67M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
2.24M
                let color_cache = huffman_info
601
2.24M
                    .color_cache
602
2.24M
                    .as_mut()
603
2.24M
                    .ok_or(DecodingError::BitStreamError)?;
604
2.24M
                let color = color_cache.lookup((code - 280).into());
605
2.24M
                data[index * 4..][..4].copy_from_slice(&color);
606
2.24M
                index += 1;
607
608
2.24M
                if index < next_block_start {
609
2.21M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
2.21M
                        if code >= 280 {
611
1.13M
                            self.bit_reader.consume(bits)?;
612
1.13M
                            data[index * 4..][..4]
613
1.13M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
1.13M
                            index += 1;
615
1.08M
                        }
616
20
                    }
617
26.6k
                }
618
            }
619
        }
620
621
904
        Ok(())
622
1.30k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data
623
624
    /// Reads color cache data from the bitstream
625
8.83k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
8.83k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
1.82k
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
1.79k
            if !(1..=11).contains(&code_bits) {
630
23
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
1.77k
            }
632
633
1.77k
            Ok(Some(code_bits))
634
        } else {
635
7.00k
            Ok(None)
636
        }
637
8.83k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
6.76k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
6.76k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
983
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
965
            if !(1..=11).contains(&code_bits) {
630
11
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
954
            }
632
633
954
            Ok(Some(code_bits))
634
        } else {
635
5.77k
            Ok(None)
636
        }
637
6.76k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
2.07k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
2.07k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
840
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
828
            if !(1..=11).contains(&code_bits) {
630
12
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
816
            }
632
633
816
            Ok(Some(code_bits))
634
        } else {
635
1.22k
            Ok(None)
636
        }
637
2.07k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_color_cache
638
639
    /// Gets the copy distance from the prefix code and bitstream
640
8.40M
    fn get_copy_distance(
641
8.40M
        bit_reader: &mut BitReader<R>,
642
8.40M
        prefix_code: u16,
643
8.40M
    ) -> Result<usize, DecodingError> {
644
8.40M
        if prefix_code < 4 {
645
2.35M
            return Ok(usize::from(prefix_code + 1));
646
6.04M
        }
647
6.04M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
6.04M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
6.04M
        let bits = bit_reader.peek(extra_bits) as usize;
651
6.04M
        bit_reader.consume(extra_bits)?;
652
653
6.04M
        Ok(offset + bits + 1)
654
8.40M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
1.05M
    fn get_copy_distance(
641
1.05M
        bit_reader: &mut BitReader<R>,
642
1.05M
        prefix_code: u16,
643
1.05M
    ) -> Result<usize, DecodingError> {
644
1.05M
        if prefix_code < 4 {
645
465k
            return Ok(usize::from(prefix_code + 1));
646
588k
        }
647
588k
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
588k
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
588k
        let bits = bit_reader.peek(extra_bits) as usize;
651
588k
        bit_reader.consume(extra_bits)?;
652
653
588k
        Ok(offset + bits + 1)
654
1.05M
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
7.34M
    fn get_copy_distance(
641
7.34M
        bit_reader: &mut BitReader<R>,
642
7.34M
        prefix_code: u16,
643
7.34M
    ) -> Result<usize, DecodingError> {
644
7.34M
        if prefix_code < 4 {
645
1.88M
            return Ok(usize::from(prefix_code + 1));
646
5.46M
        }
647
5.46M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
5.46M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
5.46M
        let bits = bit_reader.peek(extra_bits) as usize;
651
5.46M
        bit_reader.consume(extra_bits)?;
652
653
5.46M
        Ok(offset + bits + 1)
654
7.34M
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::get_copy_distance
655
656
    /// Gets distance to pixel
657
4.20M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
4.20M
        if plane_code > 120 {
659
1.97M
            plane_code - 120
660
        } else {
661
2.22M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
2.22M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
2.22M
            if dist < 1 {
665
8
                return 1;
666
2.22M
            }
667
2.22M
            dist.try_into().unwrap()
668
        }
669
4.20M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
527k
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
527k
        if plane_code > 120 {
659
162k
            plane_code - 120
660
        } else {
661
364k
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
364k
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
364k
            if dist < 1 {
665
6
                return 1;
666
364k
            }
667
364k
            dist.try_into().unwrap()
668
        }
669
527k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
3.67M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
3.67M
        if plane_code > 120 {
659
1.81M
            plane_code - 120
660
        } else {
661
1.86M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
1.86M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
1.86M
            if dist < 1 {
665
2
                return 1;
666
1.86M
            }
667
1.86M
            dist.try_into().unwrap()
668
        }
669
3.67M
    }
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
86.2M
    fn get_huff_index(&self, x: u16, y: u16) -> usize {
685
86.2M
        if self.bits == 0 {
686
708k
            return 0;
687
85.5M
        }
688
85.5M
        let position =
689
85.5M
            usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits);
690
85.5M
        let meta_huff_code: usize = usize::from(self.image[position]);
691
85.5M
        meta_huff_code
692
86.2M
    }
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
932M
    fn insert(&mut self, color: [u8; 4]) {
704
932M
        let [r, g, b, a] = color;
705
932M
        let color_u32 =
706
932M
            (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24);
707
932M
        let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits);
708
932M
        self.color_cache[index as usize] = color;
709
932M
    }
710
711
    #[inline(always)]
712
209M
    fn lookup(&self, index: usize) -> [u8; 4] {
713
209M
        self.color_cache[index]
714
209M
    }
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
5.08k
    const fn new(reader: R) -> Self {
726
5.08k
        Self {
727
5.08k
            reader,
728
5.08k
            buffer: 0,
729
5.08k
            nbits: 0,
730
5.08k
        }
731
5.08k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
3.83k
    const fn new(reader: R) -> Self {
726
3.83k
        Self {
727
3.83k
            reader,
728
3.83k
            buffer: 0,
729
3.83k
            nbits: 0,
730
3.83k
        }
731
3.83k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
1.24k
    const fn new(reader: R) -> Self {
726
1.24k
        Self {
727
1.24k
            reader,
728
1.24k
            buffer: 0,
729
1.24k
            nbits: 0,
730
1.24k
        }
731
1.24k
    }
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
212M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
212M
        debug_assert!(self.nbits < 64);
739
740
212M
        let mut buf = self.reader.fill_buf()?;
741
212M
        if buf.len() >= 8 {
742
23.2M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
23.2M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
23.2M
            self.buffer |= lookahead << self.nbits;
745
23.2M
            self.nbits |= 56;
746
23.2M
        } else {
747
189M
            while !buf.is_empty() && self.nbits < 56 {
748
26.9k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
26.9k
                self.nbits += 8;
750
26.9k
                self.reader.consume(1);
751
26.9k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
212M
        Ok(())
756
212M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
186M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
186M
        debug_assert!(self.nbits < 64);
739
740
186M
        let mut buf = self.reader.fill_buf()?;
741
186M
        if buf.len() >= 8 {
742
15.3M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
15.3M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
15.3M
            self.buffer |= lookahead << self.nbits;
745
15.3M
            self.nbits |= 56;
746
15.3M
        } else {
747
170M
            while !buf.is_empty() && self.nbits < 56 {
748
20.3k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
20.3k
                self.nbits += 8;
750
20.3k
                self.reader.consume(1);
751
20.3k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
186M
        Ok(())
756
186M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
26.4M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
26.4M
        debug_assert!(self.nbits < 64);
739
740
26.4M
        let mut buf = self.reader.fill_buf()?;
741
26.4M
        if buf.len() >= 8 {
742
7.85M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
7.85M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
7.85M
            self.buffer |= lookahead << self.nbits;
745
7.85M
            self.nbits |= 56;
746
7.85M
        } else {
747
18.6M
            while !buf.is_empty() && self.nbits < 56 {
748
6.60k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
6.60k
                self.nbits += 8;
750
6.60k
                self.reader.consume(1);
751
6.60k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
26.4M
        Ok(())
756
26.4M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::fill
757
758
    /// Peeks at the next `num` bits in the buffer.
759
6.75M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
6.75M
        self.buffer & ((1 << num) - 1)
761
6.75M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
1.14M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
1.14M
        self.buffer & ((1 << num) - 1)
761
1.14M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
5.60M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
5.60M
        self.buffer & ((1 << num) - 1)
761
5.60M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek
762
763
    /// Peeks at the full buffer.
764
70.0M
    pub(crate) const fn peek_full(&self) -> u64 {
765
70.0M
        self.buffer
766
70.0M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
54.5M
    pub(crate) const fn peek_full(&self) -> u64 {
765
54.5M
        self.buffer
766
54.5M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
15.5M
    pub(crate) const fn peek_full(&self) -> u64 {
765
15.5M
        self.buffer
766
15.5M
    }
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
179M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
179M
        if self.nbits < num {
771
1.70k
            return Err(DecodingError::BitStreamError);
772
179M
        }
773
774
179M
        self.buffer >>= num;
775
179M
        self.nbits -= num;
776
179M
        Ok(())
777
179M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
158M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
158M
        if self.nbits < num {
771
1.01k
            return Err(DecodingError::BitStreamError);
772
158M
        }
773
774
158M
        self.buffer >>= num;
775
158M
        self.nbits -= num;
776
158M
        Ok(())
777
158M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
20.7M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
20.7M
        if self.nbits < num {
771
693
            return Err(DecodingError::BitStreamError);
772
20.7M
        }
773
774
20.7M
        self.buffer >>= num;
775
20.7M
        self.nbits -= num;
776
20.7M
        Ok(())
777
20.7M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::consume
778
779
    /// Convenience function to read a number of bits and convert them to a type.
780
701k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
701k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
701k
        debug_assert!(num <= 32);
783
784
701k
        if self.nbits < num {
785
22.7k
            self.fill()?;
786
678k
        }
787
701k
        let value = self.peek(num) as u32;
788
701k
        self.consume(num)?;
789
790
700k
        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
701k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
274k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
274k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
274k
        debug_assert!(num <= 32);
783
784
274k
        if self.nbits < num {
785
7.83k
            self.fill()?;
786
266k
        }
787
274k
        let value = self.peek(num) as u32;
788
274k
        self.consume(num)?;
789
790
273k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
274k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
10.8k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
10.8k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
10.8k
        debug_assert!(num <= 32);
783
784
10.8k
        if self.nbits < num {
785
136
            self.fill()?;
786
10.6k
        }
787
10.8k
        let value = self.peek(num) as u32;
788
10.8k
        self.consume(num)?;
789
790
10.7k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
10.8k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
269k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
269k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
269k
        debug_assert!(num <= 32);
783
784
269k
        if self.nbits < num {
785
11.2k
            self.fill()?;
786
258k
        }
787
269k
        let value = self.peek(num) as u32;
788
269k
        self.consume(num)?;
789
790
269k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
269k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
91.6k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
91.6k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
91.6k
        debug_assert!(num <= 32);
783
784
91.6k
        if self.nbits < num {
785
2.43k
            self.fill()?;
786
89.2k
        }
787
91.6k
        let value = self.peek(num) as u32;
788
91.6k
        self.consume(num)?;
789
790
91.5k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
91.6k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
2.06k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
2.06k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
2.06k
        debug_assert!(num <= 32);
783
784
2.06k
        if self.nbits < num {
785
19
            self.fill()?;
786
2.04k
        }
787
2.06k
        let value = self.peek(num) as u32;
788
2.06k
        self.consume(num)?;
789
790
2.05k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
2.06k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
52.8k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
52.8k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
52.8k
        debug_assert!(num <= 32);
783
784
52.8k
        if self.nbits < num {
785
1.10k
            self.fill()?;
786
51.7k
        }
787
52.8k
        let value = self.peek(num) as u32;
788
52.8k
        self.consume(num)?;
789
790
52.6k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
52.8k
    }
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
}