Coverage Report

Created: 2026-01-10 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-jpeg-0.4.21/src/huffman.rs
Line
Count
Source
1
/*
2
 * Copyright (c) 2023.
3
 *
4
 * This software is free software;
5
 *
6
 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7
 */
8
9
//! This file contains a single struct `HuffmanTable` that
10
//! stores Huffman tables needed during `BitStream` decoding.
11
#![allow(clippy::similar_names, clippy::module_name_repetitions)]
12
13
use alloc::string::ToString;
14
15
use crate::errors::DecodeErrors;
16
17
/// Determines how many bits of lookahead we have for our bitstream decoder.
18
19
pub const HUFF_LOOKAHEAD: u8 = 9;
20
21
/// A struct which contains necessary tables for decoding a JPEG
22
/// huffman encoded bitstream
23
24
pub struct HuffmanTable {
25
    // element `[0]` of each array is unused
26
    /// largest code of length k
27
    pub(crate) maxcode: [i32; 18],
28
    /// offset for codes of length k
29
    /// Answers the question, where do code-lengths of length k end
30
    /// Element 0 is unused
31
    pub(crate) offset:  [i32; 18],
32
    /// lookup table for fast decoding
33
    ///
34
    /// top  bits above HUFF_LOOKAHEAD contain the code length.
35
    ///
36
    /// Lower (8) bits contain the symbol in order of increasing code length.
37
    pub(crate) lookup:  [i32; 1 << HUFF_LOOKAHEAD],
38
39
    /// A table which can be used to decode small AC coefficients and
40
    /// do an equivalent of receive_extend
41
    pub(crate) ac_lookup: Option<[i16; 1 << HUFF_LOOKAHEAD]>,
42
43
    /// Directly represent contents of a JPEG DHT marker
44
    ///
45
    /// \# number of symbols with codes of length `k` bits
46
    // bits[0] is unused
47
    /// Symbols in order of increasing code length
48
    pub(crate) values: [u8; 256]
49
}
50
51
impl HuffmanTable {
52
45.2k
    pub fn new(
53
45.2k
        codes: &[u8; 17], values: [u8; 256], is_dc: bool, is_progressive: bool
54
45.2k
    ) -> Result<HuffmanTable, DecodeErrors> {
55
45.2k
        let too_long_code = (i32::from(HUFF_LOOKAHEAD) + 1) << HUFF_LOOKAHEAD;
56
45.2k
        let mut p = HuffmanTable {
57
45.2k
            maxcode: [0; 18],
58
45.2k
            offset: [0; 18],
59
45.2k
            lookup: [too_long_code; 1 << HUFF_LOOKAHEAD],
60
45.2k
            values,
61
45.2k
            ac_lookup: None
62
45.2k
        };
63
64
45.2k
        p.make_derived_table(is_dc, is_progressive, codes)?;
65
66
44.9k
        Ok(p)
67
45.2k
    }
68
69
    /// Create a new huffman tables with values that aren't fixed
70
    /// used by fill_mjpeg_tables
71
3.41k
    pub fn new_unfilled(
72
3.41k
        codes: &[u8; 17], values: &[u8], is_dc: bool, is_progressive: bool
73
3.41k
    ) -> Result<HuffmanTable, DecodeErrors> {
74
3.41k
        let mut buf = [0; 256];
75
3.41k
        buf[..values.len()].copy_from_slice(values);
76
3.41k
        HuffmanTable::new(codes, buf, is_dc, is_progressive)
77
3.41k
    }
78
79
    /// Compute derived values for a Huffman table
80
    ///
81
    /// This routine performs some validation checks on the table
82
    #[allow(
83
        clippy::cast_possible_truncation,
84
        clippy::cast_possible_wrap,
85
        clippy::cast_sign_loss,
86
        clippy::too_many_lines,
87
        clippy::needless_range_loop
88
    )]
89
45.2k
    fn make_derived_table(
90
45.2k
        &mut self, is_dc: bool, _is_progressive: bool, bits: &[u8; 17]
91
45.2k
    ) -> Result<(), DecodeErrors> {
92
        // build a list of code size
93
45.2k
        let mut huff_size = [0; 257];
94
        // Huffman code lengths
95
45.2k
        let mut huff_code: [u32; 257] = [0; 257];
96
        // figure C.1 make table of Huffman code length for each symbol
97
45.2k
        let mut p = 0;
98
99
769k
        for l in 1..=16 {
100
724k
            let mut i = i32::from(bits[l]);
101
            // table overrun is checked before ,so we dont need to check
102
1.67M
            while i != 0 {
103
954k
                huff_size[p] = l as u8;
104
954k
                p += 1;
105
954k
                i -= 1;
106
954k
            }
107
        }
108
109
45.2k
        huff_size[p] = 0;
110
111
45.2k
        let num_symbols = p;
112
        // Generate the codes themselves
113
        // We also validate that the counts represent a legal Huffman code tree
114
45.2k
        let mut code = 0;
115
45.2k
        let mut si = i32::from(huff_size[0]);
116
117
45.2k
        p = 0;
118
119
422k
        while huff_size[p] != 0 {
120
1.32M
            while i32::from(huff_size[p]) == si {
121
951k
                huff_code[p] = code;
122
951k
                code += 1;
123
951k
                p += 1;
124
951k
            }
125
            // maximum code of length si, pre-shifted by 16-k bits
126
376k
            self.maxcode[si as usize] = (code << (16 - si)) as i32;
127
            // code is now 1 more than the last code used for code-length si; but
128
            // it must still fit in si bits, since no code is allowed to be all ones.
129
376k
            if (code as i32) >= (1 << si) {
130
101
                return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string()));
131
376k
            }
132
133
376k
            code <<= 1;
134
376k
            si += 1;
135
        }
136
137
        // Figure F.15 generate decoding tables for bit-sequential decoding
138
45.1k
        p = 0;
139
140
812k
        for l in 0..=16 {
141
767k
            if bits[l] == 0 {
142
489k
                // -1 if no codes of this length
143
489k
                self.maxcode[l] = -1;
144
489k
            } else {
145
277k
                // offset[l]=codes[index of 1st symbol of code length l
146
277k
                // minus minimum code of length l]
147
277k
                self.offset[l] = (p as i32) - (huff_code[p]) as i32;
148
277k
                p += usize::from(bits[l]);
149
277k
            }
150
        }
151
152
45.1k
        self.offset[17] = 0;
153
        // we ensure that decode terminates
154
45.1k
        self.maxcode[17] = 0x000F_FFFF;
155
156
        /*
157
         * Compute lookahead tables to speed up decoding.
158
         * First we set all the table entries to 0(left justified), indicating "too long";
159
         * (Note too long was set during initialization)
160
         * then we iterate through the Huffman codes that are short enough and
161
         * fill in all the entries that correspond to bit sequences starting
162
         * with that code.
163
         */
164
165
45.1k
        p = 0;
166
167
451k
        for l in 1..=HUFF_LOOKAHEAD {
168
406k
            for _ in 1..=i32::from(bits[usize::from(l)]) {
169
                // l -> Current code length,
170
                // p => Its index in self.code and self.values
171
                // Generate left justified code followed by all possible bit sequences
172
489k
                let mut look_bits = (huff_code[p] as usize) << (HUFF_LOOKAHEAD - l);
173
174
16.6M
                for _ in 0..1 << (HUFF_LOOKAHEAD - l) {
175
16.6M
                    self.lookup[look_bits] =
176
16.6M
                        (i32::from(l) << HUFF_LOOKAHEAD) | i32::from(self.values[p]);
177
16.6M
                    look_bits += 1;
178
16.6M
                }
179
180
489k
                p += 1;
181
            }
182
        }
183
        // build an ac table that does an equivalent of decode and receive_extend
184
45.1k
        if !is_dc {
185
18.8k
            let mut fast = [255; 1 << HUFF_LOOKAHEAD];
186
            // Iterate over number of symbols
187
693k
            for i in 0..num_symbols {
188
                // get code size for an item
189
693k
                let s = huff_size[i];
190
191
693k
                if s <= HUFF_LOOKAHEAD {
192
                    // if it's lower than what we need for our lookup table create the table
193
358k
                    let c = (huff_code[i] << (HUFF_LOOKAHEAD - s)) as usize;
194
358k
                    let m = (1 << (HUFF_LOOKAHEAD - s)) as usize;
195
196
9.05M
                    for j in 0..m {
197
9.05M
                        fast[c + j] = i as i16;
198
9.05M
                    }
199
334k
                }
200
            }
201
202
            // build a table that decodes both magnitude and value of small ACs in
203
            // one go.
204
18.8k
            let mut fast_ac = [0; 1 << HUFF_LOOKAHEAD];
205
206
9.65M
            for i in 0..(1 << HUFF_LOOKAHEAD) {
207
9.65M
                let fast_v = fast[i];
208
209
9.65M
                if fast_v < 255 {
210
                    // get symbol value from AC table
211
9.05M
                    let rs = self.values[fast_v as usize];
212
                    // shift by 4 to get run length
213
9.05M
                    let run = i16::from((rs >> 4) & 15);
214
                    // get magnitude bits stored at the lower 3 bits
215
9.05M
                    let mag_bits = i16::from(rs & 15);
216
                    // length of the bit we've read
217
9.05M
                    let len = i16::from(huff_size[fast_v as usize]);
218
219
9.05M
                    if mag_bits != 0 && (len + mag_bits) <= i16::from(HUFF_LOOKAHEAD) {
220
                        // magnitude code followed by receive_extend code
221
6.13M
                        let mut k = (((i as i16) << len) & ((1 << HUFF_LOOKAHEAD) - 1))
222
6.13M
                            >> (i16::from(HUFF_LOOKAHEAD) - mag_bits);
223
6.13M
                        let m = 1 << (mag_bits - 1);
224
225
6.13M
                        if k < m {
226
3.06M
                            k += (!0_i16 << mag_bits) + 1;
227
3.06M
                        };
228
229
                        // if result is small enough fit into fast ac table
230
6.13M
                        if (-128..=127).contains(&k) {
231
6.13M
                            fast_ac[i] = (k << 8) + (run << 4) + (len + mag_bits);
232
6.13M
                        }
233
2.92M
                    }
234
602k
                }
235
            }
236
18.8k
            self.ac_lookup = Some(fast_ac);
237
26.2k
        }
238
239
        // Validate symbols as being reasonable
240
        // For AC tables, we make no check, but accept all byte values 0..255
241
        // For DC tables, we require symbols to be in range 0..15
242
45.1k
        if is_dc {
243
233k
            for i in 0..num_symbols {
244
233k
                let sym = self.values[i];
245
246
233k
                if sym > 15 {
247
184
                    return Err(DecodeErrors::HuffmanDecode("Bad Huffman Table".to_string()));
248
233k
                }
249
            }
250
18.8k
        }
251
252
44.9k
        Ok(())
253
45.2k
    }
254
}