1#![allow(dead_code)]
11
12use alloc::format;
13use core::cmp::max;
14use core::fmt;
15
16use zune_core::bytestream::{ZByteReader, ZReaderTrait};
17use zune_core::colorspace::ColorSpace;
18use zune_core::log::trace;
19
20use crate::components::{ComponentID, SampleRatios};
21use crate::errors::DecodeErrors;
22use crate::huffman::HuffmanTable;
23use crate::JpegDecoder;
24
25pub const START_OF_FRAME_BASE: u16 = 0xffc0;
28
29pub const START_OF_FRAME_EXT_SEQ: u16 = 0xffc1;
32
33pub const START_OF_FRAME_PROG_DCT: u16 = 0xffc2;
36
37pub const START_OF_FRAME_LOS_SEQ: u16 = 0xffc3;
40
41pub const START_OF_FRAME_EXT_AR: u16 = 0xffc9;
44
45pub const START_OF_FRAME_PROG_DCT_AR: u16 = 0xffca;
48
49pub const START_OF_FRAME_LOS_SEQ_AR: u16 = 0xffcb;
52
53#[rustfmt::skip]
55pub 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 63, 63, 63, 63, 63, 63, 63, 63,
66 63, 63, 63, 63, 63, 63, 63, 63
67];
68
69#[repr(align(16))]
71#[derive(Clone)]
72
73pub struct Aligned16<T: ?Sized>(pub T);
74
75impl<T> Default for Aligned16<T>
76where
77 T: Default
78{
79 fn default() -> Self {
80 Aligned16(T::default())
81 }
82}
83
84#[repr(align(32))]
86#[derive(Clone)]
87pub struct Aligned32<T: ?Sized>(pub T);
88
89impl<T> Default for Aligned32<T>
90where
91 T: Default
92{
93 fn default() -> Self {
94 Aligned32(T::default())
95 }
96}
97
98#[derive(Eq, PartialEq, Copy, Clone)]
102#[allow(clippy::upper_case_acronyms)]
103pub enum SOFMarkers {
104 BaselineDct,
106 ExtendedSequentialHuffman,
108 ProgressiveDctHuffman,
110 LosslessHuffman,
112 ExtendedSequentialDctArithmetic,
114 ProgressiveDctArithmetic,
116 LosslessArithmetic
118}
119
120impl Default for SOFMarkers {
121 fn default() -> Self {
122 Self::BaselineDct
123 }
124}
125
126impl SOFMarkers {
127 pub fn is_sequential_dct(self) -> bool {
130 matches!(
131 self,
132 Self::BaselineDct
133 | Self::ExtendedSequentialHuffman
134 | Self::ExtendedSequentialDctArithmetic
135 )
136 }
137
138 pub fn is_lossless(self) -> bool {
141 matches!(self, Self::LosslessHuffman | Self::LosslessArithmetic)
142 }
143
144 pub fn is_progressive(self) -> bool {
147 matches!(
148 self,
149 Self::ProgressiveDctHuffman | Self::ProgressiveDctArithmetic
150 )
151 }
152
153 pub fn from_int(int: u16) -> Option<SOFMarkers> {
156 match int {
157 START_OF_FRAME_BASE => Some(Self::BaselineDct),
158 START_OF_FRAME_PROG_DCT => Some(Self::ProgressiveDctHuffman),
159 START_OF_FRAME_PROG_DCT_AR => Some(Self::ProgressiveDctArithmetic),
160 START_OF_FRAME_LOS_SEQ => Some(Self::LosslessHuffman),
161 START_OF_FRAME_LOS_SEQ_AR => Some(Self::LosslessArithmetic),
162 START_OF_FRAME_EXT_SEQ => Some(Self::ExtendedSequentialHuffman),
163 START_OF_FRAME_EXT_AR => Some(Self::ExtendedSequentialDctArithmetic),
164 _ => None
165 }
166 }
167}
168
169impl fmt::Debug for SOFMarkers {
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 match &self {
172 Self::BaselineDct => write!(f, "Baseline DCT"),
173 Self::ExtendedSequentialHuffman => {
174 write!(f, "Extended sequential DCT, Huffman Coding")
175 }
176 Self::ProgressiveDctHuffman => write!(f, "Progressive DCT,Huffman Encoding"),
177 Self::LosslessHuffman => write!(f, "Lossless (sequential) Huffman encoding"),
178 Self::ExtendedSequentialDctArithmetic => {
179 write!(f, "Extended sequential DCT, arithmetic coding")
180 }
181 Self::ProgressiveDctArithmetic => write!(f, "Progressive DCT, arithmetic coding"),
182 Self::LosslessArithmetic => write!(f, "Lossless (sequential) arithmetic coding")
183 }
184 }
185}
186
187#[inline]
194pub fn read_u16_into<T>(reader: &mut ZByteReader<T>, buf: &mut [u16]) -> Result<(), DecodeErrors>
195where
196 T: ZReaderTrait
197{
198 for i in buf {
199 *i = reader.get_u16_be_err()?;
200 }
201
202 Ok(())
203}
204
205pub(crate) fn setup_component_params<T: ZReaderTrait>(
210 img: &mut JpegDecoder<T>
211) -> Result<(), DecodeErrors> {
212 let img_width = img.width();
213 let img_height = img.height();
214
215 if img.components.len() == 3 && img.input_colorspace == ColorSpace::CMYK {
225 img.input_colorspace = ColorSpace::RGB;
226 }
227
228 for component in &mut img.components {
229 img.h_max = max(img.h_max, component.horizontal_sample);
232 img.v_max = max(img.v_max, component.vertical_sample);
234 img.mcu_width = img.h_max * 8;
235 img.mcu_height = img.v_max * 8;
236 img.mcu_x = (usize::from(img.info.width) + img.mcu_width - 1) / img.mcu_width;
238 img.mcu_y = (usize::from(img.info.height) + img.mcu_height - 1) / img.mcu_height;
240
241 if img.h_max != 1 || img.v_max != 1 {
242 img.is_interleaved = true;
245 }
246 let qt_table = *img.qt_tables[component.quantization_table_number as usize]
248 .as_ref()
249 .ok_or_else(|| {
250 DecodeErrors::DqtError(format!(
251 "No quantization table for component {:?}",
252 component.component_id
253 ))
254 })?;
255
256 let x = (usize::from(img_width) * component.horizontal_sample + img.h_max - 1) / img.h_max;
257 let y = (usize::from(img_height) * component.horizontal_sample + img.h_max - 1) / img.v_max;
258 component.x = x;
259 component.w2 = img.mcu_x * component.horizontal_sample * 8;
260 component.y = y;
262 component.quantization_table = qt_table;
263 component.width_stride *= img.mcu_x * 8;
265 }
266 {
267 let mut handle_that_annoying_bug = false;
284
285 if let Some(y_component) = img
286 .components
287 .iter()
288 .find(|c| c.component_id == ComponentID::Y)
289 {
290 if y_component.horizontal_sample == 2 || y_component.vertical_sample == 2 {
291 handle_that_annoying_bug = true;
292 }
293 }
294 if handle_that_annoying_bug {
295 for comp in &mut img.components {
296 if (comp.component_id != ComponentID::Y)
297 && (comp.horizontal_sample != 1 || comp.vertical_sample != 1)
298 {
299 comp.fix_an_annoying_bug = 2;
300 }
301 }
302 }
303 }
304
305 if img.is_mjpeg {
306 fill_default_mjpeg_tables(
307 img.is_progressive,
308 &mut img.dc_huffman_tables,
309 &mut img.ac_huffman_tables
310 );
311 }
312
313 Ok(())
314}
315
316pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize {
330 match sub_sample {
331 SampleRatios::None | SampleRatios::V => {
332 ((actual_width + 7) / 8) * 8
334 }
335 SampleRatios::H | SampleRatios::HV => {
336 ((actual_width + 15) / 16) * 16
338 }
339 }
340}
341
342pub fn fill_default_mjpeg_tables(
351 is_progressive: bool, dc_huffman_tables: &mut [Option<HuffmanTable>],
352 ac_huffman_tables: &mut [Option<HuffmanTable>]
353) {
354 trace!("Filling with default mjpeg tables");
356
357 if dc_huffman_tables[0].is_none() {
358 dc_huffman_tables[0] = Some(
360 HuffmanTable::new_unfilled(
361 &[
362 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00
364 ],
365 &[
366 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
367 ],
368 true,
369 is_progressive
370 )
371 .unwrap()
372 );
373 }
374 if dc_huffman_tables[1].is_none() {
375 dc_huffman_tables[1] = Some(
377 HuffmanTable::new_unfilled(
378 &[
379 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
380 0x00, 0x00, 0x00, 0x00
381 ],
382 &[
383 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
384 ],
385 true,
386 is_progressive
387 )
388 .unwrap()
389 );
390 }
391 if ac_huffman_tables[0].is_none() {
392 ac_huffman_tables[0] = Some(
394 HuffmanTable::new_unfilled(
395 &[
396 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04,
397 0x00, 0x00, 0x01, 0x7D
398 ],
399 &[
400 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
401 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42,
402 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A,
403 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35,
404 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
405 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
406 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84,
407 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
408 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3,
409 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
410 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1,
411 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4,
412 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
413 ],
414 false,
415 is_progressive
416 )
417 .unwrap()
418 );
419 }
420 if ac_huffman_tables[1].is_none() {
421 ac_huffman_tables[1] = Some(
423 HuffmanTable::new_unfilled(
424 &[
425 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
426 0x00, 0x01, 0x02, 0x77
427 ],
428 &[
429 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
430 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1,
431 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
432 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
433 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
434 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
435 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82,
436 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
437 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
438 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
439 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
440 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
441 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
442 ],
443 false,
444 is_progressive
445 )
446 .unwrap()
447 );
448 }
449}