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/misc.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
//!Miscellaneous stuff
10
#![allow(dead_code)]
11
12
use alloc::format;
13
use core::cmp::max;
14
use core::fmt;
15
16
use zune_core::bytestream::{ZByteReader, ZReaderTrait};
17
use zune_core::colorspace::ColorSpace;
18
use zune_core::log::{trace, warn};
19
20
use crate::components::{ComponentID, SampleRatios};
21
use crate::errors::DecodeErrors;
22
use crate::huffman::HuffmanTable;
23
use crate::JpegDecoder;
24
25
/// Start of baseline DCT Huffman coding
26
27
pub const START_OF_FRAME_BASE: u16 = 0xffc0;
28
29
/// Start of another frame
30
31
pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1;
32
33
/// Start of progressive DCT encoding
34
35
pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2;
36
37
/// Start of Lossless sequential Huffman coding
38
39
pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3;
40
41
/// Start of extended sequential DCT arithmetic coding
42
43
pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9;
44
45
/// Start of Progressive DCT arithmetic coding
46
47
pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca;
48
49
/// Start of Lossless sequential Arithmetic coding
50
51
pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb;
52
53
/// Undo run length encoding of coefficients by placing them in natural order
54
#[rustfmt::skip]
55
pub const UN_ZIGZAG: [usize; 64 + 16] = [
56
     0,  1,  8, 16,  9,  2,  3, 10,
57
    17, 24, 32, 25, 18, 11,  4,  5,
58
    12, 19, 26, 33, 40, 48, 41, 34,
59
    27, 20, 13,  6,  7, 14, 21, 28,
60
    35, 42, 49, 56, 57, 50, 43, 36,
61
    29, 22, 15, 23, 30, 37, 44, 51,
62
    58, 59, 52, 45, 38, 31, 39, 46,
63
    53, 60, 61, 54, 47, 55, 62, 63,
64
    // Prevent overflowing
65
    63, 63, 63, 63, 63, 63, 63, 63,
66
    63, 63, 63, 63, 63, 63, 63, 63
67
];
68
69
/// Align data to a 16 byte boundary
70
#[repr(align(16))]
71
#[derive(Clone)]
72
73
pub struct Aligned16<T: ?Sized>(pub T);
74
75
impl<T> Default for Aligned16<T>
76
where
77
    T: Default
78
{
79
0
    fn default() -> Self {
80
0
        Aligned16(T::default())
81
0
    }
82
}
83
84
/// Align data to a 32 byte boundary
85
#[repr(align(32))]
86
#[derive(Clone)]
87
pub struct Aligned32<T: ?Sized>(pub T);
88
89
impl<T> Default for Aligned32<T>
90
where
91
    T: Default
92
{
93
0
    fn default() -> Self {
94
0
        Aligned32(T::default())
95
0
    }
96
}
97
98
/// Markers that identify different Start of Image markers
99
/// They identify the type of encoding and whether the file use lossy(DCT) or
100
/// lossless compression and whether we use Huffman or arithmetic coding schemes
101
#[derive(Eq, PartialEq, Copy, Clone)]
102
#[allow(clippy::upper_case_acronyms)]
103
pub enum SOFMarkers {
104
    /// Baseline DCT markers
105
    BaselineDct,
106
    /// SOF_1 Extended sequential DCT,Huffman coding
107
    ExtendedSequentialHuffman,
108
    /// Progressive DCT, Huffman coding
109
    ProgressiveDctHuffman,
110
    /// Lossless (sequential), huffman coding,
111
    LosslessHuffman,
112
    /// Extended sequential DEC, arithmetic coding
113
    ExtendedSequentialDctArithmetic,
114
    /// Progressive DCT, arithmetic coding,
115
    ProgressiveDctArithmetic,
116
    /// Lossless ( sequential), arithmetic coding
117
    LosslessArithmetic
118
}
119
120
impl Default for SOFMarkers {
121
6.72k
    fn default() -> Self {
122
6.72k
        Self::BaselineDct
123
6.72k
    }
124
}
125
126
impl SOFMarkers {
127
    /// Check if a certain marker is sequential DCT or not
128
129
0
    pub fn is_sequential_dct(self) -> bool {
130
0
        matches!(
131
0
            self,
132
            Self::BaselineDct
133
                | Self::ExtendedSequentialHuffman
134
                | Self::ExtendedSequentialDctArithmetic
135
        )
136
0
    }
137
138
    /// Check if a marker is a Lossles type or not
139
140
0
    pub fn is_lossless(self) -> bool {
141
0
        matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic)
142
0
    }
143
144
    /// Check whether a marker is a progressive marker or not
145
146
0
    pub fn is_progressive(self) -> bool {
147
0
        matches!(
148
0
            self,
149
            Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic
150
        )
151
0
    }
152
153
    /// Create a marker from an integer
154
155
0
    pub fn from_int(int: u16) -> Option<SOFMarkers> {
156
0
        match int {
157
0
            START_OF_FRAME_BASE => Some(Self::BaselineDct),
158
0
            START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman),
159
0
            START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic),
160
0
            START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman),
161
0
            START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic),
162
0
            START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman),
163
0
            START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic),
164
0
            _ => None
165
        }
166
0
    }
167
}
168
169
impl fmt::Debug for SOFMarkers {
170
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171
0
        match &self {
172
0
            Self::BaselineDct => write!(f, "Baseline DCT"),
173
            Self::ExtendedSequentialHuffman => {
174
0
                write!(f, "Extended sequential DCT, Huffman Coding")
175
            }
176
0
            Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"),
177
0
            Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"),
178
            Self::ExtendedSequentialDctArithmetic => {
179
0
                write!(f, "Extended sequential DCT, arithmetic coding")
180
            }
181
0
            Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"),
182
0
            Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding")
183
        }
184
0
    }
185
}
186
187
/// Read `buf.len()*2` data from the underlying `u8` buffer and convert it into
188
/// u16, and store it into `buf`
189
///
190
/// # Arguments
191
/// - reader: A mutable reference to the underlying reader.
192
/// - buf: A mutable reference to a slice containing u16's
193
#[inline]
194
0
pub fn read_u16_into<T>(reader: &mut ZByteReader<T>, buf: &mut [u16]) -> Result<(), DecodeErrors>
195
0
where
196
0
    T: ZReaderTrait
197
{
198
0
    for i in buf {
199
0
        *i = reader.get_u16_be_err()?;
200
    }
201
202
0
    Ok(())
203
0
}
204
205
/// Set up component parameters.
206
///
207
/// This modifies the components in place setting up details needed by other
208
/// parts fo the decoder.
209
5.56k
pub(crate) fn setup_component_params<T: ZReaderTrait>(
210
5.56k
    img: &mut JpegDecoder<T>
211
5.56k
) -> Result<(), DecodeErrors> {
212
5.56k
    let img_width = img.width();
213
5.56k
    let img_height = img.height();
214
215
    // in case of adobe app14 being present, zero may indicate
216
    // either CMYK if components are 4 or RGB if components are 3,
217
    // see https://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html
218
    // so since we may not know how many number of components
219
    // we have when decoding app14, we have to defer that check
220
    // until now.
221
    //
222
    // We know adobe app14 was present since it's the only one that can modify
223
    // input colorspace to be CMYK
224
5.56k
    if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK {
225
0
        img.input_colorspace = ColorSpace::RGB;
226
5.56k
    }
227
228
13.8k
    for component in &mut img.components {
229
        // compute interleaved image info
230
        // h_max contains the maximum horizontal component
231
8.29k
        img.h_max = max(img.h_max, component.horizontal_sample);
232
        // v_max contains the maximum vertical component
233
8.29k
        img.v_max = max(img.v_max, component.vertical_sample);
234
8.29k
        img.mcu_width = img.h_max * 8;
235
8.29k
        img.mcu_height = img.v_max * 8;
236
        // Number of MCU's per width
237
8.29k
        img.mcu_x = (usize::from(img.info.width) + img.mcu_width - 1) / img.mcu_width;
238
        // Number of MCU's per height
239
8.29k
        img.mcu_y = (usize::from(img.info.height) + img.mcu_height - 1) / img.mcu_height;
240
241
8.29k
        if img.h_max != 1 || img.v_max != 1 {
242
894
            // interleaved images have horizontal and vertical sampling factors
243
894
            // not equal to 1.
244
894
            img.is_interleaved = true;
245
7.39k
        }
246
        // Extract quantization tables from the arrays into components
247
8.29k
        let qt_table = *img.qt_tables[component.quantization_table_number as usize]
248
8.29k
            .as_ref()
249
8.29k
            .ok_or_else(|| {
250
7
                DecodeErrors::DqtError(format!(
251
7
                    "No quantization table for component {:?}",
252
7
                    component.component_id
253
7
                ))
254
7
            })?;
zune_jpeg::misc::setup_component_params::<alloc::vec::Vec<u8>>::{closure#0}
Line
Count
Source
249
7
            .ok_or_else(|| {
250
7
                DecodeErrors::DqtError(format!(
251
7
                    "No quantization table for component {:?}",
252
7
                    component.component_id
253
7
                ))
254
7
            })?;
Unexecuted instantiation: zune_jpeg::misc::setup_component_params::<_>::{closure#0}
255
256
8.28k
        let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max;
257
8.28k
        let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max;
258
8.28k
        component.x = x;
259
8.28k
        component.w2 = img.mcu_x * component.horizontal_sample * 8;
260
        // probably not needed. :)
261
8.28k
        component.y = y;
262
8.28k
        component.quantization_table = qt_table;
263
        // initially stride contains its horizontal sub-sampling
264
8.28k
        component.width_stride *= img.mcu_x * 8;
265
    }
266
    {
267
        // Sampling factors are one thing that suck
268
        // this fixes a specific problem with images like
269
        //
270
        // (2 2) None
271
        // (2 1) H
272
        // (2 1) H
273
        //
274
        // The images exist in the wild, the images are not meant to exist
275
        // but they do, it's just an annoying horizontal sub-sampling that
276
        // I don't know why it exists.
277
        // But it does
278
        // So we try to cope with that.
279
        // I am not sure of how to explain how to fix it, but it involved a debugger
280
        // and to much coke(the legal one)
281
        //
282
        // If this wasn't present, self.upsample_dest would have the wrong length
283
5.55k
        let mut handle_that_annoying_bug = false;
284
285
5.55k
        if let Some(y_component) = img
286
5.55k
            .components
287
5.55k
            .iter()
288
5.55k
            .find(|c| c.component_id == ComponentID::Y)
zune_jpeg::misc::setup_component_params::<alloc::vec::Vec<u8>>::{closure#1}
Line
Count
Source
288
5.55k
            .find(|c| c.component_id == ComponentID::Y)
Unexecuted instantiation: zune_jpeg::misc::setup_component_params::<_>::{closure#1}
289
        {
290
5.55k
            if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 {
291
122
                handle_that_annoying_bug = true;
292
5.43k
            }
293
0
        }
294
5.55k
        if handle_that_annoying_bug {
295
475
            for comp in &mut img.components {
296
353
                if (comp.component_id != ComponentID::Y)
297
231
                    && (comp.horizontal_sample != 1 || comp.vertical_sample != 1)
298
7
                {
299
7
                    comp.fix_an_annoying_bug = 2;
300
346
                }
301
            }
302
5.43k
        }
303
    }
304
305
5.55k
    if img.is_mjpeg {
306
1.12k
        fill_default_mjpeg_tables(
307
1.12k
            img.is_progressive,
308
1.12k
            &mut img.dc_huffman_tables,
309
1.12k
            &mut img.ac_huffman_tables
310
1.12k
        );
311
4.42k
    }
312
313
    // check colorspace matches
314
5.55k
    if img.input_colorspace.num_components() > img.components.len() {
315
0
        if img.input_colorspace == ColorSpace::YCCK {
316
            // Some images may have YCCK format (from adobe app14 segment) which is supposed to be 4 components
317
            // but only 3 components, see issue https://github.com/etemesi254/zune-image/issues/275
318
            // So this is the behaviour of other decoders
319
            // - stb_image: Treats it as YCbCr image
320
            // - libjpeg_turbo: Does not know how to parse YCCK images (transform 2 app14) so treats
321
            // it as YCbCr
322
            // So I will match that to match existing ones
323
0
            warn!("Treating YCCK colorspace as YCbCr as component length does not match");
324
0
            img.input_colorspace = ColorSpace::YCbCr
325
        } else {
326
0
            let msg = format!(
327
0
                " Expected {} number of components but found {}",
328
0
                img.input_colorspace.num_components(),
329
0
                img.components.len()
330
            );
331
332
0
            return Err(DecodeErrors::Format(msg));
333
        }
334
5.55k
    }
335
5.55k
    Ok(())
336
5.56k
}
zune_jpeg::misc::setup_component_params::<alloc::vec::Vec<u8>>
Line
Count
Source
209
5.56k
pub(crate) fn setup_component_params<T: ZReaderTrait>(
210
5.56k
    img: &mut JpegDecoder<T>
211
5.56k
) -> Result<(), DecodeErrors> {
212
5.56k
    let img_width = img.width();
213
5.56k
    let img_height = img.height();
214
215
    // in case of adobe app14 being present, zero may indicate
216
    // either CMYK if components are 4 or RGB if components are 3,
217
    // see https://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html
218
    // so since we may not know how many number of components
219
    // we have when decoding app14, we have to defer that check
220
    // until now.
221
    //
222
    // We know adobe app14 was present since it's the only one that can modify
223
    // input colorspace to be CMYK
224
5.56k
    if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK {
225
0
        img.input_colorspace = ColorSpace::RGB;
226
5.56k
    }
227
228
13.8k
    for component in &mut img.components {
229
        // compute interleaved image info
230
        // h_max contains the maximum horizontal component
231
8.29k
        img.h_max = max(img.h_max, component.horizontal_sample);
232
        // v_max contains the maximum vertical component
233
8.29k
        img.v_max = max(img.v_max, component.vertical_sample);
234
8.29k
        img.mcu_width = img.h_max * 8;
235
8.29k
        img.mcu_height = img.v_max * 8;
236
        // Number of MCU's per width
237
8.29k
        img.mcu_x = (usize::from(img.info.width) + img.mcu_width - 1) / img.mcu_width;
238
        // Number of MCU's per height
239
8.29k
        img.mcu_y = (usize::from(img.info.height) + img.mcu_height - 1) / img.mcu_height;
240
241
8.29k
        if img.h_max != 1 || img.v_max != 1 {
242
894
            // interleaved images have horizontal and vertical sampling factors
243
894
            // not equal to 1.
244
894
            img.is_interleaved = true;
245
7.39k
        }
246
        // Extract quantization tables from the arrays into components
247
8.29k
        let qt_table = *img.qt_tables[component.quantization_table_number as usize]
248
8.29k
            .as_ref()
249
8.29k
            .ok_or_else(|| {
250
                DecodeErrors::DqtError(format!(
251
                    "No quantization table for component {:?}",
252
                    component.component_id
253
                ))
254
7
            })?;
255
256
8.28k
        let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max;
257
8.28k
        let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max;
258
8.28k
        component.x = x;
259
8.28k
        component.w2 = img.mcu_x * component.horizontal_sample * 8;
260
        // probably not needed. :)
261
8.28k
        component.y = y;
262
8.28k
        component.quantization_table = qt_table;
263
        // initially stride contains its horizontal sub-sampling
264
8.28k
        component.width_stride *= img.mcu_x * 8;
265
    }
266
    {
267
        // Sampling factors are one thing that suck
268
        // this fixes a specific problem with images like
269
        //
270
        // (2 2) None
271
        // (2 1) H
272
        // (2 1) H
273
        //
274
        // The images exist in the wild, the images are not meant to exist
275
        // but they do, it's just an annoying horizontal sub-sampling that
276
        // I don't know why it exists.
277
        // But it does
278
        // So we try to cope with that.
279
        // I am not sure of how to explain how to fix it, but it involved a debugger
280
        // and to much coke(the legal one)
281
        //
282
        // If this wasn't present, self.upsample_dest would have the wrong length
283
5.55k
        let mut handle_that_annoying_bug = false;
284
285
5.55k
        if let Some(y_component) = img
286
5.55k
            .components
287
5.55k
            .iter()
288
5.55k
            .find(|c| c.component_id == ComponentID::Y)
289
        {
290
5.55k
            if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 {
291
122
                handle_that_annoying_bug = true;
292
5.43k
            }
293
0
        }
294
5.55k
        if handle_that_annoying_bug {
295
475
            for comp in &mut img.components {
296
353
                if (comp.component_id != ComponentID::Y)
297
231
                    && (comp.horizontal_sample != 1 || comp.vertical_sample != 1)
298
7
                {
299
7
                    comp.fix_an_annoying_bug = 2;
300
346
                }
301
            }
302
5.43k
        }
303
    }
304
305
5.55k
    if img.is_mjpeg {
306
1.12k
        fill_default_mjpeg_tables(
307
1.12k
            img.is_progressive,
308
1.12k
            &mut img.dc_huffman_tables,
309
1.12k
            &mut img.ac_huffman_tables
310
1.12k
        );
311
4.42k
    }
312
313
    // check colorspace matches
314
5.55k
    if img.input_colorspace.num_components() > img.components.len() {
315
0
        if img.input_colorspace == ColorSpace::YCCK {
316
            // Some images may have YCCK format (from adobe app14 segment) which is supposed to be 4 components
317
            // but only 3 components, see issue https://github.com/etemesi254/zune-image/issues/275
318
            // So this is the behaviour of other decoders
319
            // - stb_image: Treats it as YCbCr image
320
            // - libjpeg_turbo: Does not know how to parse YCCK images (transform 2 app14) so treats
321
            // it as YCbCr
322
            // So I will match that to match existing ones
323
0
            warn!("Treating YCCK colorspace as YCbCr as component length does not match");
324
0
            img.input_colorspace = ColorSpace::YCbCr
325
        } else {
326
0
            let msg = format!(
327
0
                " Expected {} number of components but found {}",
328
0
                img.input_colorspace.num_components(),
329
0
                img.components.len()
330
            );
331
332
0
            return Err(DecodeErrors::Format(msg));
333
        }
334
5.55k
    }
335
5.55k
    Ok(())
336
5.56k
}
Unexecuted instantiation: zune_jpeg::misc::setup_component_params::<_>
337
338
///Calculate number of fill bytes added to the end of a JPEG image
339
/// to fill the image
340
///
341
/// JPEG usually inserts padding bytes if the image width cannot be evenly divided into
342
/// 8 , 16 or 32 chunks depending on the sub sampling ratio. So given a sub-sampling ratio,
343
/// and the actual width, this calculates the padded bytes that were added to the image
344
///
345
///  # Params
346
/// -actual_width: Actual width of the image
347
/// -sub_sample: Sub sampling factor of the image
348
///
349
/// # Returns
350
/// The padded width, this is how long the width is for a particular image
351
1.72k
pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize {
352
1.72k
    match sub_sample {
353
        SampleRatios::None | SampleRatios::V => {
354
            // None+V sends one MCU row, so that's a simple calculation
355
1.20k
            ((actual_width + 7) / 8) * 8
356
        }
357
        SampleRatios::H | SampleRatios::HV => {
358
            // sends two rows, width can be expanded by up to 15 more bytes
359
139
            ((actual_width + 15) / 16) * 16
360
        }
361
380
        SampleRatios::Generic(h, _) => {
362
380
            ((actual_width + ((h * 8).saturating_sub(1))) / (h * 8)) * (h * 8)
363
        }
364
    }
365
1.72k
}
366
367
// https://www.loc.gov/preservation/digital/formats/fdd/fdd000063.shtml
368
// "Avery Lee, writing in the rec.video.desktop newsgroup in 2001, commented that "MJPEG, or at
369
//  least the MJPEG in AVIs having the MJPG fourcc, is restricted JPEG with a fixed -- and
370
//  *omitted* -- Huffman table. The JPEG must be YCbCr colorspace, it must be 4:2:2, and it must
371
//  use basic Huffman encoding, not arithmetic or progressive.... You can indeed extract the
372
//  MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT
373
//  segment to them, or else the decoder won't have any idea how to decompress the data.
374
//  The exact table necessary is given in the OpenDML spec.""
375
1.12k
pub fn fill_default_mjpeg_tables(
376
1.12k
    is_progressive: bool, dc_huffman_tables: &mut [Option<HuffmanTable>],
377
1.12k
    ac_huffman_tables: &mut [Option<HuffmanTable>]
378
1.12k
) {
379
    // Section K.3.3
380
    trace!("Filling with default mjpeg tables");
381
382
1.12k
    if dc_huffman_tables[0].is_none() {
383
585
        // Table K.3
384
585
        dc_huffman_tables[0] = Some(
385
585
            HuffmanTable::new_unfilled(
386
585
                &[
387
585
                    0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
388
585
                    0x00, 0x00, 0x00, 0x00
389
585
                ],
390
585
                &[
391
585
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
392
585
                ],
393
585
                true,
394
585
                is_progressive
395
585
            )
396
585
            .unwrap()
397
585
        );
398
585
    }
399
1.12k
    if dc_huffman_tables[1].is_none() {
400
1.12k
        // Table K.4
401
1.12k
        dc_huffman_tables[1] = Some(
402
1.12k
            HuffmanTable::new_unfilled(
403
1.12k
                &[
404
1.12k
                    0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
405
1.12k
                    0x00, 0x00, 0x00, 0x00
406
1.12k
                ],
407
1.12k
                &[
408
1.12k
                    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
409
1.12k
                ],
410
1.12k
                true,
411
1.12k
                is_progressive
412
1.12k
            )
413
1.12k
            .unwrap()
414
1.12k
        );
415
1.12k
    }
416
1.12k
    if ac_huffman_tables[0].is_none() {
417
580
        // Table K.5
418
580
        ac_huffman_tables[0] = Some(
419
580
            HuffmanTable::new_unfilled(
420
580
                &[
421
580
                    0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04,
422
580
                    0x00, 0x00, 0x01, 0x7D
423
580
                ],
424
580
                &[
425
580
                    0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
426
580
                    0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42,
427
580
                    0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A,
428
580
                    0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35,
429
580
                    0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
430
580
                    0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
431
580
                    0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84,
432
580
                    0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
433
580
                    0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3,
434
580
                    0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
435
580
                    0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1,
436
580
                    0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4,
437
580
                    0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
438
580
                ],
439
580
                false,
440
580
                is_progressive
441
580
            )
442
580
            .unwrap()
443
580
        );
444
580
    }
445
1.12k
    if ac_huffman_tables[1].is_none() {
446
1.12k
        // Table K.6
447
1.12k
        ac_huffman_tables[1] = Some(
448
1.12k
            HuffmanTable::new_unfilled(
449
1.12k
                &[
450
1.12k
                    0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
451
1.12k
                    0x00, 0x01, 0x02, 0x77
452
1.12k
                ],
453
1.12k
                &[
454
1.12k
                    0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
455
1.12k
                    0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1,
456
1.12k
                    0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
457
1.12k
                    0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
458
1.12k
                    0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
459
1.12k
                    0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
460
1.12k
                    0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82,
461
1.12k
                    0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
462
1.12k
                    0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
463
1.12k
                    0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
464
1.12k
                    0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
465
1.12k
                    0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
466
1.12k
                    0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
467
1.12k
                ],
468
1.12k
                false,
469
1.12k
                is_progressive
470
1.12k
            )
471
1.12k
            .unwrap()
472
1.12k
        );
473
1.12k
    }
474
1.12k
}