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, warn};
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 if img.input_colorspace.num_components() > img.components.len() {
315 if img.input_colorspace == ColorSpace::YCCK {
316 warn!("Treating YCCK colorspace as YCbCr as component length does not match");
324 img.input_colorspace = ColorSpace::YCbCr
325 } else {
326 let msg = format!(
327 " Expected {} number of components but found {}",
328 img.input_colorspace.num_components(),
329 img.components.len()
330 );
331
332 return Err(DecodeErrors::Format(msg));
333 }
334 }
335 Ok(())
336}
337
338pub fn calculate_padded_width(actual_width: usize, sub_sample: SampleRatios) -> usize {
352 match sub_sample {
353 SampleRatios::None | SampleRatios::V => {
354 ((actual_width + 7) / 8) * 8
356 }
357 SampleRatios::H | SampleRatios::HV => {
358 ((actual_width + 15) / 16) * 16
360 }
361 SampleRatios::Generic(h, _) => {
362 ((actual_width + ((h * 8).saturating_sub(1))) / (h * 8)) * (h * 8)
363 }
364 }
365}
366
367pub fn fill_default_mjpeg_tables(
376 is_progressive: bool, dc_huffman_tables: &mut [Option<HuffmanTable>],
377 ac_huffman_tables: &mut [Option<HuffmanTable>]
378) {
379 trace!("Filling with default mjpeg tables");
381
382 if dc_huffman_tables[0].is_none() {
383 dc_huffman_tables[0] = Some(
385 HuffmanTable::new_unfilled(
386 &[
387 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00
389 ],
390 &[
391 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
392 ],
393 true,
394 is_progressive
395 )
396 .unwrap()
397 );
398 }
399 if dc_huffman_tables[1].is_none() {
400 dc_huffman_tables[1] = Some(
402 HuffmanTable::new_unfilled(
403 &[
404 0x00, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
405 0x00, 0x00, 0x00, 0x00
406 ],
407 &[
408 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
409 ],
410 true,
411 is_progressive
412 )
413 .unwrap()
414 );
415 }
416 if ac_huffman_tables[0].is_none() {
417 ac_huffman_tables[0] = Some(
419 HuffmanTable::new_unfilled(
420 &[
421 0x00, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04,
422 0x00, 0x00, 0x01, 0x7D
423 ],
424 &[
425 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
426 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42,
427 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A,
428 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35,
429 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
430 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67,
431 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84,
432 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
433 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3,
434 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
435 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1,
436 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4,
437 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
438 ],
439 false,
440 is_progressive
441 )
442 .unwrap()
443 );
444 }
445 if ac_huffman_tables[1].is_none() {
446 ac_huffman_tables[1] = Some(
448 HuffmanTable::new_unfilled(
449 &[
450 0x00, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
451 0x00, 0x01, 0x02, 0x77
452 ],
453 &[
454 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
455 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1,
456 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
457 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
458 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
459 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
460 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82,
461 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96,
462 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
463 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5,
464 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
465 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
466 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
467 ],
468 false,
469 is_progressive
470 )
471 .unwrap()
472 );
473 }
474}