Coverage Report

Created: 2026-03-07 07:19

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
11.1k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
11.1k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
11.1k
        .try_into()
57
11.1k
        .unwrap()
58
11.1k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
8.79k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
8.79k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
8.79k
        .try_into()
57
8.79k
        .unwrap()
58
8.79k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
2.37k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
2.37k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
2.37k
        .try_into()
57
2.37k
        .unwrap()
58
2.37k
}
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
4.58k
    pub(crate) const fn new(r: R) -> Self {
75
4.58k
        Self {
76
4.58k
            bit_reader: BitReader::new(r),
77
4.58k
            transforms: [None, None, None, None],
78
4.58k
            transform_order: Vec::new(),
79
4.58k
            width: 0,
80
4.58k
            height: 0,
81
4.58k
        }
82
4.58k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
3.76k
    pub(crate) const fn new(r: R) -> Self {
75
3.76k
        Self {
76
3.76k
            bit_reader: BitReader::new(r),
77
3.76k
            transforms: [None, None, None, None],
78
3.76k
            transform_order: Vec::new(),
79
3.76k
            width: 0,
80
3.76k
            height: 0,
81
3.76k
        }
82
3.76k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
822
    pub(crate) const fn new(r: R) -> Self {
75
822
        Self {
76
822
            bit_reader: BitReader::new(r),
77
822
            transforms: [None, None, None, None],
78
822
            transform_order: Vec::new(),
79
822
            width: 0,
80
822
            height: 0,
81
822
        }
82
822
    }
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
4.58k
    pub(crate) fn decode_frame(
90
4.58k
        &mut self,
91
4.58k
        width: u32,
92
4.58k
        height: u32,
93
4.58k
        implicit_dimensions: bool,
94
4.58k
        buf: &mut [u8],
95
4.58k
    ) -> Result<(), DecodingError> {
96
4.58k
        if implicit_dimensions {
97
822
            self.width = width as u16;
98
822
            self.height = height as u16;
99
822
        } else {
100
3.76k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.76k
            if signature != 0x2f {
102
1
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.76k
            }
104
105
3.76k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.75k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.75k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
11
                return Err(DecodingError::InconsistentImageSizes);
109
3.74k
            }
110
111
3.74k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
3.74k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
3.74k
            if version_num != 0 {
114
1
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
3.74k
            }
116
        }
117
118
4.56k
        let transformed_width = self.read_transforms()?;
119
4.09k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
4.09k
        self.decode_image_stream(
121
4.09k
            transformed_width,
122
4.09k
            self.height,
123
            true,
124
4.09k
            &mut buf[..transformed_size],
125
1.38k
        )?;
126
127
2.71k
        let mut image_size = transformed_size;
128
2.71k
        let mut width = transformed_width;
129
4.70k
        for &trans_index in self.transform_order.iter().rev() {
130
4.70k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.70k
            match transform {
132
                TransformType::PredictorTransform {
133
2.32k
                    size_bits,
134
2.32k
                    predictor_data,
135
2.32k
                } => apply_predictor_transform(
136
2.32k
                    &mut buf[..image_size],
137
2.32k
                    width,
138
2.32k
                    self.height,
139
2.32k
                    *size_bits,
140
2.32k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
47
                    size_bits,
144
47
                    transform_data,
145
47
                } => {
146
47
                    apply_color_transform(
147
47
                        &mut buf[..image_size],
148
47
                        width,
149
47
                        *size_bits,
150
47
                        transform_data,
151
47
                    );
152
47
                }
153
2.05k
                TransformType::SubtractGreen => {
154
2.05k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
2.05k
                }
156
                TransformType::ColorIndexingTransform {
157
273
                    table_size,
158
273
                    table_data,
159
273
                } => {
160
273
                    width = self.width;
161
273
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
273
                    apply_color_indexing_transform(
163
273
                        buf,
164
273
                        width,
165
273
                        self.height,
166
273
                        *table_size,
167
273
                        table_data,
168
273
                    );
169
273
                }
170
            }
171
        }
172
173
2.71k
        Ok(())
174
4.58k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
3.76k
    pub(crate) fn decode_frame(
90
3.76k
        &mut self,
91
3.76k
        width: u32,
92
3.76k
        height: u32,
93
3.76k
        implicit_dimensions: bool,
94
3.76k
        buf: &mut [u8],
95
3.76k
    ) -> Result<(), DecodingError> {
96
3.76k
        if implicit_dimensions {
97
0
            self.width = width as u16;
98
0
            self.height = height as u16;
99
0
        } else {
100
3.76k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.76k
            if signature != 0x2f {
102
1
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.76k
            }
104
105
3.76k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.75k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.75k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
11
                return Err(DecodingError::InconsistentImageSizes);
109
3.74k
            }
110
111
3.74k
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
3.74k
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
3.74k
            if version_num != 0 {
114
1
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
3.74k
            }
116
        }
117
118
3.74k
        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
943
        )?;
126
127
2.56k
        let mut image_size = transformed_size;
128
2.56k
        let mut width = transformed_width;
129
4.57k
        for &trans_index in self.transform_order.iter().rev() {
130
4.57k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.57k
            match transform {
132
                TransformType::PredictorTransform {
133
2.26k
                    size_bits,
134
2.26k
                    predictor_data,
135
2.26k
                } => apply_predictor_transform(
136
2.26k
                    &mut buf[..image_size],
137
2.26k
                    width,
138
2.26k
                    self.height,
139
2.26k
                    *size_bits,
140
2.26k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
43
                    size_bits,
144
43
                    transform_data,
145
43
                } => {
146
43
                    apply_color_transform(
147
43
                        &mut buf[..image_size],
148
43
                        width,
149
43
                        *size_bits,
150
43
                        transform_data,
151
43
                    );
152
43
                }
153
2.05k
                TransformType::SubtractGreen => {
154
2.05k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
2.05k
                }
156
                TransformType::ColorIndexingTransform {
157
221
                    table_size,
158
221
                    table_data,
159
221
                } => {
160
221
                    width = self.width;
161
221
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
221
                    apply_color_indexing_transform(
163
221
                        buf,
164
221
                        width,
165
221
                        self.height,
166
221
                        *table_size,
167
221
                        table_data,
168
221
                    );
169
221
                }
170
            }
171
        }
172
173
2.56k
        Ok(())
174
3.76k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
822
    pub(crate) fn decode_frame(
90
822
        &mut self,
91
822
        width: u32,
92
822
        height: u32,
93
822
        implicit_dimensions: bool,
94
822
        buf: &mut [u8],
95
822
    ) -> Result<(), DecodingError> {
96
822
        if implicit_dimensions {
97
822
            self.width = width as u16;
98
822
            self.height = height as u16;
99
822
        } 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
822
        let transformed_width = self.read_transforms()?;
119
587
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
587
        self.decode_image_stream(
121
587
            transformed_width,
122
587
            self.height,
123
            true,
124
587
            &mut buf[..transformed_size],
125
439
        )?;
126
127
148
        let mut image_size = transformed_size;
128
148
        let mut width = transformed_width;
129
148
        for &trans_index in self.transform_order.iter().rev() {
130
125
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
125
            match transform {
132
                TransformType::PredictorTransform {
133
63
                    size_bits,
134
63
                    predictor_data,
135
63
                } => apply_predictor_transform(
136
63
                    &mut buf[..image_size],
137
63
                    width,
138
63
                    self.height,
139
63
                    *size_bits,
140
63
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
4
                    size_bits,
144
4
                    transform_data,
145
4
                } => {
146
4
                    apply_color_transform(
147
4
                        &mut buf[..image_size],
148
4
                        width,
149
4
                        *size_bits,
150
4
                        transform_data,
151
4
                    );
152
4
                }
153
6
                TransformType::SubtractGreen => {
154
6
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
6
                }
156
                TransformType::ColorIndexingTransform {
157
52
                    table_size,
158
52
                    table_data,
159
52
                } => {
160
52
                    width = self.width;
161
52
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
52
                    apply_color_indexing_transform(
163
52
                        buf,
164
52
                        width,
165
52
                        self.height,
166
52
                        *table_size,
167
52
                        table_data,
168
52
                    );
169
52
                }
170
            }
171
        }
172
173
148
        Ok(())
174
822
    }
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.88k
    fn decode_image_stream(
182
8.88k
        &mut self,
183
8.88k
        xsize: u16,
184
8.88k
        ysize: u16,
185
8.88k
        is_argb_img: bool,
186
8.88k
        data: &mut [u8],
187
8.88k
    ) -> Result<(), DecodingError> {
188
8.88k
        let color_cache_bits = self.read_color_cache()?;
189
8.84k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
1.30k
            color_cache_bits: bits,
191
1.30k
            color_cache: vec![[0; 4]; 1 << bits],
192
1.30k
        });
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
894
            color_cache_bits: bits,
191
894
            color_cache: vec![[0; 4]; 1 << bits],
192
894
        });
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
412
            color_cache_bits: bits,
191
412
            color_cache: vec![[0; 4]; 1 << bits],
192
412
        });
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream::{closure#0}
193
194
8.84k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
7.66k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
8.88k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
7.23k
    fn decode_image_stream(
182
7.23k
        &mut self,
183
7.23k
        xsize: u16,
184
7.23k
        ysize: u16,
185
7.23k
        is_argb_img: bool,
186
7.23k
        data: &mut [u8],
187
7.23k
    ) -> Result<(), DecodingError> {
188
7.23k
        let color_cache_bits = self.read_color_cache()?;
189
7.21k
        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
7.21k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
6.41k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
7.23k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
1.64k
    fn decode_image_stream(
182
1.64k
        &mut self,
183
1.64k
        xsize: u16,
184
1.64k
        ysize: u16,
185
1.64k
        is_argb_img: bool,
186
1.64k
        data: &mut [u8],
187
1.64k
    ) -> Result<(), DecodingError> {
188
1.64k
        let color_cache_bits = self.read_color_cache()?;
189
1.62k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
            color_cache_bits: bits,
191
            color_cache: vec![[0; 4]; 1 << bits],
192
        });
193
194
1.62k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
1.24k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
1.64k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream
197
198
    /// Reads transforms and their data from the bitstream
199
4.56k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
4.56k
        let mut xsize = self.width;
201
202
10.5k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
6.41k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
6.40k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
8
                return Err(DecodingError::TransformError);
208
6.40k
            }
209
210
6.40k
            self.transform_order.push(transform_type_val);
211
212
6.40k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.91k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.90k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.90k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.90k
                    let mut predictor_data =
222
2.90k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.90k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.66k
                    TransformType::PredictorTransform {
226
2.66k
                        size_bits,
227
2.66k
                        predictor_data,
228
2.66k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
276
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
274
                    let block_xsize = subsample_size(xsize, size_bits);
236
274
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
274
                    let mut transform_data =
239
274
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
274
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
209
                    TransformType::ColorTransform {
243
209
                        size_bits,
244
209
                        transform_data,
245
209
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.50k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
708
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
702
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
702
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
604
                    let bits = if color_table_size <= 2 {
259
151
                        3
260
453
                    } else if color_table_size <= 4 {
261
122
                        2
262
331
                    } else if color_table_size <= 16 {
263
85
                        1
264
                    } else {
265
246
                        0
266
                    };
267
604
                    xsize = subsample_size(xsize, bits);
268
269
604
                    Self::adjust_color_map(&mut color_map);
270
271
604
                    TransformType::ColorIndexingTransform {
272
604
                        table_size: color_table_size,
273
604
                        table_data: color_map,
274
604
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
5.98k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
4.09k
        Ok(xsize)
283
4.56k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
3.74k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
3.74k
        let mut xsize = self.width;
201
202
9.01k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
5.46k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
5.46k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
5
                return Err(DecodingError::TransformError);
208
5.45k
            }
209
210
5.45k
            self.transform_order.push(transform_type_val);
211
212
5.45k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.53k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.52k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.52k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.52k
                    let mut predictor_data =
222
2.52k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.52k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.42k
                    TransformType::PredictorTransform {
226
2.42k
                        size_bits,
227
2.42k
                        predictor_data,
228
2.42k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
229
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
227
                    let block_xsize = subsample_size(xsize, size_bits);
236
227
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
227
                    let mut transform_data =
239
227
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
227
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
195
                    TransformType::ColorTransform {
243
195
                        size_bits,
244
195
                        transform_data,
245
195
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.35k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
340
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
335
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
335
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
299
                    let bits = if color_table_size <= 2 {
259
49
                        3
260
250
                    } else if color_table_size <= 4 {
261
72
                        2
262
178
                    } else if color_table_size <= 16 {
263
74
                        1
264
                    } else {
265
104
                        0
266
                    };
267
299
                    xsize = subsample_size(xsize, bits);
268
269
299
                    Self::adjust_color_map(&mut color_map);
270
271
299
                    TransformType::ColorIndexingTransform {
272
299
                        table_size: color_table_size,
273
299
                        table_data: color_map,
274
299
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
5.27k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
3.50k
        Ok(xsize)
283
3.74k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_transforms
Line
Count
Source
199
822
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
822
        let mut xsize = self.width;
201
202
1.53k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
947
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
946
            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
943
            }
209
210
943
            self.transform_order.push(transform_type_val);
211
212
943
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
379
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
378
                    let block_xsize = subsample_size(xsize, size_bits);
219
378
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
378
                    let mut predictor_data =
222
378
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
378
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
245
                    TransformType::PredictorTransform {
226
245
                        size_bits,
227
245
                        predictor_data,
228
245
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
47
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
47
                    let block_xsize = subsample_size(xsize, size_bits);
236
47
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
47
                    let mut transform_data =
239
47
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
47
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
14
                    TransformType::ColorTransform {
243
14
                        size_bits,
244
14
                        transform_data,
245
14
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
149
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
368
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
367
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
367
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
305
                    let bits = if color_table_size <= 2 {
259
102
                        3
260
203
                    } else if color_table_size <= 4 {
261
50
                        2
262
153
                    } else if color_table_size <= 16 {
263
11
                        1
264
                    } else {
265
142
                        0
266
                    };
267
305
                    xsize = subsample_size(xsize, bits);
268
269
305
                    Self::adjust_color_map(&mut color_map);
270
271
305
                    TransformType::ColorIndexingTransform {
272
305
                        table_size: color_table_size,
273
305
                        table_data: color_map,
274
305
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
713
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
587
        Ok(xsize)
283
822
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_transforms
284
285
    /// Adjusts the color map since it's subtraction coded
286
604
    fn adjust_color_map(color_map: &mut [u8]) {
287
126k
        for i in 4..color_map.len() {
288
126k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
126k
        }
290
604
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
299
    fn adjust_color_map(color_map: &mut [u8]) {
287
68.0k
        for i in 4..color_map.len() {
288
68.0k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
68.0k
        }
290
299
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
305
    fn adjust_color_map(color_map: &mut [u8]) {
287
58.8k
        for i in 4..color_map.len() {
288
58.8k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
58.8k
        }
290
305
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::adjust_color_map
291
292
    /// Reads huffman codes associated with an image
293
8.84k
    fn read_huffman_codes(
294
8.84k
        &mut self,
295
8.84k
        read_meta: bool,
296
8.84k
        xsize: u16,
297
8.84k
        ysize: u16,
298
8.84k
        color_cache: Option<ColorCache>,
299
8.84k
    ) -> Result<HuffmanInfo, DecodingError> {
300
8.84k
        let mut num_huff_groups = 1u32;
301
302
8.84k
        let mut huffman_bits = 0;
303
8.84k
        let mut huffman_xsize = 1;
304
8.84k
        let mut huffman_ysize = 1;
305
8.84k
        let mut entropy_image = Vec::new();
306
307
8.84k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
920
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
916
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
916
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
916
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
916
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
758
            entropy_image = data
317
758
                .chunks_exact(4)
318
20.0M
                .map(|pixel| {
319
20.0M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
20.0M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
1.14k
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
20.0M
                    }
323
20.0M
                    meta_huff_code
324
20.0M
                })
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
19.9M
                .map(|pixel| {
319
19.9M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
19.9M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
687
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
19.9M
                    }
323
19.9M
                    meta_huff_code
324
19.9M
                })
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
72.1k
                .map(|pixel| {
319
72.1k
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
72.1k
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
454
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
71.7k
                    }
323
72.1k
                    meta_huff_code
324
72.1k
                })
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes::{closure#0}
325
758
                .collect::<Vec<u16>>();
326
7.92k
        }
327
328
8.68k
        let mut hufftree_groups = Vec::new();
329
330
40.8k
        for _i in 0..num_huff_groups {
331
40.8k
            let mut group: HuffmanCodeGroup = Default::default();
332
241k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
201k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
201k
                if j == 0 {
335
40.8k
                    if let Some(color_cache) = color_cache.as_ref() {
336
12.5k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
28.3k
                    }
338
160k
                }
339
340
201k
                let tree = self.read_huffman_code(alphabet_size)?;
341
200k
                group[j] = tree;
342
            }
343
39.8k
            hufftree_groups.push(group);
344
        }
345
346
7.66k
        let huffman_mask = if huffman_bits == 0 {
347
7.38k
            !0
348
        } else {
349
283
            (1 << huffman_bits) - 1
350
        };
351
352
7.66k
        let info = HuffmanInfo {
353
7.66k
            xsize: huffman_xsize,
354
7.66k
            _ysize: huffman_ysize,
355
7.66k
            color_cache,
356
7.66k
            image: entropy_image,
357
7.66k
            bits: huffman_bits,
358
7.66k
            mask: huffman_mask,
359
7.66k
            huffman_code_groups: hufftree_groups,
360
7.66k
        };
361
362
7.66k
        Ok(info)
363
8.84k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
7.21k
    fn read_huffman_codes(
294
7.21k
        &mut self,
295
7.21k
        read_meta: bool,
296
7.21k
        xsize: u16,
297
7.21k
        ysize: u16,
298
7.21k
        color_cache: Option<ColorCache>,
299
7.21k
    ) -> Result<HuffmanInfo, DecodingError> {
300
7.21k
        let mut num_huff_groups = 1u32;
301
302
7.21k
        let mut huffman_bits = 0;
303
7.21k
        let mut huffman_xsize = 1;
304
7.21k
        let mut huffman_ysize = 1;
305
7.21k
        let mut entropy_image = Vec::new();
306
307
7.21k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
649
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
646
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
646
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
646
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
646
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
513
            entropy_image = data
317
513
                .chunks_exact(4)
318
513
                .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
513
                .collect::<Vec<u16>>();
326
6.56k
        }
327
328
7.08k
        let mut hufftree_groups = Vec::new();
329
330
32.6k
        for _i in 0..num_huff_groups {
331
32.6k
            let mut group: HuffmanCodeGroup = Default::default();
332
193k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
161k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
161k
                if j == 0 {
335
32.6k
                    if let Some(color_cache) = color_cache.as_ref() {
336
11.7k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
20.9k
                    }
338
128k
                }
339
340
161k
                let tree = self.read_huffman_code(alphabet_size)?;
341
161k
                group[j] = tree;
342
            }
343
32.0k
            hufftree_groups.push(group);
344
        }
345
346
6.41k
        let huffman_mask = if huffman_bits == 0 {
347
6.27k
            !0
348
        } else {
349
141
            (1 << huffman_bits) - 1
350
        };
351
352
6.41k
        let info = HuffmanInfo {
353
6.41k
            xsize: huffman_xsize,
354
6.41k
            _ysize: huffman_ysize,
355
6.41k
            color_cache,
356
6.41k
            image: entropy_image,
357
6.41k
            bits: huffman_bits,
358
6.41k
            mask: huffman_mask,
359
6.41k
            huffman_code_groups: hufftree_groups,
360
6.41k
        };
361
362
6.41k
        Ok(info)
363
7.21k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
1.62k
    fn read_huffman_codes(
294
1.62k
        &mut self,
295
1.62k
        read_meta: bool,
296
1.62k
        xsize: u16,
297
1.62k
        ysize: u16,
298
1.62k
        color_cache: Option<ColorCache>,
299
1.62k
    ) -> Result<HuffmanInfo, DecodingError> {
300
1.62k
        let mut num_huff_groups = 1u32;
301
302
1.62k
        let mut huffman_bits = 0;
303
1.62k
        let mut huffman_xsize = 1;
304
1.62k
        let mut huffman_ysize = 1;
305
1.62k
        let mut entropy_image = Vec::new();
306
307
1.62k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
271
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
270
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
270
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
270
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
270
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
245
            entropy_image = data
317
245
                .chunks_exact(4)
318
245
                .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
245
                .collect::<Vec<u16>>();
326
1.35k
        }
327
328
1.60k
        let mut hufftree_groups = Vec::new();
329
330
8.18k
        for _i in 0..num_huff_groups {
331
8.18k
            let mut group: HuffmanCodeGroup = Default::default();
332
47.7k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
39.8k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
39.8k
                if j == 0 {
335
8.18k
                    if let Some(color_cache) = color_cache.as_ref() {
336
778
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
7.40k
                    }
338
31.7k
                }
339
340
39.8k
                let tree = self.read_huffman_code(alphabet_size)?;
341
39.5k
                group[j] = tree;
342
            }
343
7.82k
            hufftree_groups.push(group);
344
        }
345
346
1.24k
        let huffman_mask = if huffman_bits == 0 {
347
1.10k
            !0
348
        } else {
349
142
            (1 << huffman_bits) - 1
350
        };
351
352
1.24k
        let info = HuffmanInfo {
353
1.24k
            xsize: huffman_xsize,
354
1.24k
            _ysize: huffman_ysize,
355
1.24k
            color_cache,
356
1.24k
            image: entropy_image,
357
1.24k
            bits: huffman_bits,
358
1.24k
            mask: huffman_mask,
359
1.24k
            huffman_code_groups: hufftree_groups,
360
1.24k
        };
361
362
1.24k
        Ok(info)
363
1.62k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes
364
365
    /// Decodes and returns a single huffman tree
366
201k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
201k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
201k
        if simple {
370
185k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
185k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
185k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
185k
            if zero_symbol >= alphabet_size {
376
16
                return Err(DecodingError::BitStreamError);
377
185k
            }
378
379
185k
            if num_symbols == 1 {
380
173k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
11.9k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
11.9k
                if one_symbol >= alphabet_size {
384
9
                    return Err(DecodingError::BitStreamError);
385
11.9k
                }
386
11.9k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
16.1k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
16.1k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
208k
            for i in 0..num_code_lengths {
393
208k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
208k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
15.5k
            let new_code_lengths =
398
15.9k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
15.5k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
201k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
161k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
161k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
161k
        if simple {
370
147k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
147k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
147k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
147k
            if zero_symbol >= alphabet_size {
376
10
                return Err(DecodingError::BitStreamError);
377
147k
            }
378
379
147k
            if num_symbols == 1 {
380
137k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
9.71k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
9.68k
                if one_symbol >= alphabet_size {
384
5
                    return Err(DecodingError::BitStreamError);
385
9.68k
                }
386
9.68k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
14.0k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
14.0k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
190k
            for i in 0..num_code_lengths {
393
190k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
190k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
13.6k
            let new_code_lengths =
398
13.9k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
13.6k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
161k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
39.8k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
39.8k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
39.8k
        if simple {
370
37.8k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
37.8k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
37.7k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
37.7k
            if zero_symbol >= alphabet_size {
376
6
                return Err(DecodingError::BitStreamError);
377
37.7k
            }
378
379
37.7k
            if num_symbols == 1 {
380
35.5k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
2.27k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
2.26k
                if one_symbol >= alphabet_size {
384
4
                    return Err(DecodingError::BitStreamError);
385
2.26k
                }
386
2.26k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
2.08k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
2.08k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
18.4k
            for i in 0..num_code_lengths {
393
18.4k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
18.4k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
1.81k
            let new_code_lengths =
398
2.05k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
1.81k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
39.8k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code
403
404
    /// Reads huffman code lengths
405
15.9k
    fn read_huffman_code_lengths(
406
15.9k
        &mut self,
407
15.9k
        code_length_code_lengths: Vec<u16>,
408
15.9k
        num_symbols: u16,
409
15.9k
    ) -> Result<Vec<u16>, DecodingError> {
410
15.9k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
15.6k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
10.2k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
10.2k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
10.1k
            if max_minus_two > num_symbols - 2 {
416
5
                return Err(DecodingError::BitStreamError);
417
10.1k
            }
418
10.1k
            2 + max_minus_two
419
        } else {
420
5.45k
            num_symbols
421
        };
422
423
15.6k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
15.6k
        let mut prev_code_len = 8; //default code length
425
426
15.6k
        let mut symbol = 0;
427
2.00M
        while symbol < num_symbols {
428
1.99M
            if max_symbol == 0 {
429
5.01k
                break;
430
1.98M
            }
431
1.98M
            max_symbol -= 1;
432
433
1.98M
            self.bit_reader.fill()?;
434
1.98M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.98M
            if code_len < 16 {
437
1.93M
                code_lengths[usize::from(symbol)] = code_len;
438
1.93M
                symbol += 1;
439
1.93M
                if code_len != 0 {
440
928k
                    prev_code_len = code_len;
441
1.01M
                }
442
            } else {
443
50.3k
                let use_prev = code_len == 16;
444
50.3k
                let slot = code_len - 16;
445
50.3k
                let extra_bits = match slot {
446
26.9k
                    0 => 2,
447
7.44k
                    1 => 3,
448
15.8k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
50.3k
                let repeat_offset = match slot {
452
34.4k
                    0 | 1 => 3,
453
15.8k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
50.3k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
50.2k
                if symbol + repeat > num_symbols {
460
62
                    return Err(DecodingError::BitStreamError);
461
50.2k
                }
462
463
50.2k
                let length = if use_prev { prev_code_len } else { 0 };
464
1.30M
                while repeat > 0 {
465
1.25M
                    repeat -= 1;
466
1.25M
                    code_lengths[usize::from(symbol)] = length;
467
1.25M
                    symbol += 1;
468
1.25M
                }
469
            }
470
        }
471
472
15.5k
        Ok(code_lengths)
473
15.9k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
13.9k
    fn read_huffman_code_lengths(
406
13.9k
        &mut self,
407
13.9k
        code_length_code_lengths: Vec<u16>,
408
13.9k
        num_symbols: u16,
409
13.9k
    ) -> Result<Vec<u16>, DecodingError> {
410
13.9k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
13.8k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
9.40k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
9.40k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
9.39k
            if max_minus_two > num_symbols - 2 {
416
4
                return Err(DecodingError::BitStreamError);
417
9.39k
            }
418
9.39k
            2 + max_minus_two
419
        } else {
420
4.40k
            num_symbols
421
        };
422
423
13.7k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
13.7k
        let mut prev_code_len = 8; //default code length
425
426
13.7k
        let mut symbol = 0;
427
1.96M
        while symbol < num_symbols {
428
1.95M
            if max_symbol == 0 {
429
4.21k
                break;
430
1.95M
            }
431
1.95M
            max_symbol -= 1;
432
433
1.95M
            self.bit_reader.fill()?;
434
1.95M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.95M
            if code_len < 16 {
437
1.91M
                code_lengths[usize::from(symbol)] = code_len;
438
1.91M
                symbol += 1;
439
1.91M
                if code_len != 0 {
440
903k
                    prev_code_len = code_len;
441
1.00M
                }
442
            } else {
443
41.6k
                let use_prev = code_len == 16;
444
41.6k
                let slot = code_len - 16;
445
41.6k
                let extra_bits = match slot {
446
23.3k
                    0 => 2,
447
5.87k
                    1 => 3,
448
12.4k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
41.6k
                let repeat_offset = match slot {
452
29.1k
                    0 | 1 => 3,
453
12.4k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
41.6k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
41.5k
                if symbol + repeat > num_symbols {
460
30
                    return Err(DecodingError::BitStreamError);
461
41.5k
                }
462
463
41.5k
                let length = if use_prev { prev_code_len } else { 0 };
464
1.00M
                while repeat > 0 {
465
961k
                    repeat -= 1;
466
961k
                    code_lengths[usize::from(symbol)] = length;
467
961k
                    symbol += 1;
468
961k
                }
469
            }
470
        }
471
472
13.6k
        Ok(code_lengths)
473
13.9k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
2.05k
    fn read_huffman_code_lengths(
406
2.05k
        &mut self,
407
2.05k
        code_length_code_lengths: Vec<u16>,
408
2.05k
        num_symbols: u16,
409
2.05k
    ) -> Result<Vec<u16>, DecodingError> {
410
2.05k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
1.86k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
802
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
802
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
800
            if max_minus_two > num_symbols - 2 {
416
1
                return Err(DecodingError::BitStreamError);
417
799
            }
418
799
            2 + max_minus_two
419
        } else {
420
1.05k
            num_symbols
421
        };
422
423
1.85k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
1.85k
        let mut prev_code_len = 8; //default code length
425
426
1.85k
        let mut symbol = 0;
427
38.0k
        while symbol < num_symbols {
428
37.0k
            if max_symbol == 0 {
429
797
                break;
430
36.2k
            }
431
36.2k
            max_symbol -= 1;
432
433
36.2k
            self.bit_reader.fill()?;
434
36.2k
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
36.2k
            if code_len < 16 {
437
27.5k
                code_lengths[usize::from(symbol)] = code_len;
438
27.5k
                symbol += 1;
439
27.5k
                if code_len != 0 {
440
24.7k
                    prev_code_len = code_len;
441
24.7k
                }
442
            } else {
443
8.70k
                let use_prev = code_len == 16;
444
8.70k
                let slot = code_len - 16;
445
8.70k
                let extra_bits = match slot {
446
3.67k
                    0 => 2,
447
1.57k
                    1 => 3,
448
3.46k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
8.70k
                let repeat_offset = match slot {
452
5.24k
                    0 | 1 => 3,
453
3.46k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
8.70k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
8.70k
                if symbol + repeat > num_symbols {
460
32
                    return Err(DecodingError::BitStreamError);
461
8.67k
                }
462
463
8.67k
                let length = if use_prev { prev_code_len } else { 0 };
464
304k
                while repeat > 0 {
465
295k
                    repeat -= 1;
466
295k
                    code_lengths[usize::from(symbol)] = length;
467
295k
                    symbol += 1;
468
295k
                }
469
            }
470
        }
471
472
1.81k
        Ok(code_lengths)
473
2.05k
    }
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.66k
    fn decode_image_data(
477
7.66k
        &mut self,
478
7.66k
        width: u16,
479
7.66k
        height: u16,
480
7.66k
        mut huffman_info: HuffmanInfo,
481
7.66k
        data: &mut [u8],
482
7.66k
    ) -> Result<(), DecodingError> {
483
7.66k
        let num_values = usize::from(width) * usize::from(height);
484
485
7.66k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
7.66k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
7.66k
        let mut index = 0;
488
489
7.66k
        let mut next_block_start = 0;
490
57.1M
        while index < num_values {
491
57.1M
            self.bit_reader.fill()?;
492
493
57.1M
            if index >= next_block_start {
494
19.6M
                let x = index % usize::from(width);
495
19.6M
                let y = index / usize::from(width);
496
19.6M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
19.6M
                    + y * usize::from(width)
498
19.6M
                    + 1;
499
500
19.6M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
19.6M
                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
76.0M
                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
75.1M
                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
815k
                if tree[..4].iter().all(|t| t.is_single_node()) {
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data::{closure#0}
508
18.7M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
18.7M
                    if code < 256 {
510
18.7M
                        let n = if huffman_info.bits == 0 {
511
3.06k
                            num_values
512
                        } else {
513
18.7M
                            next_block_start - index
514
                        };
515
516
18.7M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
18.7M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
18.7M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
18.7M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
1.08G
                        for i in 0..n {
522
1.08G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
1.08G
                        }
524
525
18.7M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
5.21M
                            color_cache.insert(value);
527
13.5M
                        }
528
529
18.7M
                        index += n;
530
18.7M
                        continue;
531
1
                    }
532
930k
                }
533
37.4M
            }
534
535
38.4M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
38.4M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
22.5M
                let green = code as u8;
541
22.5M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
22.5M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
22.5M
                if self.bit_reader.nbits < 15 {
544
6.92k
                    self.bit_reader.fill()?;
545
22.5M
                }
546
22.5M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
22.5M
                data[index * 4] = red;
549
22.5M
                data[index * 4 + 1] = green;
550
22.5M
                data[index * 4 + 2] = blue;
551
22.5M
                data[index * 4 + 3] = alpha;
552
553
22.5M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
6.51M
                    color_cache.insert([red, green, blue, alpha]);
555
16.0M
                }
556
22.5M
                index += 1;
557
15.8M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
9.77M
                let length_symbol = code - 256;
560
9.77M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
9.77M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
9.77M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
9.77M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
9.77M
                if index < dist || num_values - index < length {
567
138
                    return Err(DecodingError::BitStreamError);
568
9.77M
                }
569
570
9.77M
                if dist == 1 {
571
5.45M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
3.07G
                    for i in 0..length {
573
3.07G
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
3.07G
                    }
575
                } else {
576
4.31M
                    if index + length + 3 <= num_values {
577
4.31M
                        let start = (index - dist) * 4;
578
4.31M
                        data.copy_within(start..start + 16, index * 4);
579
580
4.31M
                        if length > 4 || dist < 4 {
581
316M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
316M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
316M
                            }
584
16.7k
                        }
585
                    } else {
586
66.2k
                        for i in 0..length * 4 {
587
66.2k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
66.2k
                        }
589
                    }
590
591
4.31M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
1.27G
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
1.27G
                            color_cache.insert(pixel.try_into().unwrap());
594
1.27G
                        }
595
42.9k
                    }
596
                }
597
9.77M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
6.05M
                let color_cache = huffman_info
601
6.05M
                    .color_cache
602
6.05M
                    .as_mut()
603
6.05M
                    .ok_or(DecodingError::BitStreamError)?;
604
6.05M
                let color = color_cache.lookup((code - 280).into());
605
6.05M
                data[index * 4..][..4].copy_from_slice(&color);
606
6.05M
                index += 1;
607
608
6.05M
                if index < next_block_start {
609
6.05M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
6.05M
                        if code >= 280 {
611
3.31M
                            self.bit_reader.consume(bits)?;
612
3.31M
                            data[index * 4..][..4]
613
3.31M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
3.31M
                            index += 1;
615
2.74M
                        }
616
490
                    }
617
4.19k
                }
618
            }
619
        }
620
621
6.94k
        Ok(())
622
7.66k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
6.41k
    fn decode_image_data(
477
6.41k
        &mut self,
478
6.41k
        width: u16,
479
6.41k
        height: u16,
480
6.41k
        mut huffman_info: HuffmanInfo,
481
6.41k
        data: &mut [u8],
482
6.41k
    ) -> Result<(), DecodingError> {
483
6.41k
        let num_values = usize::from(width) * usize::from(height);
484
485
6.41k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
6.41k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
6.41k
        let mut index = 0;
488
489
6.41k
        let mut next_block_start = 0;
490
44.4M
        while index < num_values {
491
44.4M
            self.bit_reader.fill()?;
492
493
44.4M
            if index >= next_block_start {
494
19.1M
                let x = index % usize::from(width);
495
19.1M
                let y = index / usize::from(width);
496
19.1M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
19.1M
                    + y * usize::from(width)
498
19.1M
                    + 1;
499
500
19.1M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
19.1M
                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
19.1M
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
18.6M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
18.6M
                    if code < 256 {
510
18.6M
                        let n = if huffman_info.bits == 0 {
511
2.88k
                            num_values
512
                        } else {
513
18.6M
                            next_block_start - index
514
                        };
515
516
18.6M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
18.6M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
18.6M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
18.6M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
1.08G
                        for i in 0..n {
522
1.08G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
1.08G
                        }
524
525
18.6M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
5.21M
                            color_cache.insert(value);
527
13.4M
                        }
528
529
18.6M
                        index += n;
530
18.6M
                        continue;
531
1
                    }
532
476k
                }
533
25.3M
            }
534
535
25.8M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
25.8M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
18.7M
                let green = code as u8;
541
18.7M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
18.7M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
18.7M
                if self.bit_reader.nbits < 15 {
544
6.49k
                    self.bit_reader.fill()?;
545
18.7M
                }
546
18.7M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
18.7M
                data[index * 4] = red;
549
18.7M
                data[index * 4 + 1] = green;
550
18.7M
                data[index * 4 + 2] = blue;
551
18.7M
                data[index * 4 + 3] = alpha;
552
553
18.7M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
2.93M
                    color_cache.insert([red, green, blue, alpha]);
555
15.8M
                }
556
18.7M
                index += 1;
557
7.05M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
3.58M
                let length_symbol = code - 256;
560
3.58M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
3.58M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
3.58M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
3.58M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
3.58M
                if index < dist || num_values - index < length {
567
50
                    return Err(DecodingError::BitStreamError);
568
3.58M
                }
569
570
3.58M
                if dist == 1 {
571
2.00M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
2.56G
                    for i in 0..length {
573
2.56G
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
2.56G
                    }
575
                } else {
576
1.58M
                    if index + length + 3 <= num_values {
577
1.58M
                        let start = (index - dist) * 4;
578
1.58M
                        data.copy_within(start..start + 16, index * 4);
579
580
1.58M
                        if length > 4 || dist < 4 {
581
230M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
230M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
230M
                            }
584
10.4k
                        }
585
                    } else {
586
20.7k
                        for i in 0..length * 4 {
587
20.7k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
20.7k
                        }
589
                    }
590
591
1.58M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
925M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
925M
                            color_cache.insert(pixel.try_into().unwrap());
594
925M
                        }
595
15.8k
                    }
596
                }
597
3.58M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
3.46M
                let color_cache = huffman_info
601
3.46M
                    .color_cache
602
3.46M
                    .as_mut()
603
3.46M
                    .ok_or(DecodingError::BitStreamError)?;
604
3.46M
                let color = color_cache.lookup((code - 280).into());
605
3.46M
                data[index * 4..][..4].copy_from_slice(&color);
606
3.46M
                index += 1;
607
608
3.46M
                if index < next_block_start {
609
3.46M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
3.46M
                        if code >= 280 {
611
2.60M
                            self.bit_reader.consume(bits)?;
612
2.60M
                            data[index * 4..][..4]
613
2.60M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
2.60M
                            index += 1;
615
862k
                        }
616
468
                    }
617
2.80k
                }
618
            }
619
        }
620
621
5.99k
        Ok(())
622
6.41k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
1.24k
    fn decode_image_data(
477
1.24k
        &mut self,
478
1.24k
        width: u16,
479
1.24k
        height: u16,
480
1.24k
        mut huffman_info: HuffmanInfo,
481
1.24k
        data: &mut [u8],
482
1.24k
    ) -> Result<(), DecodingError> {
483
1.24k
        let num_values = usize::from(width) * usize::from(height);
484
485
1.24k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
1.24k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
1.24k
        let mut index = 0;
488
489
1.24k
        let mut next_block_start = 0;
490
12.6M
        while index < num_values {
491
12.6M
            self.bit_reader.fill()?;
492
493
12.6M
            if index >= next_block_start {
494
536k
                let x = index % usize::from(width);
495
536k
                let y = index / usize::from(width);
496
536k
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
536k
                    + y * usize::from(width)
498
536k
                    + 1;
499
500
536k
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
536k
                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
536k
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
82.4k
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
82.4k
                    if code < 256 {
510
82.4k
                        let n = if huffman_info.bits == 0 {
511
180
                            num_values
512
                        } else {
513
82.2k
                            next_block_start - index
514
                        };
515
516
82.4k
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
82.4k
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
82.4k
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
82.4k
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
1.08M
                        for i in 0..n {
522
1.08M
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
1.08M
                        }
524
525
82.4k
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
54
                            color_cache.insert(value);
527
82.4k
                        }
528
529
82.4k
                        index += n;
530
82.4k
                        continue;
531
0
                    }
532
454k
                }
533
12.1M
            }
534
535
12.5M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
12.5M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
3.81M
                let green = code as u8;
541
3.81M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
3.81M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
3.81M
                if self.bit_reader.nbits < 15 {
544
437
                    self.bit_reader.fill()?;
545
3.80M
                }
546
3.81M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
3.81M
                data[index * 4] = red;
549
3.81M
                data[index * 4 + 1] = green;
550
3.81M
                data[index * 4 + 2] = blue;
551
3.81M
                data[index * 4 + 3] = alpha;
552
553
3.81M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
3.58M
                    color_cache.insert([red, green, blue, alpha]);
555
3.58M
                }
556
3.81M
                index += 1;
557
8.77M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
6.18M
                let length_symbol = code - 256;
560
6.18M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
6.18M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
6.18M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
6.18M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
6.18M
                if index < dist || num_values - index < length {
567
88
                    return Err(DecodingError::BitStreamError);
568
6.18M
                }
569
570
6.18M
                if dist == 1 {
571
3.45M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
506M
                    for i in 0..length {
573
506M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
506M
                    }
575
                } else {
576
2.72M
                    if index + length + 3 <= num_values {
577
2.72M
                        let start = (index - dist) * 4;
578
2.72M
                        data.copy_within(start..start + 16, index * 4);
579
580
2.72M
                        if length > 4 || dist < 4 {
581
85.5M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
85.5M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
85.5M
                            }
584
6.31k
                        }
585
                    } else {
586
45.4k
                        for i in 0..length * 4 {
587
45.4k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
45.4k
                        }
589
                    }
590
591
2.72M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
347M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
347M
                            color_cache.insert(pixel.try_into().unwrap());
594
347M
                        }
595
27.0k
                    }
596
                }
597
6.18M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
2.58M
                let color_cache = huffman_info
601
2.58M
                    .color_cache
602
2.58M
                    .as_mut()
603
2.58M
                    .ok_or(DecodingError::BitStreamError)?;
604
2.58M
                let color = color_cache.lookup((code - 280).into());
605
2.58M
                data[index * 4..][..4].copy_from_slice(&color);
606
2.58M
                index += 1;
607
608
2.58M
                if index < next_block_start {
609
2.58M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
2.58M
                        if code >= 280 {
611
707k
                            self.bit_reader.consume(bits)?;
612
707k
                            data[index * 4..][..4]
613
707k
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
707k
                            index += 1;
615
1.88M
                        }
616
22
                    }
617
1.38k
                }
618
            }
619
        }
620
621
957
        Ok(())
622
1.24k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data
623
624
    /// Reads color cache data from the bitstream
625
8.88k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
8.88k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
1.34k
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
1.33k
            if !(1..=11).contains(&code_bits) {
630
26
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
1.30k
            }
632
633
1.30k
            Ok(Some(code_bits))
634
        } else {
635
7.54k
            Ok(None)
636
        }
637
8.88k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
7.23k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
7.23k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
913
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
904
            if !(1..=11).contains(&code_bits) {
630
10
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
894
            }
632
633
894
            Ok(Some(code_bits))
634
        } else {
635
6.32k
            Ok(None)
636
        }
637
7.23k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
1.64k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
1.64k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
432
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
428
            if !(1..=11).contains(&code_bits) {
630
16
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
412
            }
632
633
412
            Ok(Some(code_bits))
634
        } else {
635
1.21k
            Ok(None)
636
        }
637
1.64k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_color_cache
638
639
    /// Gets the copy distance from the prefix code and bitstream
640
19.5M
    fn get_copy_distance(
641
19.5M
        bit_reader: &mut BitReader<R>,
642
19.5M
        prefix_code: u16,
643
19.5M
    ) -> Result<usize, DecodingError> {
644
19.5M
        if prefix_code < 4 {
645
5.71M
            return Ok(usize::from(prefix_code + 1));
646
13.8M
        }
647
13.8M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
13.8M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
13.8M
        let bits = bit_reader.peek(extra_bits) as usize;
651
13.8M
        bit_reader.consume(extra_bits)?;
652
653
13.8M
        Ok(offset + bits + 1)
654
19.5M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
7.16M
    fn get_copy_distance(
641
7.16M
        bit_reader: &mut BitReader<R>,
642
7.16M
        prefix_code: u16,
643
7.16M
    ) -> Result<usize, DecodingError> {
644
7.16M
        if prefix_code < 4 {
645
2.12M
            return Ok(usize::from(prefix_code + 1));
646
5.04M
        }
647
5.04M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
5.04M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
5.04M
        let bits = bit_reader.peek(extra_bits) as usize;
651
5.04M
        bit_reader.consume(extra_bits)?;
652
653
5.03M
        Ok(offset + bits + 1)
654
7.16M
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
12.3M
    fn get_copy_distance(
641
12.3M
        bit_reader: &mut BitReader<R>,
642
12.3M
        prefix_code: u16,
643
12.3M
    ) -> Result<usize, DecodingError> {
644
12.3M
        if prefix_code < 4 {
645
3.58M
            return Ok(usize::from(prefix_code + 1));
646
8.79M
        }
647
8.79M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
8.79M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
8.79M
        let bits = bit_reader.peek(extra_bits) as usize;
651
8.79M
        bit_reader.consume(extra_bits)?;
652
653
8.79M
        Ok(offset + bits + 1)
654
12.3M
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::get_copy_distance
655
656
    /// Gets distance to pixel
657
9.77M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
9.77M
        if plane_code > 120 {
659
4.17M
            plane_code - 120
660
        } else {
661
5.59M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
5.59M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
5.59M
            if dist < 1 {
665
0
                return 1;
666
5.59M
            }
667
5.59M
            dist.try_into().unwrap()
668
        }
669
9.77M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
3.58M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
3.58M
        if plane_code > 120 {
659
1.56M
            plane_code - 120
660
        } else {
661
2.01M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
2.01M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
2.01M
            if dist < 1 {
665
0
                return 1;
666
2.01M
            }
667
2.01M
            dist.try_into().unwrap()
668
        }
669
3.58M
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
6.18M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
6.18M
        if plane_code > 120 {
659
2.61M
            plane_code - 120
660
        } else {
661
3.57M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
3.57M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
3.57M
            if dist < 1 {
665
0
                return 1;
666
3.57M
            }
667
3.57M
            dist.try_into().unwrap()
668
        }
669
6.18M
    }
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
19.6M
    fn get_huff_index(&self, x: u16, y: u16) -> usize {
685
19.6M
        if self.bits == 0 {
686
907k
            return 0;
687
18.7M
        }
688
18.7M
        let position =
689
18.7M
            usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits);
690
18.7M
        let meta_huff_code: usize = usize::from(self.image[position]);
691
18.7M
        meta_huff_code
692
19.6M
    }
693
}
694
695
#[derive(Debug, Clone)]
696
struct ColorCache {
697
    color_cache_bits: u8,
698
    color_cache: Vec<[u8; 4]>,
699
}
700
701
impl ColorCache {
702
    #[inline(always)]
703
1.28G
    fn insert(&mut self, color: [u8; 4]) {
704
1.28G
        let [r, g, b, a] = color;
705
1.28G
        let color_u32 =
706
1.28G
            (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24);
707
1.28G
        let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits);
708
1.28G
        self.color_cache[index as usize] = color;
709
1.28G
    }
710
711
    #[inline(always)]
712
9.37M
    fn lookup(&self, index: usize) -> [u8; 4] {
713
9.37M
        self.color_cache[index]
714
9.37M
    }
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
4.58k
    const fn new(reader: R) -> Self {
726
4.58k
        Self {
727
4.58k
            reader,
728
4.58k
            buffer: 0,
729
4.58k
            nbits: 0,
730
4.58k
        }
731
4.58k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
3.76k
    const fn new(reader: R) -> Self {
726
3.76k
        Self {
727
3.76k
            reader,
728
3.76k
            buffer: 0,
729
3.76k
            nbits: 0,
730
3.76k
        }
731
3.76k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
822
    const fn new(reader: R) -> Self {
726
822
        Self {
727
822
            reader,
728
822
            buffer: 0,
729
822
            nbits: 0,
730
822
        }
731
822
    }
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
59.1M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
59.1M
        debug_assert!(self.nbits < 64);
739
740
59.1M
        let mut buf = self.reader.fill_buf()?;
741
59.1M
        if buf.len() >= 8 {
742
42.8M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
42.8M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
42.8M
            self.buffer |= lookahead << self.nbits;
745
42.8M
            self.nbits |= 56;
746
42.8M
        } else {
747
16.3M
            while !buf.is_empty() && self.nbits < 56 {
748
22.3k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
22.3k
                self.nbits += 8;
750
22.3k
                self.reader.consume(1);
751
22.3k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
59.1M
        Ok(())
756
59.1M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
46.4M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
46.4M
        debug_assert!(self.nbits < 64);
739
740
46.4M
        let mut buf = self.reader.fill_buf()?;
741
46.4M
        if buf.len() >= 8 {
742
30.1M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
30.1M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
30.1M
            self.buffer |= lookahead << self.nbits;
745
30.1M
            self.nbits |= 56;
746
30.1M
        } else {
747
16.3M
            while !buf.is_empty() && self.nbits < 56 {
748
18.8k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
18.8k
                self.nbits += 8;
750
18.8k
                self.reader.consume(1);
751
18.8k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
46.4M
        Ok(())
756
46.4M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
12.7M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
12.7M
        debug_assert!(self.nbits < 64);
739
740
12.7M
        let mut buf = self.reader.fill_buf()?;
741
12.7M
        if buf.len() >= 8 {
742
12.6M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
12.6M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
12.6M
            self.buffer |= lookahead << self.nbits;
745
12.6M
            self.nbits |= 56;
746
12.6M
        } else {
747
28.4k
            while !buf.is_empty() && self.nbits < 56 {
748
3.53k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
3.53k
                self.nbits += 8;
750
3.53k
                self.reader.consume(1);
751
3.53k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
12.7M
        Ok(())
756
12.7M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::fill
757
758
    /// Peeks at the next `num` bits in the buffer.
759
14.9M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
14.9M
        self.buffer & ((1 << num) - 1)
761
14.9M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
5.98M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
5.98M
        self.buffer & ((1 << num) - 1)
761
5.98M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
8.98M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
8.98M
        self.buffer & ((1 << num) - 1)
761
8.98M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek
762
763
    /// Peeks at the full buffer.
764
108M
    pub(crate) const fn peek_full(&self) -> u64 {
765
108M
        self.buffer
766
108M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
84.0M
    pub(crate) const fn peek_full(&self) -> u64 {
765
84.0M
        self.buffer
766
84.0M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
24.1M
    pub(crate) const fn peek_full(&self) -> u64 {
765
24.1M
        self.buffer
766
24.1M
    }
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
122M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
122M
        if self.nbits < num {
771
1.13k
            return Err(DecodingError::BitStreamError);
772
122M
        }
773
774
122M
        self.buffer >>= num;
775
122M
        self.nbits -= num;
776
122M
        Ok(())
777
122M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
91.2M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
91.2M
        if self.nbits < num {
771
838
            return Err(DecodingError::BitStreamError);
772
91.2M
        }
773
774
91.2M
        self.buffer >>= num;
775
91.2M
        self.nbits -= num;
776
91.2M
        Ok(())
777
91.2M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
31.2M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
31.2M
        if self.nbits < num {
771
298
            return Err(DecodingError::BitStreamError);
772
31.2M
        }
773
774
31.2M
        self.buffer >>= num;
775
31.2M
        self.nbits -= num;
776
31.2M
        Ok(())
777
31.2M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::consume
778
779
    /// Convenience function to read a number of bits and convert them to a type.
780
1.13M
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
1.13M
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
1.13M
        debug_assert!(num <= 32);
783
784
1.13M
        if self.nbits < num {
785
30.9k
            self.fill()?;
786
1.10M
        }
787
1.13M
        let value = self.peek(num) as u32;
788
1.13M
        self.consume(num)?;
789
790
1.13M
        value.try_into().map_err(|_| {
791
0
            debug_assert!(false, "Value too large to fit in type");
792
0
            DecodingError::BitStreamError
793
0
        })
Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>::{closure#0}
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::read_bits::<_>::{closure#0}
794
1.13M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
520k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
520k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
520k
        debug_assert!(num <= 32);
783
784
520k
        if self.nbits < num {
785
11.8k
            self.fill()?;
786
508k
        }
787
520k
        let value = self.peek(num) as u32;
788
520k
        self.consume(num)?;
789
790
520k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
520k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
14.0k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
14.0k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
14.0k
        debug_assert!(num <= 32);
783
784
14.0k
        if self.nbits < num {
785
211
            self.fill()?;
786
13.8k
        }
787
14.0k
        let value = self.peek(num) as u32;
788
14.0k
        self.consume(num)?;
789
790
14.0k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
14.0k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
406k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
406k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
406k
        debug_assert!(num <= 32);
783
784
406k
        if self.nbits < num {
785
14.9k
            self.fill()?;
786
391k
        }
787
406k
        let value = self.peek(num) as u32;
788
406k
        self.consume(num)?;
789
790
406k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
406k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
124k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
124k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
124k
        debug_assert!(num <= 32);
783
784
124k
        if self.nbits < num {
785
2.91k
            self.fill()?;
786
121k
        }
787
124k
        let value = self.peek(num) as u32;
788
124k
        self.consume(num)?;
789
790
123k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
124k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
2.08k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
2.08k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
2.08k
        debug_assert!(num <= 32);
783
784
2.08k
        if self.nbits < num {
785
4
            self.fill()?;
786
2.08k
        }
787
2.08k
        let value = self.peek(num) as u32;
788
2.08k
        self.consume(num)?;
789
790
2.08k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
2.08k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
68.4k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
68.4k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
68.4k
        debug_assert!(num <= 32);
783
784
68.4k
        if self.nbits < num {
785
996
            self.fill()?;
786
67.4k
        }
787
68.4k
        let value = self.peek(num) as u32;
788
68.4k
        self.consume(num)?;
789
790
68.3k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
68.4k
    }
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
}