Coverage Report

Created: 2026-06-07 07:04

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