Coverage Report

Created: 2026-05-16 07:04

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.68k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
8.68k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
8.68k
        .try_into()
57
8.68k
        .unwrap()
58
8.68k
}
image_webp::lossless::subsample_size
Line
Count
Source
54
2.51k
pub(crate) fn subsample_size(size: u16, bits: u8) -> u16 {
55
2.51k
    ((u32::from(size) + (1u32 << bits) - 1) >> bits)
56
2.51k
        .try_into()
57
2.51k
        .unwrap()
58
2.51k
}
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.99k
    pub(crate) const fn new(r: R) -> Self {
75
4.99k
        Self {
76
4.99k
            bit_reader: BitReader::new(r),
77
4.99k
            transforms: [None, None, None, None],
78
4.99k
            transform_order: Vec::new(),
79
4.99k
            width: 0,
80
4.99k
            height: 0,
81
4.99k
        }
82
4.99k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
3.82k
    pub(crate) const fn new(r: R) -> Self {
75
3.82k
        Self {
76
3.82k
            bit_reader: BitReader::new(r),
77
3.82k
            transforms: [None, None, None, None],
78
3.82k
            transform_order: Vec::new(),
79
3.82k
            width: 0,
80
3.82k
            height: 0,
81
3.82k
        }
82
3.82k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
74
1.16k
    pub(crate) const fn new(r: R) -> Self {
75
1.16k
        Self {
76
1.16k
            bit_reader: BitReader::new(r),
77
1.16k
            transforms: [None, None, None, None],
78
1.16k
            transform_order: Vec::new(),
79
1.16k
            width: 0,
80
1.16k
            height: 0,
81
1.16k
        }
82
1.16k
    }
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.99k
    pub(crate) fn decode_frame(
90
4.99k
        &mut self,
91
4.99k
        width: u32,
92
4.99k
        height: u32,
93
4.99k
        implicit_dimensions: bool,
94
4.99k
        buf: &mut [u8],
95
4.99k
    ) -> Result<(), DecodingError> {
96
4.99k
        if implicit_dimensions {
97
1.16k
            self.width = width as u16;
98
1.16k
            self.height = height as u16;
99
1.16k
        } else {
100
3.82k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.82k
            if signature != 0x2f {
102
9
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.81k
            }
104
105
3.81k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.80k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.80k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
56
                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.91k
        let transformed_width = self.read_transforms()?;
119
4.39k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
4.39k
        self.decode_image_stream(
121
4.39k
            transformed_width,
122
4.39k
            self.height,
123
            true,
124
4.39k
            &mut buf[..transformed_size],
125
1.51k
        )?;
126
127
2.88k
        let mut image_size = transformed_size;
128
2.88k
        let mut width = transformed_width;
129
4.93k
        for &trans_index in self.transform_order.iter().rev() {
130
4.93k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.93k
            match transform {
132
                TransformType::PredictorTransform {
133
2.44k
                    size_bits,
134
2.44k
                    predictor_data,
135
2.44k
                } => apply_predictor_transform(
136
2.44k
                    &mut buf[..image_size],
137
2.44k
                    width,
138
2.44k
                    self.height,
139
2.44k
                    *size_bits,
140
2.44k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
73
                    size_bits,
144
73
                    transform_data,
145
73
                } => {
146
73
                    apply_color_transform(
147
73
                        &mut buf[..image_size],
148
73
                        width,
149
73
                        *size_bits,
150
73
                        transform_data,
151
73
                    );
152
73
                }
153
2.21k
                TransformType::SubtractGreen => {
154
2.21k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
2.21k
                }
156
                TransformType::ColorIndexingTransform {
157
210
                    table_size,
158
210
                    table_data,
159
210
                } => {
160
210
                    width = self.width;
161
210
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
210
                    apply_color_indexing_transform(
163
210
                        buf,
164
210
                        width,
165
210
                        self.height,
166
210
                        *table_size,
167
210
                        table_data,
168
210
                    );
169
210
                }
170
            }
171
        }
172
173
2.88k
        Ok(())
174
4.99k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
3.82k
    pub(crate) fn decode_frame(
90
3.82k
        &mut self,
91
3.82k
        width: u32,
92
3.82k
        height: u32,
93
3.82k
        implicit_dimensions: bool,
94
3.82k
        buf: &mut [u8],
95
3.82k
    ) -> Result<(), DecodingError> {
96
3.82k
        if implicit_dimensions {
97
0
            self.width = width as u16;
98
0
            self.height = height as u16;
99
0
        } else {
100
3.82k
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
3.82k
            if signature != 0x2f {
102
9
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
3.81k
            }
104
105
3.81k
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
3.80k
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
3.80k
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
56
                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.52k
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
3.52k
        self.decode_image_stream(
121
3.52k
            transformed_width,
122
3.52k
            self.height,
123
            true,
124
3.52k
            &mut buf[..transformed_size],
125
839
        )?;
126
127
2.69k
        let mut image_size = transformed_size;
128
2.69k
        let mut width = transformed_width;
129
4.78k
        for &trans_index in self.transform_order.iter().rev() {
130
4.78k
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
4.78k
            match transform {
132
                TransformType::PredictorTransform {
133
2.37k
                    size_bits,
134
2.37k
                    predictor_data,
135
2.37k
                } => apply_predictor_transform(
136
2.37k
                    &mut buf[..image_size],
137
2.37k
                    width,
138
2.37k
                    self.height,
139
2.37k
                    *size_bits,
140
2.37k
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
46
                    size_bits,
144
46
                    transform_data,
145
46
                } => {
146
46
                    apply_color_transform(
147
46
                        &mut buf[..image_size],
148
46
                        width,
149
46
                        *size_bits,
150
46
                        transform_data,
151
46
                    );
152
46
                }
153
2.18k
                TransformType::SubtractGreen => {
154
2.18k
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
2.18k
                }
156
                TransformType::ColorIndexingTransform {
157
184
                    table_size,
158
184
                    table_data,
159
184
                } => {
160
184
                    width = self.width;
161
184
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
184
                    apply_color_indexing_transform(
163
184
                        buf,
164
184
                        width,
165
184
                        self.height,
166
184
                        *table_size,
167
184
                        table_data,
168
184
                    );
169
184
                }
170
            }
171
        }
172
173
2.69k
        Ok(())
174
3.82k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_frame
Line
Count
Source
89
1.16k
    pub(crate) fn decode_frame(
90
1.16k
        &mut self,
91
1.16k
        width: u32,
92
1.16k
        height: u32,
93
1.16k
        implicit_dimensions: bool,
94
1.16k
        buf: &mut [u8],
95
1.16k
    ) -> Result<(), DecodingError> {
96
1.16k
        if implicit_dimensions {
97
1.16k
            self.width = width as u16;
98
1.16k
            self.height = height as u16;
99
1.16k
        } else {
100
0
            let signature = self.bit_reader.read_bits::<u8>(8)?;
101
0
            if signature != 0x2f {
102
0
                return Err(DecodingError::LosslessSignatureInvalid(signature));
103
0
            }
104
105
0
            self.width = self.bit_reader.read_bits::<u16>(14)? + 1;
106
0
            self.height = self.bit_reader.read_bits::<u16>(14)? + 1;
107
0
            if u32::from(self.width) != width || u32::from(self.height) != height {
108
0
                return Err(DecodingError::InconsistentImageSizes);
109
0
            }
110
111
0
            let _alpha_used = self.bit_reader.read_bits::<u8>(1)?;
112
0
            let version_num = self.bit_reader.read_bits::<u8>(3)?;
113
0
            if version_num != 0 {
114
0
                return Err(DecodingError::VersionNumberInvalid(version_num));
115
0
            }
116
        }
117
118
1.16k
        let transformed_width = self.read_transforms()?;
119
865
        let transformed_size = usize::from(transformed_width) * usize::from(self.height) * 4;
120
865
        self.decode_image_stream(
121
865
            transformed_width,
122
865
            self.height,
123
            true,
124
865
            &mut buf[..transformed_size],
125
672
        )?;
126
127
193
        let mut image_size = transformed_size;
128
193
        let mut width = transformed_width;
129
193
        for &trans_index in self.transform_order.iter().rev() {
130
149
            let transform = self.transforms[usize::from(trans_index)].as_ref().unwrap();
131
149
            match transform {
132
                TransformType::PredictorTransform {
133
67
                    size_bits,
134
67
                    predictor_data,
135
67
                } => apply_predictor_transform(
136
67
                    &mut buf[..image_size],
137
67
                    width,
138
67
                    self.height,
139
67
                    *size_bits,
140
67
                    predictor_data,
141
0
                )?,
142
                TransformType::ColorTransform {
143
27
                    size_bits,
144
27
                    transform_data,
145
27
                } => {
146
27
                    apply_color_transform(
147
27
                        &mut buf[..image_size],
148
27
                        width,
149
27
                        *size_bits,
150
27
                        transform_data,
151
27
                    );
152
27
                }
153
29
                TransformType::SubtractGreen => {
154
29
                    apply_subtract_green_transform(&mut buf[..image_size]);
155
29
                }
156
                TransformType::ColorIndexingTransform {
157
26
                    table_size,
158
26
                    table_data,
159
26
                } => {
160
26
                    width = self.width;
161
26
                    image_size = usize::from(width) * usize::from(self.height) * 4;
162
26
                    apply_color_indexing_transform(
163
26
                        buf,
164
26
                        width,
165
26
                        self.height,
166
26
                        *table_size,
167
26
                        table_data,
168
26
                    );
169
26
                }
170
            }
171
        }
172
173
193
        Ok(())
174
1.16k
    }
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
9.04k
    fn decode_image_stream(
182
9.04k
        &mut self,
183
9.04k
        xsize: u16,
184
9.04k
        ysize: u16,
185
9.04k
        is_argb_img: bool,
186
9.04k
        data: &mut [u8],
187
9.04k
    ) -> Result<(), DecodingError> {
188
9.04k
        let color_cache_bits = self.read_color_cache()?;
189
9.00k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
1.53k
            color_cache_bits: bits,
191
1.53k
            color_cache: vec![[0; 4]; 1 << bits],
192
1.53k
        });
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
810
            color_cache_bits: bits,
191
810
            color_cache: vec![[0; 4]; 1 << bits],
192
810
        });
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream::{closure#0}
Line
Count
Source
190
728
            color_cache_bits: bits,
191
728
            color_cache: vec![[0; 4]; 1 << bits],
192
728
        });
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream::{closure#0}
193
194
9.00k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
7.60k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
9.04k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
6.95k
    fn decode_image_stream(
182
6.95k
        &mut self,
183
6.95k
        xsize: u16,
184
6.95k
        ysize: u16,
185
6.95k
        is_argb_img: bool,
186
6.95k
        data: &mut [u8],
187
6.95k
    ) -> Result<(), DecodingError> {
188
6.95k
        let color_cache_bits = self.read_color_cache()?;
189
6.92k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
            color_cache_bits: bits,
191
            color_cache: vec![[0; 4]; 1 << bits],
192
        });
193
194
6.92k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
6.21k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
6.95k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_stream
Line
Count
Source
181
2.09k
    fn decode_image_stream(
182
2.09k
        &mut self,
183
2.09k
        xsize: u16,
184
2.09k
        ysize: u16,
185
2.09k
        is_argb_img: bool,
186
2.09k
        data: &mut [u8],
187
2.09k
    ) -> Result<(), DecodingError> {
188
2.09k
        let color_cache_bits = self.read_color_cache()?;
189
2.07k
        let color_cache = color_cache_bits.map(|bits| ColorCache {
190
            color_cache_bits: bits,
191
            color_cache: vec![[0; 4]; 1 << bits],
192
        });
193
194
2.07k
        let huffman_info = self.read_huffman_codes(is_argb_img, xsize, ysize, color_cache)?;
195
1.38k
        self.decode_image_data(xsize, ysize, huffman_info, data)
196
2.09k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_stream
197
198
    /// Reads transforms and their data from the bitstream
199
4.91k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
4.91k
        let mut xsize = self.width;
201
202
10.8k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
6.40k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
6.38k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
9
                return Err(DecodingError::TransformError);
208
6.37k
            }
209
210
6.37k
            self.transform_order.push(transform_type_val);
211
212
6.37k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
3.07k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
3.07k
                    let block_xsize = subsample_size(xsize, size_bits);
219
3.07k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
3.07k
                    let mut predictor_data =
222
3.07k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
3.07k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.82k
                    TransformType::PredictorTransform {
226
2.82k
                        size_bits,
227
2.82k
                        predictor_data,
228
2.82k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
232
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
228
                    let block_xsize = subsample_size(xsize, size_bits);
236
228
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
228
                    let mut transform_data =
239
228
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
228
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
150
                    TransformType::ColorTransform {
243
150
                        size_bits,
244
150
                        transform_data,
245
150
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.54k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
529
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
522
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
522
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
424
                    let bits = if color_table_size <= 2 {
259
152
                        3
260
272
                    } else if color_table_size <= 4 {
261
99
                        2
262
173
                    } else if color_table_size <= 16 {
263
66
                        1
264
                    } else {
265
107
                        0
266
                    };
267
424
                    xsize = subsample_size(xsize, bits);
268
269
424
                    Self::adjust_color_map(&mut color_map);
270
271
424
                    TransformType::ColorIndexingTransform {
272
424
                        table_size: color_table_size,
273
424
                        table_data: color_map,
274
424
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
5.93k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
4.39k
        Ok(xsize)
283
4.91k
    }
<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
8.88k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
5.30k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
5.29k
            if self.transforms[usize::from(transform_type_val)].is_some() {
206
                //can only have one of each transform, error
207
4
                return Err(DecodingError::TransformError);
208
5.29k
            }
209
210
5.29k
            self.transform_order.push(transform_type_val);
211
212
5.29k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
2.60k
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
2.60k
                    let block_xsize = subsample_size(xsize, size_bits);
219
2.60k
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
2.60k
                    let mut predictor_data =
222
2.60k
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
2.60k
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
2.52k
                    TransformType::PredictorTransform {
226
2.52k
                        size_bits,
227
2.52k
                        predictor_data,
228
2.52k
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
107
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
105
                    let block_xsize = subsample_size(xsize, size_bits);
236
105
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
105
                    let mut transform_data =
239
105
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
105
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
84
                    TransformType::ColorTransform {
243
84
                        size_bits,
244
84
                        transform_data,
245
84
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
2.28k
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
292
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
287
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
287
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
241
                    let bits = if color_table_size <= 2 {
259
52
                        3
260
189
                    } else if color_table_size <= 4 {
261
58
                        2
262
131
                    } else if color_table_size <= 16 {
263
58
                        1
264
                    } else {
265
73
                        0
266
                    };
267
241
                    xsize = subsample_size(xsize, bits);
268
269
241
                    Self::adjust_color_map(&mut color_map);
270
271
241
                    TransformType::ColorIndexingTransform {
272
241
                        table_size: color_table_size,
273
241
                        table_data: color_map,
274
241
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
5.14k
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
3.52k
        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
1.16k
    fn read_transforms(&mut self) -> Result<u16, DecodingError> {
200
1.16k
        let mut xsize = self.width;
201
202
1.96k
        while self.bit_reader.read_bits::<u8>(1)? == 1 {
203
1.09k
            let transform_type_val = self.bit_reader.read_bits::<u8>(2)?;
204
205
1.09k
            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
1.08k
            }
209
210
1.08k
            self.transform_order.push(transform_type_val);
211
212
1.08k
            let transform_type = match transform_type_val {
213
                0 => {
214
                    //predictor
215
216
472
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
217
218
470
                    let block_xsize = subsample_size(xsize, size_bits);
219
470
                    let block_ysize = subsample_size(self.height, size_bits);
220
221
470
                    let mut predictor_data =
222
470
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
223
470
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut predictor_data)?;
224
225
294
                    TransformType::PredictorTransform {
226
294
                        size_bits,
227
294
                        predictor_data,
228
294
                    }
229
                }
230
                1 => {
231
                    //color transform
232
233
125
                    let size_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
234
235
123
                    let block_xsize = subsample_size(xsize, size_bits);
236
123
                    let block_ysize = subsample_size(self.height, size_bits);
237
238
123
                    let mut transform_data =
239
123
                        vec![0; usize::from(block_xsize) * usize::from(block_ysize) * 4];
240
123
                    self.decode_image_stream(block_xsize, block_ysize, false, &mut transform_data)?;
241
242
66
                    TransformType::ColorTransform {
243
66
                        size_bits,
244
66
                        transform_data,
245
66
                    }
246
                }
247
                2 => {
248
                    //subtract green
249
250
252
                    TransformType::SubtractGreen
251
                }
252
                3 => {
253
237
                    let color_table_size = self.bit_reader.read_bits::<u16>(8)? + 1;
254
255
235
                    let mut color_map = vec![0; usize::from(color_table_size) * 4];
256
235
                    self.decode_image_stream(color_table_size, 1, false, &mut color_map)?;
257
258
183
                    let bits = if color_table_size <= 2 {
259
100
                        3
260
83
                    } else if color_table_size <= 4 {
261
41
                        2
262
42
                    } else if color_table_size <= 16 {
263
8
                        1
264
                    } else {
265
34
                        0
266
                    };
267
183
                    xsize = subsample_size(xsize, bits);
268
269
183
                    Self::adjust_color_map(&mut color_map);
270
271
183
                    TransformType::ColorIndexingTransform {
272
183
                        table_size: color_table_size,
273
183
                        table_data: color_map,
274
183
                    }
275
                }
276
0
                _ => unreachable!(),
277
            };
278
279
795
            self.transforms[usize::from(transform_type_val)] = Some(transform_type);
280
        }
281
282
865
        Ok(xsize)
283
1.16k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_transforms
284
285
    /// Adjusts the color map since it's subtraction coded
286
424
    fn adjust_color_map(color_map: &mut [u8]) {
287
68.7k
        for i in 4..color_map.len() {
288
68.7k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
68.7k
        }
290
424
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
241
    fn adjust_color_map(color_map: &mut [u8]) {
287
50.2k
        for i in 4..color_map.len() {
288
50.2k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
50.2k
        }
290
241
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::adjust_color_map
Line
Count
Source
286
183
    fn adjust_color_map(color_map: &mut [u8]) {
287
18.5k
        for i in 4..color_map.len() {
288
18.5k
            color_map[i] = color_map[i].wrapping_add(color_map[i - 4]);
289
18.5k
        }
290
183
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::adjust_color_map
291
292
    /// Reads huffman codes associated with an image
293
9.00k
    fn read_huffman_codes(
294
9.00k
        &mut self,
295
9.00k
        read_meta: bool,
296
9.00k
        xsize: u16,
297
9.00k
        ysize: u16,
298
9.00k
        color_cache: Option<ColorCache>,
299
9.00k
    ) -> Result<HuffmanInfo, DecodingError> {
300
9.00k
        let mut num_huff_groups = 1u32;
301
302
9.00k
        let mut huffman_bits = 0;
303
9.00k
        let mut huffman_xsize = 1;
304
9.00k
        let mut huffman_ysize = 1;
305
9.00k
        let mut entropy_image = Vec::new();
306
307
9.00k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
840
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
828
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
828
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
828
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
828
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
612
            entropy_image = data
317
612
                .chunks_exact(4)
318
51.5M
                .map(|pixel| {
319
51.5M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
51.5M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
668
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
51.5M
                    }
323
51.5M
                    meta_huff_code
324
51.5M
                })
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
49.6M
                .map(|pixel| {
319
49.6M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
49.6M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
410
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
49.6M
                    }
323
49.6M
                    meta_huff_code
324
49.6M
                })
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes::{closure#0}
Line
Count
Source
318
1.93M
                .map(|pixel| {
319
1.93M
                    let meta_huff_code = (u16::from(pixel[0]) << 8) | u16::from(pixel[1]);
320
1.93M
                    if u32::from(meta_huff_code) >= num_huff_groups {
321
258
                        num_huff_groups = u32::from(meta_huff_code) + 1;
322
1.93M
                    }
323
1.93M
                    meta_huff_code
324
1.93M
                })
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes::{closure#0}
325
612
                .collect::<Vec<u16>>();
326
8.15k
        }
327
328
8.76k
        let mut hufftree_groups = Vec::new();
329
330
27.1k
        for _i in 0..num_huff_groups {
331
27.1k
            let mut group: HuffmanCodeGroup = Default::default();
332
158k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
132k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
132k
                if j == 0 {
335
27.1k
                    if let Some(color_cache) = color_cache.as_ref() {
336
6.11k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
21.0k
                    }
338
105k
                }
339
340
132k
                let tree = self.read_huffman_code(alphabet_size)?;
341
131k
                group[j] = tree;
342
            }
343
26.0k
            hufftree_groups.push(group);
344
        }
345
346
7.60k
        let huffman_mask = if huffman_bits == 0 {
347
7.42k
            !0
348
        } else {
349
177
            (1 << huffman_bits) - 1
350
        };
351
352
7.60k
        let info = HuffmanInfo {
353
7.60k
            xsize: huffman_xsize,
354
7.60k
            _ysize: huffman_ysize,
355
7.60k
            color_cache,
356
7.60k
            image: entropy_image,
357
7.60k
            bits: huffman_bits,
358
7.60k
            mask: huffman_mask,
359
7.60k
            huffman_code_groups: hufftree_groups,
360
7.60k
        };
361
362
7.60k
        Ok(info)
363
9.00k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
6.92k
    fn read_huffman_codes(
294
6.92k
        &mut self,
295
6.92k
        read_meta: bool,
296
6.92k
        xsize: u16,
297
6.92k
        ysize: u16,
298
6.92k
        color_cache: Option<ColorCache>,
299
6.92k
    ) -> Result<HuffmanInfo, DecodingError> {
300
6.92k
        let mut num_huff_groups = 1u32;
301
302
6.92k
        let mut huffman_bits = 0;
303
6.92k
        let mut huffman_xsize = 1;
304
6.92k
        let mut huffman_ysize = 1;
305
6.92k
        let mut entropy_image = Vec::new();
306
307
6.92k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
441
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
431
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
431
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
431
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
431
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
342
            entropy_image = data
317
342
                .chunks_exact(4)
318
342
                .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
342
                .collect::<Vec<u16>>();
326
6.48k
        }
327
328
6.82k
        let mut hufftree_groups = Vec::new();
329
330
21.4k
        for _i in 0..num_huff_groups {
331
21.4k
            let mut group: HuffmanCodeGroup = Default::default();
332
126k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
105k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
105k
                if j == 0 {
335
21.4k
                    if let Some(color_cache) = color_cache.as_ref() {
336
5.02k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
16.4k
                    }
338
84.2k
                }
339
340
105k
                let tree = self.read_huffman_code(alphabet_size)?;
341
105k
                group[j] = tree;
342
            }
343
20.8k
            hufftree_groups.push(group);
344
        }
345
346
6.21k
        let huffman_mask = if huffman_bits == 0 {
347
6.15k
            !0
348
        } else {
349
65
            (1 << huffman_bits) - 1
350
        };
351
352
6.21k
        let info = HuffmanInfo {
353
6.21k
            xsize: huffman_xsize,
354
6.21k
            _ysize: huffman_ysize,
355
6.21k
            color_cache,
356
6.21k
            image: entropy_image,
357
6.21k
            bits: huffman_bits,
358
6.21k
            mask: huffman_mask,
359
6.21k
            huffman_code_groups: hufftree_groups,
360
6.21k
        };
361
362
6.21k
        Ok(info)
363
6.92k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_codes
Line
Count
Source
293
2.07k
    fn read_huffman_codes(
294
2.07k
        &mut self,
295
2.07k
        read_meta: bool,
296
2.07k
        xsize: u16,
297
2.07k
        ysize: u16,
298
2.07k
        color_cache: Option<ColorCache>,
299
2.07k
    ) -> Result<HuffmanInfo, DecodingError> {
300
2.07k
        let mut num_huff_groups = 1u32;
301
302
2.07k
        let mut huffman_bits = 0;
303
2.07k
        let mut huffman_xsize = 1;
304
2.07k
        let mut huffman_ysize = 1;
305
2.07k
        let mut entropy_image = Vec::new();
306
307
2.07k
        if read_meta && self.bit_reader.read_bits::<u8>(1)? == 1 {
308
            //meta huffman codes
309
399
            huffman_bits = self.bit_reader.read_bits::<u8>(3)? + 2;
310
397
            huffman_xsize = subsample_size(xsize, huffman_bits);
311
397
            huffman_ysize = subsample_size(ysize, huffman_bits);
312
313
397
            let mut data = vec![0; usize::from(huffman_xsize) * usize::from(huffman_ysize) * 4];
314
397
            self.decode_image_stream(huffman_xsize, huffman_ysize, false, &mut data)?;
315
316
270
            entropy_image = data
317
270
                .chunks_exact(4)
318
270
                .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
270
                .collect::<Vec<u16>>();
326
1.66k
        }
327
328
1.93k
        let mut hufftree_groups = Vec::new();
329
330
5.69k
        for _i in 0..num_huff_groups {
331
5.69k
            let mut group: HuffmanCodeGroup = Default::default();
332
32.0k
            for j in 0..HUFFMAN_CODES_PER_META_CODE {
333
26.9k
                let mut alphabet_size = ALPHABET_SIZE[j];
334
26.9k
                if j == 0 {
335
5.69k
                    if let Some(color_cache) = color_cache.as_ref() {
336
1.08k
                        alphabet_size += 1 << color_cache.color_cache_bits;
337
4.60k
                    }
338
21.2k
                }
339
340
26.9k
                let tree = self.read_huffman_code(alphabet_size)?;
341
26.3k
                group[j] = tree;
342
            }
343
5.14k
            hufftree_groups.push(group);
344
        }
345
346
1.38k
        let huffman_mask = if huffman_bits == 0 {
347
1.27k
            !0
348
        } else {
349
112
            (1 << huffman_bits) - 1
350
        };
351
352
1.38k
        let info = HuffmanInfo {
353
1.38k
            xsize: huffman_xsize,
354
1.38k
            _ysize: huffman_ysize,
355
1.38k
            color_cache,
356
1.38k
            image: entropy_image,
357
1.38k
            bits: huffman_bits,
358
1.38k
            mask: huffman_mask,
359
1.38k
            huffman_code_groups: hufftree_groups,
360
1.38k
        };
361
362
1.38k
        Ok(info)
363
2.07k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_codes
364
365
    /// Decodes and returns a single huffman tree
366
132k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
132k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
132k
        if simple {
370
119k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
119k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
119k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
119k
            if zero_symbol >= alphabet_size {
376
17
                return Err(DecodingError::BitStreamError);
377
119k
            }
378
379
119k
            if num_symbols == 1 {
380
111k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
7.96k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
7.92k
                if one_symbol >= alphabet_size {
384
15
                    return Err(DecodingError::BitStreamError);
385
7.90k
                }
386
7.90k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
12.9k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
12.9k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
181k
            for i in 0..num_code_lengths {
393
181k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
181k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
12.2k
            let new_code_lengths =
398
12.7k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
12.2k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
132k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
105k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
105k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
105k
        if simple {
370
94.8k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
94.7k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
94.7k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
94.7k
            if zero_symbol >= alphabet_size {
376
4
                return Err(DecodingError::BitStreamError);
377
94.7k
            }
378
379
94.7k
            if num_symbols == 1 {
380
89.1k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
5.54k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
5.51k
                if one_symbol >= alphabet_size {
384
5
                    return Err(DecodingError::BitStreamError);
385
5.51k
                }
386
5.51k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
10.7k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
10.7k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
165k
            for i in 0..num_code_lengths {
393
165k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
165k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
10.4k
            let new_code_lengths =
398
10.6k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
10.4k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
105k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code
Line
Count
Source
366
26.9k
    fn read_huffman_code(&mut self, alphabet_size: u16) -> Result<HuffmanTree, DecodingError> {
367
26.9k
        let simple = self.bit_reader.read_bits::<u8>(1)? == 1;
368
369
26.9k
        if simple {
370
24.7k
            let num_symbols = self.bit_reader.read_bits::<u8>(1)? + 1;
371
372
24.7k
            let is_first_8bits = self.bit_reader.read_bits::<u8>(1)?;
373
24.7k
            let zero_symbol = self.bit_reader.read_bits::<u16>(1 + 7 * is_first_8bits)?;
374
375
24.7k
            if zero_symbol >= alphabet_size {
376
13
                return Err(DecodingError::BitStreamError);
377
24.7k
            }
378
379
24.7k
            if num_symbols == 1 {
380
22.2k
                Ok(HuffmanTree::build_single_node(zero_symbol))
381
            } else {
382
2.42k
                let one_symbol = self.bit_reader.read_bits::<u16>(8)?;
383
2.40k
                if one_symbol >= alphabet_size {
384
10
                    return Err(DecodingError::BitStreamError);
385
2.39k
                }
386
2.39k
                Ok(HuffmanTree::build_two_node(zero_symbol, one_symbol))
387
            }
388
        } else {
389
2.11k
            let mut code_length_code_lengths = vec![0; CODE_LENGTH_CODES];
390
391
2.11k
            let num_code_lengths = 4 + self.bit_reader.read_bits::<usize>(4)?;
392
16.4k
            for i in 0..num_code_lengths {
393
16.3k
                code_length_code_lengths[CODE_LENGTH_CODE_ORDER[i]] =
394
16.4k
                    self.bit_reader.read_bits(3)?;
395
            }
396
397
1.73k
            let new_code_lengths =
398
2.03k
                self.read_huffman_code_lengths(code_length_code_lengths, alphabet_size)?;
399
400
1.73k
            HuffmanTree::build_implicit(new_code_lengths)
401
        }
402
26.9k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_huffman_code
403
404
    /// Reads huffman code lengths
405
12.7k
    fn read_huffman_code_lengths(
406
12.7k
        &mut self,
407
12.7k
        code_length_code_lengths: Vec<u16>,
408
12.7k
        num_symbols: u16,
409
12.7k
    ) -> Result<Vec<u16>, DecodingError> {
410
12.7k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
12.4k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
8.26k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
8.24k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
8.22k
            if max_minus_two > num_symbols - 2 {
416
3
                return Err(DecodingError::BitStreamError);
417
8.22k
            }
418
8.22k
            2 + max_minus_two
419
        } else {
420
4.16k
            num_symbols
421
        };
422
423
12.3k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
12.3k
        let mut prev_code_len = 8; //default code length
425
426
12.3k
        let mut symbol = 0;
427
1.97M
        while symbol < num_symbols {
428
1.96M
            if max_symbol == 0 {
429
2.92k
                break;
430
1.96M
            }
431
1.96M
            max_symbol -= 1;
432
433
1.96M
            self.bit_reader.fill()?;
434
1.96M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.96M
            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
823k
                    prev_code_len = code_len;
441
1.11M
                }
442
            } else {
443
29.2k
                let use_prev = code_len == 16;
444
29.2k
                let slot = code_len - 16;
445
29.2k
                let extra_bits = match slot {
446
16.3k
                    0 => 2,
447
5.15k
                    1 => 3,
448
7.79k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
29.2k
                let repeat_offset = match slot {
452
21.5k
                    0 | 1 => 3,
453
7.79k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
29.2k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
29.2k
                if symbol + repeat > num_symbols {
460
44
                    return Err(DecodingError::BitStreamError);
461
29.1k
                }
462
463
29.1k
                let length = if use_prev { prev_code_len } else { 0 };
464
699k
                while repeat > 0 {
465
669k
                    repeat -= 1;
466
669k
                    code_lengths[usize::from(symbol)] = length;
467
669k
                    symbol += 1;
468
669k
                }
469
            }
470
        }
471
472
12.2k
        Ok(code_lengths)
473
12.7k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
10.6k
    fn read_huffman_code_lengths(
406
10.6k
        &mut self,
407
10.6k
        code_length_code_lengths: Vec<u16>,
408
10.6k
        num_symbols: u16,
409
10.6k
    ) -> Result<Vec<u16>, DecodingError> {
410
10.6k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
10.5k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
7.35k
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
7.34k
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
7.33k
            if max_minus_two > num_symbols - 2 {
416
2
                return Err(DecodingError::BitStreamError);
417
7.33k
            }
418
7.33k
            2 + max_minus_two
419
        } else {
420
3.23k
            num_symbols
421
        };
422
423
10.5k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
10.5k
        let mut prev_code_len = 8; //default code length
425
426
10.5k
        let mut symbol = 0;
427
1.94M
        while symbol < num_symbols {
428
1.94M
            if max_symbol == 0 {
429
2.04k
                break;
430
1.93M
            }
431
1.93M
            max_symbol -= 1;
432
433
1.93M
            self.bit_reader.fill()?;
434
1.93M
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
1.93M
            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
806k
                    prev_code_len = code_len;
441
1.11M
                }
442
            } else {
443
21.7k
                let use_prev = code_len == 16;
444
21.7k
                let slot = code_len - 16;
445
21.7k
                let extra_bits = match slot {
446
13.6k
                    0 => 2,
447
3.59k
                    1 => 3,
448
4.48k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
21.7k
                let repeat_offset = match slot {
452
17.2k
                    0 | 1 => 3,
453
4.48k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
21.7k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
21.6k
                if symbol + repeat > num_symbols {
460
19
                    return Err(DecodingError::BitStreamError);
461
21.6k
                }
462
463
21.6k
                let length = if use_prev { prev_code_len } else { 0 };
464
401k
                while repeat > 0 {
465
379k
                    repeat -= 1;
466
379k
                    code_lengths[usize::from(symbol)] = length;
467
379k
                    symbol += 1;
468
379k
                }
469
            }
470
        }
471
472
10.4k
        Ok(code_lengths)
473
10.6k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_huffman_code_lengths
Line
Count
Source
405
2.03k
    fn read_huffman_code_lengths(
406
2.03k
        &mut self,
407
2.03k
        code_length_code_lengths: Vec<u16>,
408
2.03k
        num_symbols: u16,
409
2.03k
    ) -> Result<Vec<u16>, DecodingError> {
410
2.03k
        let table = HuffmanTree::build_implicit(code_length_code_lengths)?;
411
412
1.83k
        let mut max_symbol = if self.bit_reader.read_bits::<u8>(1)? == 1 {
413
901
            let length_nbits = 2 + 2 * self.bit_reader.read_bits::<u8>(3)?;
414
896
            let max_minus_two = self.bit_reader.read_bits::<u16>(length_nbits)?;
415
891
            if max_minus_two > num_symbols - 2 {
416
1
                return Err(DecodingError::BitStreamError);
417
890
            }
418
890
            2 + max_minus_two
419
        } else {
420
934
            num_symbols
421
        };
422
423
1.82k
        let mut code_lengths = vec![0; usize::from(num_symbols)];
424
1.82k
        let mut prev_code_len = 8; //default code length
425
426
1.82k
        let mut symbol = 0;
427
29.2k
        while symbol < num_symbols {
428
28.4k
            if max_symbol == 0 {
429
884
                break;
430
27.5k
            }
431
27.5k
            max_symbol -= 1;
432
433
27.5k
            self.bit_reader.fill()?;
434
27.5k
            let code_len = table.read_symbol(&mut self.bit_reader)?;
435
436
27.5k
            if code_len < 16 {
437
19.9k
                code_lengths[usize::from(symbol)] = code_len;
438
19.9k
                symbol += 1;
439
19.9k
                if code_len != 0 {
440
17.6k
                    prev_code_len = code_len;
441
17.6k
                }
442
            } else {
443
7.58k
                let use_prev = code_len == 16;
444
7.58k
                let slot = code_len - 16;
445
7.58k
                let extra_bits = match slot {
446
2.71k
                    0 => 2,
447
1.55k
                    1 => 3,
448
3.30k
                    2 => 7,
449
0
                    _ => return Err(DecodingError::BitStreamError),
450
                };
451
7.58k
                let repeat_offset = match slot {
452
4.27k
                    0 | 1 => 3,
453
3.30k
                    2 => 11,
454
0
                    _ => return Err(DecodingError::BitStreamError),
455
                };
456
457
7.58k
                let mut repeat = self.bit_reader.read_bits::<u16>(extra_bits)? + repeat_offset;
458
459
7.54k
                if symbol + repeat > num_symbols {
460
25
                    return Err(DecodingError::BitStreamError);
461
7.51k
                }
462
463
7.51k
                let length = if use_prev { prev_code_len } else { 0 };
464
297k
                while repeat > 0 {
465
289k
                    repeat -= 1;
466
289k
                    code_lengths[usize::from(symbol)] = length;
467
289k
                    symbol += 1;
468
289k
                }
469
            }
470
        }
471
472
1.73k
        Ok(code_lengths)
473
2.03k
    }
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.60k
    fn decode_image_data(
477
7.60k
        &mut self,
478
7.60k
        width: u16,
479
7.60k
        height: u16,
480
7.60k
        mut huffman_info: HuffmanInfo,
481
7.60k
        data: &mut [u8],
482
7.60k
    ) -> Result<(), DecodingError> {
483
7.60k
        let num_values = usize::from(width) * usize::from(height);
484
485
7.60k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
7.60k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
7.60k
        let mut index = 0;
488
489
7.60k
        let mut next_block_start = 0;
490
246M
        while index < num_values {
491
246M
            self.bit_reader.fill()?;
492
493
246M
            if index >= next_block_start {
494
95.2M
                let x = index % usize::from(width);
495
95.2M
                let y = index / usize::from(width);
496
95.2M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
95.2M
                    + y * usize::from(width)
498
95.2M
                    + 1;
499
500
95.2M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
95.2M
                tree = &huffman_info.huffman_code_groups[huff_index];
502
503
                // Fast path: If all the codes each contain only a single
504
                // symbol, then the pixel data isn't written to the bitstream
505
                // and we can just fill the output buffer with the symbol
506
                // directly.
507
378M
                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
342M
                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
35.9M
                if tree[..4].iter().all(|t| t.is_single_node()) {
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data::{closure#0}
508
94.5M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
94.5M
                    if code < 256 {
510
94.5M
                        let n = if huffman_info.bits == 0 {
511
3.58k
                            num_values
512
                        } else {
513
94.5M
                            next_block_start - index
514
                        };
515
516
94.5M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
94.5M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
94.5M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
94.5M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
4.90G
                        for i in 0..n {
522
4.90G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
4.90G
                        }
524
525
94.5M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
37.8M
                            color_cache.insert(value);
527
56.6M
                        }
528
529
94.5M
                        index += n;
530
94.5M
                        continue;
531
45.3k
                    }
532
690k
                }
533
151M
            }
534
535
151M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
151M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
19.1M
                let green = code as u8;
541
19.1M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
19.1M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
19.1M
                if self.bit_reader.nbits < 15 {
544
7.22k
                    self.bit_reader.fill()?;
545
19.1M
                }
546
19.1M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
19.1M
                data[index * 4] = red;
549
19.1M
                data[index * 4 + 1] = green;
550
19.1M
                data[index * 4 + 2] = blue;
551
19.1M
                data[index * 4 + 3] = alpha;
552
553
19.1M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
3.98M
                    color_cache.insert([red, green, blue, alpha]);
555
15.1M
                }
556
19.1M
                index += 1;
557
132M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
6.73M
                let length_symbol = code - 256;
560
6.73M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
6.73M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
6.73M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
6.73M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
6.73M
                if index < dist || num_values - index < length {
567
82
                    return Err(DecodingError::BitStreamError);
568
6.73M
                }
569
570
6.73M
                if dist == 1 {
571
3.69M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
583M
                    for i in 0..length {
573
583M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
583M
                    }
575
                } else {
576
3.03M
                    if index + length + 3 <= num_values {
577
3.03M
                        let start = (index - dist) * 4;
578
3.03M
                        data.copy_within(start..start + 16, index * 4);
579
580
3.03M
                        if length > 4 || dist < 4 {
581
106M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
106M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
106M
                            }
584
10.7k
                        }
585
                    } else {
586
65.8k
                        for i in 0..length * 4 {
587
65.8k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
65.8k
                        }
589
                    }
590
591
3.03M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
431M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
431M
                            color_cache.insert(pixel.try_into().unwrap());
594
431M
                        }
595
28.5k
                    }
596
                }
597
6.73M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
125M
                let color_cache = huffman_info
601
125M
                    .color_cache
602
125M
                    .as_mut()
603
125M
                    .ok_or(DecodingError::BitStreamError)?;
604
125M
                let color = color_cache.lookup((code - 280).into());
605
125M
                data[index * 4..][..4].copy_from_slice(&color);
606
125M
                index += 1;
607
608
125M
                if index < next_block_start {
609
125M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
125M
                        if code >= 280 {
611
123M
                            self.bit_reader.consume(bits)?;
612
123M
                            data[index * 4..][..4]
613
123M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
123M
                            index += 1;
615
1.96M
                        }
616
407
                    }
617
67.6k
                }
618
            }
619
        }
620
621
6.89k
        Ok(())
622
7.60k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
6.21k
    fn decode_image_data(
477
6.21k
        &mut self,
478
6.21k
        width: u16,
479
6.21k
        height: u16,
480
6.21k
        mut huffman_info: HuffmanInfo,
481
6.21k
        data: &mut [u8],
482
6.21k
    ) -> Result<(), DecodingError> {
483
6.21k
        let num_values = usize::from(width) * usize::from(height);
484
485
6.21k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
6.21k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
6.21k
        let mut index = 0;
488
489
6.21k
        let mut next_block_start = 0;
490
222M
        while index < num_values {
491
222M
            self.bit_reader.fill()?;
492
493
222M
            if index >= next_block_start {
494
85.9M
                let x = index % usize::from(width);
495
85.9M
                let y = index / usize::from(width);
496
85.9M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
85.9M
                    + y * usize::from(width)
498
85.9M
                    + 1;
499
500
85.9M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
85.9M
                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
85.9M
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
85.6M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
85.6M
                    if code < 256 {
510
85.6M
                        let n = if huffman_info.bits == 0 {
511
3.19k
                            num_values
512
                        } else {
513
85.6M
                            next_block_start - index
514
                        };
515
516
85.6M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
85.6M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
85.6M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
85.6M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
4.58G
                        for i in 0..n {
522
4.58G
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
4.58G
                        }
524
525
85.6M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
37.8M
                            color_cache.insert(value);
527
47.8M
                        }
528
529
85.6M
                        index += n;
530
85.6M
                        continue;
531
30.3k
                    }
532
231k
                }
533
137M
            }
534
535
137M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
137M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
15.0M
                let green = code as u8;
541
15.0M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
15.0M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
15.0M
                if self.bit_reader.nbits < 15 {
544
5.95k
                    self.bit_reader.fill()?;
545
15.0M
                }
546
15.0M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
15.0M
                data[index * 4] = red;
549
15.0M
                data[index * 4 + 1] = green;
550
15.0M
                data[index * 4 + 2] = blue;
551
15.0M
                data[index * 4 + 3] = alpha;
552
553
15.0M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
83.9k
                    color_cache.insert([red, green, blue, alpha]);
555
14.9M
                }
556
15.0M
                index += 1;
557
122M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
157k
                let length_symbol = code - 256;
560
157k
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
157k
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
157k
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
157k
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
157k
                if index < dist || num_values - index < length {
567
43
                    return Err(DecodingError::BitStreamError);
568
157k
                }
569
570
157k
                if dist == 1 {
571
112k
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
47.3M
                    for i in 0..length {
573
47.3M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
47.3M
                    }
575
                } else {
576
45.4k
                    if index + length + 3 <= num_values {
577
45.3k
                        let start = (index - dist) * 4;
578
45.3k
                        data.copy_within(start..start + 16, index * 4);
579
580
45.3k
                        if length > 4 || dist < 4 {
581
12.6M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
12.6M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
12.6M
                            }
584
8.71k
                        }
585
                    } else {
586
24.5k
                        for i in 0..length * 4 {
587
24.5k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
24.5k
                        }
589
                    }
590
591
45.4k
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
50.4M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
50.4M
                            color_cache.insert(pixel.try_into().unwrap());
594
50.4M
                        }
595
5.10k
                    }
596
                }
597
157k
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
122M
                let color_cache = huffman_info
601
122M
                    .color_cache
602
122M
                    .as_mut()
603
122M
                    .ok_or(DecodingError::BitStreamError)?;
604
122M
                let color = color_cache.lookup((code - 280).into());
605
122M
                data[index * 4..][..4].copy_from_slice(&color);
606
122M
                index += 1;
607
608
122M
                if index < next_block_start {
609
122M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
122M
                        if code >= 280 {
611
122M
                            self.bit_reader.consume(bits)?;
612
122M
                            data[index * 4..][..4]
613
122M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
122M
                            index += 1;
615
7.14k
                        }
616
397
                    }
617
35.2k
                }
618
            }
619
        }
620
621
5.88k
        Ok(())
622
6.21k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::decode_image_data
Line
Count
Source
476
1.38k
    fn decode_image_data(
477
1.38k
        &mut self,
478
1.38k
        width: u16,
479
1.38k
        height: u16,
480
1.38k
        mut huffman_info: HuffmanInfo,
481
1.38k
        data: &mut [u8],
482
1.38k
    ) -> Result<(), DecodingError> {
483
1.38k
        let num_values = usize::from(width) * usize::from(height);
484
485
1.38k
        let huff_index = huffman_info.get_huff_index(0, 0);
486
1.38k
        let mut tree = &huffman_info.huffman_code_groups[huff_index];
487
1.38k
        let mut index = 0;
488
489
1.38k
        let mut next_block_start = 0;
490
23.2M
        while index < num_values {
491
23.2M
            self.bit_reader.fill()?;
492
493
23.2M
            if index >= next_block_start {
494
9.33M
                let x = index % usize::from(width);
495
9.33M
                let y = index / usize::from(width);
496
9.33M
                next_block_start = (x | usize::from(huffman_info.mask)).min(usize::from(width - 1))
497
9.33M
                    + y * usize::from(width)
498
9.33M
                    + 1;
499
500
9.33M
                let huff_index = huffman_info.get_huff_index(x as u16, y as u16);
501
9.33M
                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
9.33M
                if tree[..4].iter().all(|t| t.is_single_node()) {
508
8.87M
                    let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
509
8.87M
                    if code < 256 {
510
8.86M
                        let n = if huffman_info.bits == 0 {
511
393
                            num_values
512
                        } else {
513
8.85M
                            next_block_start - index
514
                        };
515
516
8.86M
                        let red = tree[RED].read_symbol(&mut self.bit_reader)?;
517
8.86M
                        let blue = tree[BLUE].read_symbol(&mut self.bit_reader)?;
518
8.86M
                        let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)?;
519
8.86M
                        let value = [red as u8, code as u8, blue as u8, alpha as u8];
520
521
325M
                        for i in 0..n {
522
325M
                            data[index * 4 + i * 4..][..4].copy_from_slice(&value);
523
325M
                        }
524
525
8.86M
                        if let Some(color_cache) = huffman_info.color_cache.as_mut() {
526
12.9k
                            color_cache.insert(value);
527
8.84M
                        }
528
529
8.86M
                        index += n;
530
8.86M
                        continue;
531
15.0k
                    }
532
459k
                }
533
13.9M
            }
534
535
14.4M
            let code = tree[GREEN].read_symbol(&mut self.bit_reader)?;
536
537
            //check code
538
14.4M
            if code < 256 {
539
                //literal, so just use huffman codes and read as argb
540
4.04M
                let green = code as u8;
541
4.04M
                let red = tree[RED].read_symbol(&mut self.bit_reader)? as u8;
542
4.04M
                let blue = tree[BLUE].read_symbol(&mut self.bit_reader)? as u8;
543
4.04M
                if self.bit_reader.nbits < 15 {
544
1.26k
                    self.bit_reader.fill()?;
545
4.04M
                }
546
4.04M
                let alpha = tree[ALPHA].read_symbol(&mut self.bit_reader)? as u8;
547
548
4.04M
                data[index * 4] = red;
549
4.04M
                data[index * 4 + 1] = green;
550
4.04M
                data[index * 4 + 2] = blue;
551
4.04M
                data[index * 4 + 3] = alpha;
552
553
4.04M
                if let Some(color_cache) = huffman_info.color_cache.as_mut() {
554
3.90M
                    color_cache.insert([red, green, blue, alpha]);
555
3.90M
                }
556
4.04M
                index += 1;
557
10.3M
            } else if code < 256 + 24 {
558
                //backward reference, so go back and use that to add image data
559
6.57M
                let length_symbol = code - 256;
560
6.57M
                let length = Self::get_copy_distance(&mut self.bit_reader, length_symbol)?;
561
562
6.57M
                let dist_symbol = tree[DIST].read_symbol(&mut self.bit_reader)?;
563
6.57M
                let dist_code = Self::get_copy_distance(&mut self.bit_reader, dist_symbol)?;
564
6.57M
                let dist = Self::plane_code_to_distance(width, dist_code);
565
566
6.57M
                if index < dist || num_values - index < length {
567
39
                    return Err(DecodingError::BitStreamError);
568
6.57M
                }
569
570
6.57M
                if dist == 1 {
571
3.58M
                    let value: [u8; 4] = data[(index - dist) * 4..][..4].try_into().unwrap();
572
535M
                    for i in 0..length {
573
535M
                        data[index * 4 + i * 4..][..4].copy_from_slice(&value);
574
535M
                    }
575
                } else {
576
2.98M
                    if index + length + 3 <= num_values {
577
2.98M
                        let start = (index - dist) * 4;
578
2.98M
                        data.copy_within(start..start + 16, index * 4);
579
580
2.98M
                        if length > 4 || dist < 4 {
581
93.6M
                            for i in (0..length * 4).step_by((dist * 4).min(16)).skip(1) {
582
93.6M
                                data.copy_within(start + i..start + i + 16, index * 4 + i);
583
93.6M
                            }
584
1.99k
                        }
585
                    } else {
586
41.2k
                        for i in 0..length * 4 {
587
41.2k
                            data[index * 4 + i] = data[index * 4 + i - dist * 4];
588
41.2k
                        }
589
                    }
590
591
2.98M
                    if let Some(color_cache) = huffman_info.color_cache.as_mut() {
592
381M
                        for pixel in data[index * 4..][..length * 4].chunks_exact(4) {
593
381M
                            color_cache.insert(pixel.try_into().unwrap());
594
381M
                        }
595
23.3k
                    }
596
                }
597
6.57M
                index += length;
598
            } else {
599
                //color cache, so use previously stored pixels to get this pixel
600
3.78M
                let color_cache = huffman_info
601
3.78M
                    .color_cache
602
3.78M
                    .as_mut()
603
3.78M
                    .ok_or(DecodingError::BitStreamError)?;
604
3.78M
                let color = color_cache.lookup((code - 280).into());
605
3.78M
                data[index * 4..][..4].copy_from_slice(&color);
606
3.78M
                index += 1;
607
608
3.78M
                if index < next_block_start {
609
3.74M
                    if let Some((bits, code)) = tree[GREEN].peek_symbol(&self.bit_reader) {
610
3.74M
                        if code >= 280 {
611
1.78M
                            self.bit_reader.consume(bits)?;
612
1.78M
                            data[index * 4..][..4]
613
1.78M
                                .copy_from_slice(&color_cache.lookup((code - 280).into()));
614
1.78M
                            index += 1;
615
1.96M
                        }
616
10
                    }
617
32.4k
                }
618
            }
619
        }
620
621
1.00k
        Ok(())
622
1.38k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::decode_image_data
623
624
    /// Reads color cache data from the bitstream
625
9.04k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
9.04k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
1.57k
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
1.55k
            if !(1..=11).contains(&code_bits) {
630
16
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
1.53k
            }
632
633
1.53k
            Ok(Some(code_bits))
634
        } else {
635
7.46k
            Ok(None)
636
        }
637
9.04k
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
6.95k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
6.95k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
833
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
818
            if !(1..=11).contains(&code_bits) {
630
8
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
810
            }
632
633
810
            Ok(Some(code_bits))
634
        } else {
635
6.11k
            Ok(None)
636
        }
637
6.95k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_color_cache
Line
Count
Source
625
2.09k
    fn read_color_cache(&mut self) -> Result<Option<u8>, DecodingError> {
626
2.09k
        if self.bit_reader.read_bits::<u8>(1)? == 1 {
627
742
            let code_bits = self.bit_reader.read_bits::<u8>(4)?;
628
629
736
            if !(1..=11).contains(&code_bits) {
630
8
                return Err(DecodingError::InvalidColorCacheBits(code_bits));
631
728
            }
632
633
728
            Ok(Some(code_bits))
634
        } else {
635
1.34k
            Ok(None)
636
        }
637
2.09k
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::read_color_cache
638
639
    /// Gets the copy distance from the prefix code and bitstream
640
13.4M
    fn get_copy_distance(
641
13.4M
        bit_reader: &mut BitReader<R>,
642
13.4M
        prefix_code: u16,
643
13.4M
    ) -> Result<usize, DecodingError> {
644
13.4M
        if prefix_code < 4 {
645
3.85M
            return Ok(usize::from(prefix_code + 1));
646
9.61M
        }
647
9.61M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
9.61M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
9.61M
        let bits = bit_reader.peek(extra_bits) as usize;
651
9.61M
        bit_reader.consume(extra_bits)?;
652
653
9.61M
        Ok(offset + bits + 1)
654
13.4M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
315k
    fn get_copy_distance(
641
315k
        bit_reader: &mut BitReader<R>,
642
315k
        prefix_code: u16,
643
315k
    ) -> Result<usize, DecodingError> {
644
315k
        if prefix_code < 4 {
645
188k
            return Ok(usize::from(prefix_code + 1));
646
127k
        }
647
127k
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
127k
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
127k
        let bits = bit_reader.peek(extra_bits) as usize;
651
127k
        bit_reader.consume(extra_bits)?;
652
653
126k
        Ok(offset + bits + 1)
654
315k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::get_copy_distance
Line
Count
Source
640
13.1M
    fn get_copy_distance(
641
13.1M
        bit_reader: &mut BitReader<R>,
642
13.1M
        prefix_code: u16,
643
13.1M
    ) -> Result<usize, DecodingError> {
644
13.1M
        if prefix_code < 4 {
645
3.66M
            return Ok(usize::from(prefix_code + 1));
646
9.49M
        }
647
9.49M
        let extra_bits: u8 = ((prefix_code - 2) >> 1).try_into().unwrap();
648
9.49M
        let offset = (2 + (usize::from(prefix_code) & 1)) << extra_bits;
649
650
9.49M
        let bits = bit_reader.peek(extra_bits) as usize;
651
9.49M
        bit_reader.consume(extra_bits)?;
652
653
9.49M
        Ok(offset + bits + 1)
654
13.1M
    }
Unexecuted instantiation: <image_webp::lossless::LosslessDecoder<_>>::get_copy_distance
655
656
    /// Gets distance to pixel
657
6.73M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
6.73M
        if plane_code > 120 {
659
2.95M
            plane_code - 120
660
        } else {
661
3.77M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
3.77M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
3.77M
            if dist < 1 {
665
5
                return 1;
666
3.77M
            }
667
3.77M
            dist.try_into().unwrap()
668
        }
669
6.73M
    }
<image_webp::lossless::LosslessDecoder<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
157k
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
157k
        if plane_code > 120 {
659
39.4k
            plane_code - 120
660
        } else {
661
118k
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
118k
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
118k
            if dist < 1 {
665
4
                return 1;
666
118k
            }
667
118k
            dist.try_into().unwrap()
668
        }
669
157k
    }
<image_webp::lossless::LosslessDecoder<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::plane_code_to_distance
Line
Count
Source
657
6.57M
    fn plane_code_to_distance(xsize: u16, plane_code: usize) -> usize {
658
6.57M
        if plane_code > 120 {
659
2.91M
            plane_code - 120
660
        } else {
661
3.66M
            let (xoffset, yoffset) = DISTANCE_MAP[plane_code - 1];
662
663
3.66M
            let dist = i32::from(xoffset) + i32::from(yoffset) * i32::from(xsize);
664
3.66M
            if dist < 1 {
665
1
                return 1;
666
3.66M
            }
667
3.66M
            dist.try_into().unwrap()
668
        }
669
6.57M
    }
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
95.2M
    fn get_huff_index(&self, x: u16, y: u16) -> usize {
685
95.2M
        if self.bits == 0 {
686
727k
            return 0;
687
94.5M
        }
688
94.5M
        let position =
689
94.5M
            usize::from(y >> self.bits) * usize::from(self.xsize) + usize::from(x >> self.bits);
690
94.5M
        let meta_huff_code: usize = usize::from(self.image[position]);
691
94.5M
        meta_huff_code
692
95.2M
    }
693
}
694
695
#[derive(Debug, Clone)]
696
struct ColorCache {
697
    color_cache_bits: u8,
698
    color_cache: Vec<[u8; 4]>,
699
}
700
701
impl ColorCache {
702
    #[inline(always)]
703
473M
    fn insert(&mut self, color: [u8; 4]) {
704
473M
        let [r, g, b, a] = color;
705
473M
        let color_u32 =
706
473M
            (u32::from(r) << 16) | (u32::from(g) << 8) | (u32::from(b)) | (u32::from(a) << 24);
707
473M
        let index = (0x1e35a7bdu32.wrapping_mul(color_u32)) >> (32 - self.color_cache_bits);
708
473M
        self.color_cache[index as usize] = color;
709
473M
    }
710
711
    #[inline(always)]
712
249M
    fn lookup(&self, index: usize) -> [u8; 4] {
713
249M
        self.color_cache[index]
714
249M
    }
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.99k
    const fn new(reader: R) -> Self {
726
4.99k
        Self {
727
4.99k
            reader,
728
4.99k
            buffer: 0,
729
4.99k
            nbits: 0,
730
4.99k
        }
731
4.99k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
3.82k
    const fn new(reader: R) -> Self {
726
3.82k
        Self {
727
3.82k
            reader,
728
3.82k
            buffer: 0,
729
3.82k
            nbits: 0,
730
3.82k
        }
731
3.82k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::new
Line
Count
Source
725
1.16k
    const fn new(reader: R) -> Self {
726
1.16k
        Self {
727
1.16k
            reader,
728
1.16k
            buffer: 0,
729
1.16k
            nbits: 0,
730
1.16k
        }
731
1.16k
    }
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
248M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
248M
        debug_assert!(self.nbits < 64);
739
740
248M
        let mut buf = self.reader.fill_buf()?;
741
248M
        if buf.len() >= 8 {
742
37.3M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
37.3M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
37.3M
            self.buffer |= lookahead << self.nbits;
745
37.3M
            self.nbits |= 56;
746
37.3M
        } else {
747
210M
            while !buf.is_empty() && self.nbits < 56 {
748
26.5k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
26.5k
                self.nbits += 8;
750
26.5k
                self.reader.consume(1);
751
26.5k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
248M
        Ok(())
756
248M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
224M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
224M
        debug_assert!(self.nbits < 64);
739
740
224M
        let mut buf = self.reader.fill_buf()?;
741
224M
        if buf.len() >= 8 {
742
19.7M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
19.7M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
19.7M
            self.buffer |= lookahead << self.nbits;
745
19.7M
            self.nbits |= 56;
746
19.7M
        } else {
747
205M
            while !buf.is_empty() && self.nbits < 56 {
748
20.4k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
20.4k
                self.nbits += 8;
750
20.4k
                self.reader.consume(1);
751
20.4k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
224M
        Ok(())
756
224M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::fill
Line
Count
Source
737
23.2M
    pub(crate) fn fill(&mut self) -> Result<(), DecodingError> {
738
23.2M
        debug_assert!(self.nbits < 64);
739
740
23.2M
        let mut buf = self.reader.fill_buf()?;
741
23.2M
        if buf.len() >= 8 {
742
17.5M
            let lookahead = u64::from_le_bytes(buf[..8].try_into().unwrap());
743
17.5M
            self.reader.consume(usize::from((63 - self.nbits) / 8));
744
17.5M
            self.buffer |= lookahead << self.nbits;
745
17.5M
            self.nbits |= 56;
746
17.5M
        } else {
747
5.74M
            while !buf.is_empty() && self.nbits < 56 {
748
6.09k
                self.buffer |= u64::from(buf[0]) << self.nbits;
749
6.09k
                self.nbits += 8;
750
6.09k
                self.reader.consume(1);
751
6.09k
                buf = self.reader.fill_buf()?;
752
            }
753
        }
754
755
23.2M
        Ok(())
756
23.2M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::fill
757
758
    /// Peeks at the next `num` bits in the buffer.
759
10.4M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
10.4M
        self.buffer & ((1 << num) - 1)
761
10.4M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
793k
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
793k
        self.buffer & ((1 << num) - 1)
761
793k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek
Line
Count
Source
759
9.63M
    pub(crate) const fn peek(&self, num: u8) -> u64 {
760
9.63M
        self.buffer & ((1 << num) - 1)
761
9.63M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::peek
762
763
    /// Peeks at the full buffer.
764
88.1M
    pub(crate) const fn peek_full(&self) -> u64 {
765
88.1M
        self.buffer
766
88.1M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
62.1M
    pub(crate) const fn peek_full(&self) -> u64 {
765
62.1M
        self.buffer
766
62.1M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::peek_full
Line
Count
Source
764
25.9M
    pub(crate) const fn peek_full(&self) -> u64 {
765
25.9M
        self.buffer
766
25.9M
    }
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
219M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
219M
        if self.nbits < num {
771
1.43k
            return Err(DecodingError::BitStreamError);
772
219M
        }
773
774
219M
        self.buffer >>= num;
775
219M
        self.nbits -= num;
776
219M
        Ok(())
777
219M
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
185M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
185M
        if self.nbits < num {
771
818
            return Err(DecodingError::BitStreamError);
772
185M
        }
773
774
185M
        self.buffer >>= num;
775
185M
        self.nbits -= num;
776
185M
        Ok(())
777
185M
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::consume
Line
Count
Source
769
34.6M
    pub(crate) fn consume(&mut self, num: u8) -> Result<(), DecodingError> {
770
34.6M
        if self.nbits < num {
771
621
            return Err(DecodingError::BitStreamError);
772
34.6M
        }
773
774
34.6M
        self.buffer >>= num;
775
34.6M
        self.nbits -= num;
776
34.6M
        Ok(())
777
34.6M
    }
Unexecuted instantiation: <image_webp::lossless::BitReader<_>>::consume
778
779
    /// Convenience function to read a number of bits and convert them to a type.
780
808k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
808k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
808k
        debug_assert!(num <= 32);
783
784
808k
        if self.nbits < num {
785
24.9k
            self.fill()?;
786
783k
        }
787
808k
        let value = self.peek(num) as u32;
788
808k
        self.consume(num)?;
789
790
807k
        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
808k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
353k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
353k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
353k
        debug_assert!(num <= 32);
783
784
353k
        if self.nbits < num {
785
9.48k
            self.fill()?;
786
343k
        }
787
353k
        let value = self.peek(num) as u32;
788
353k
        self.consume(num)?;
789
790
353k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
353k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
10.7k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
10.7k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
10.7k
        debug_assert!(num <= 32);
783
784
10.7k
        if self.nbits < num {
785
123
            self.fill()?;
786
10.6k
        }
787
10.7k
        let value = self.peek(num) as u32;
788
10.7k
        self.consume(num)?;
789
790
10.7k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
10.7k
    }
<image_webp::lossless::BitReader<std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
302k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
302k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
302k
        debug_assert!(num <= 32);
783
784
302k
        if self.nbits < num {
785
12.0k
            self.fill()?;
786
290k
        }
787
302k
        let value = self.peek(num) as u32;
788
302k
        self.consume(num)?;
789
790
302k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
302k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u8>
Line
Count
Source
780
86.9k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
86.9k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
86.9k
        debug_assert!(num <= 32);
783
784
86.9k
        if self.nbits < num {
785
2.27k
            self.fill()?;
786
84.6k
        }
787
86.9k
        let value = self.peek(num) as u32;
788
86.9k
        self.consume(num)?;
789
790
86.8k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
86.9k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<usize>
Line
Count
Source
780
2.11k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
2.11k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
2.11k
        debug_assert!(num <= 32);
783
784
2.11k
        if self.nbits < num {
785
13
            self.fill()?;
786
2.10k
        }
787
2.11k
        let value = self.peek(num) as u32;
788
2.11k
        self.consume(num)?;
789
790
2.10k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
2.11k
    }
<image_webp::lossless::BitReader<&mut std::io::Take<&mut std::io::cursor::Cursor<&[u8]>>>>::read_bits::<u16>
Line
Count
Source
780
52.3k
    pub(crate) fn read_bits<T: TryFrom<u32>>(&mut self, num: u8) -> Result<T, DecodingError> {
781
52.3k
        debug_assert!(num as usize <= 8 * mem::size_of::<T>());
782
52.3k
        debug_assert!(num <= 32);
783
784
52.3k
        if self.nbits < num {
785
1.00k
            self.fill()?;
786
51.3k
        }
787
52.3k
        let value = self.peek(num) as u32;
788
52.3k
        self.consume(num)?;
789
790
52.1k
        value.try_into().map_err(|_| {
791
            debug_assert!(false, "Value too large to fit in type");
792
            DecodingError::BitStreamError
793
        })
794
52.3k
    }
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
}