1use alloc::{collections::BTreeMap, rc::Rc, string::String, vec, vec::Vec};
2use core::cell::RefCell;
3use libm::ceil;
4
5const DCT_COS1: i32 = 4017; const DCT_SIN1: i32 = 799; const DCT_COS3: i32 = 3406; const DCT_SIN3: i32 = 2276; const DCT_COS6: i32 = 1567; const DCT_SIN6: i32 = 3784; const DCT_SQRT2: i32 = 5793; const DCT_SQRT1D2: i32 = 2896; #[derive(Debug, Clone)]
38pub struct JPEGOptions {
39 pub skip_mutation: bool,
41 pub color_transform: Option<bool>,
43 pub format_as_rgba: bool,
45 pub tolerant_decoding: bool,
47 pub max_resolution_in_mp: usize,
49 pub max_memory_usage_in_mb: usize,
51}
52impl Default for JPEGOptions {
53 fn default() -> Self {
54 Self {
55 skip_mutation: false,
56 color_transform: None,
57 format_as_rgba: true,
58 tolerant_decoding: true,
59 max_resolution_in_mp: 100,
60 max_memory_usage_in_mb: 512,
61 }
62 }
63}
64
65#[derive(Debug, Default, Clone)]
67struct JPEGComponent {
68 pub h: usize,
70 pub v: usize,
72 pub quantization_idx: usize,
74 pub blocks_per_line: usize,
76 pub blocks_per_column: usize,
78 pub blocks: Vec<Vec<Vec<i32>>>,
80 pub huffman_table_dc: Rc<RefCell<Vec<HuffmanNode>>>,
82 pub huffman_table_ac: Rc<RefCell<Vec<HuffmanNode>>>,
84 pub quantization_table: Vec<i32>,
86 pub pred: i32,
88 pub dct_zig_zag: Vec<i32>,
90}
91
92#[derive(Debug, Default, Clone)]
94struct OutComponent {
95 pub lines: Vec<Vec<u8>>,
97 pub scale_x: usize,
99 pub scale_y: usize,
101}
102
103#[derive(Debug, Default, Clone)]
105pub struct JPEGFrame {
106 pub extended: bool,
108 progressive: bool,
109 pub precision: u8,
111 scan_lines: usize,
112 samples_per_line: usize,
113 components: BTreeMap<i32, Rc<RefCell<JPEGComponent>>>,
114 components_order: Vec<i32>,
115 max_h: usize,
116 max_v: usize,
117 mcus_per_line: usize,
118 mcus_per_column: usize,
119}
120
121#[derive(Debug, Default, Clone)]
123pub struct Adobe {
124 pub version: u8,
126 pub flags0: usize,
128 pub flags1: usize,
130 pub transform_code: u8,
132}
133
134#[derive(Debug, Default, Clone)]
136pub struct JFIFVersion {
137 pub major: u8,
139 pub minor: u8,
141}
142
143#[derive(Debug, Default, Clone)]
145pub struct JFIF {
146 pub version: JFIFVersion,
148 pub density_units: usize,
150 pub x_density: usize,
152 pub y_density: usize,
154 pub thumb_width: usize,
156 pub thumb_height: usize,
158 pub thumb_data: Vec<u8>,
160}
161
162#[derive(Debug, Clone)]
165pub enum HuffmanNode {
166 Leaf(u8),
168 Node(Rc<RefCell<Vec<HuffmanNode>>>),
170}
171impl Default for HuffmanNode {
172 fn default() -> Self {
173 Self::Node(Rc::new(RefCell::new(vec![])))
174 }
175}
176
177#[derive(Debug, Default, Clone)]
180pub struct Code {
181 pub children: Rc<RefCell<Vec<HuffmanNode>>>,
183 pub index: Rc<RefCell<usize>>,
185}
186
187#[derive(Debug, Clone)]
189pub struct ParseResult {
190 data: Vec<u8>,
191 out_components: Vec<OutComponent>,
192 ready: bool,
193}
194
195#[derive(Debug, Clone)]
197pub struct Image {
198 pub width: usize,
200 pub height: usize,
202 pub exif_buffer: Option<Vec<u8>>,
204 pub data: Vec<u8>,
206 pub comments: Vec<String>,
208}
209
210#[derive(Debug)]
211struct InputReader<'a> {
212 data: &'a [u8],
213 offset: usize,
214}
215
216impl<'a> InputReader<'a> {
217 fn read_u16(&mut self) -> u16 {
218 let v = u16::from_be_bytes([self.data[self.offset], self.data[self.offset + 1]]);
219 self.offset += 2;
220 v
221 }
222
223 fn read_block(&mut self) -> Vec<u8> {
224 let len = self.read_u16() as usize;
225 let start = self.offset;
226 let end = start + len - 2;
227 self.offset = end;
228 self.data[start..end].to_vec()
229 }
230}
231
232pub fn decode_jpeg_data(
242 jpeg_data: &[u8],
243 user_opts: Option<JPEGOptions>,
244 jpeg_tables: Option<&[u8]>,
245) -> Image {
246 let mut reader = JpegStreamReader::new(user_opts);
247 reader.reset_max_memory_usage(reader.max_memory_usage_in_mb * 1024 * 1024);
250 if let Some(jpeg_tables) = jpeg_tables {
251 reader.parse(jpeg_tables);
252 }
253 reader.parse(jpeg_data);
254
255 reader.get_image_data()
256}
257
258pub fn jpeg_decoder(buffer: &[u8], jpeg_tables: Option<&[u8]>) -> Vec<u8> {
267 decode_jpeg_data(
268 buffer,
269 Some(JPEGOptions { skip_mutation: true, ..Default::default() }),
270 jpeg_tables,
271 )
272 .data
273}
274
275#[derive(Debug)]
277pub struct JpegStreamReader {
278 color_transform: Option<bool>,
279 skip_mutation: bool,
280 format_as_rgba: bool,
281 tolerant_decoding: bool,
282 max_resolution_in_mp: usize,
284 max_memory_usage_in_mb: usize,
286 quantization_tables: Vec<Vec<i32>>,
287 huffman_tables_ac: Vec<HuffmanNode>,
288 huffman_tables_dc: Vec<HuffmanNode>,
289 total_bytes_allocated: RefCell<usize>,
290 max_memory_usage_bytes: usize,
291 width: usize,
292 height: usize,
293 reset_interval: usize,
294 comments: Vec<String>,
295 adobe: Option<Adobe>,
296 jfif: Option<JFIF>,
297 exif_buffer: Option<Vec<u8>>,
298 frames: Vec<JPEGFrame>,
299 dct_zig_zag: Vec<i32>,
300}
301impl JpegStreamReader {
302 pub fn new(opts: Option<JPEGOptions>) -> Self {
304 let opts = opts.unwrap_or_default();
305 Self {
306 color_transform: opts.color_transform,
307 skip_mutation: opts.skip_mutation,
308 format_as_rgba: opts.format_as_rgba,
309 tolerant_decoding: opts.tolerant_decoding,
310 max_resolution_in_mp: opts.max_resolution_in_mp,
311 max_memory_usage_in_mb: opts.max_memory_usage_in_mb,
312 quantization_tables: vec![],
313 huffman_tables_ac: vec![],
314 huffman_tables_dc: vec![],
315 total_bytes_allocated: 0.into(),
316 max_memory_usage_bytes: 0,
317 width: 0,
318 height: 0,
319 reset_interval: 0,
320 comments: vec![],
321 adobe: None,
322 jfif: None,
323 exif_buffer: None,
324 frames: vec![],
325 dct_zig_zag: vec![
326 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41,
327 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23,
328 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
329 ],
330 }
331 }
332
333 pub fn reset_frames(&mut self) {
335 self.frames = vec![];
336 }
337
338 pub fn reset_max_memory_usage(&mut self, max_memory_usage_bytes: usize) {
343 self.total_bytes_allocated = 0.into();
344 self.max_memory_usage_bytes = max_memory_usage_bytes;
345 }
346
347 pub fn get_image_data(&mut self) -> Image {
352 let channels = if self.format_as_rgba { 4 } else { 3 };
353 let ParseResult { data, out_components, ready } = self.get_result();
354 let bytes_needed = self.width * self.height * channels;
355 self.request_memory_allocation(bytes_needed);
356
357 if ready {
358 return Image {
359 width: self.width,
360 height: self.height,
361 exif_buffer: self.exif_buffer.clone(),
362 data,
363 comments: self.comments.clone(),
364 };
365 }
366 let mut image = Image {
367 width: self.width,
368 height: self.height,
369 exif_buffer: self.exif_buffer.clone(),
370 data: vec![0; bytes_needed],
371 comments: self.comments.clone(),
372 };
373
374 let image_data_array = &mut image.data;
375 let mut i = 0;
376 let mut j = 0;
377 match out_components.len() {
378 1 => {
379 for _ in 0..self.height {
380 for _ in 0..self.width {
381 let _y = data[i];
382 i += 1;
383
384 image_data_array[j] = _y;
385 j += 1;
386 image_data_array[j] = _y;
387 j += 1;
388 image_data_array[j] = _y;
389 j += 1;
390 if self.format_as_rgba {
391 image_data_array[j] = 255;
392 j += 1;
393 }
394 }
395 }
396 }
397 3 => {
398 for _ in 0..self.height {
399 for _ in 0..self.width {
400 let _r = data[i];
401 i += 1;
402 let _g = data[i];
403 i += 1;
404 let _b = data[i];
405 i += 1;
406
407 image_data_array[j] = _r;
408 j += 1;
409 image_data_array[j] = _g;
410 j += 1;
411 image_data_array[j] = _b;
412 j += 1;
413 if self.format_as_rgba {
414 image_data_array[j] = 255;
415 j += 1;
416 }
417 }
418 }
419 }
420 4 => {
421 for _ in 0..self.height {
422 for _ in 0..self.width {
423 let _c = data[i] as f64;
424 i += 1;
425 let _m = data[i] as f64;
426 i += 1;
427 let _y = data[i] as f64;
428 i += 1;
429 let _k = data[i] as f64;
430 i += 1;
431
432 let _r = 255 - clamp_to_8bit(ceil(_c * (1. - _k / 255.) + _k));
433 let _g = 255 - clamp_to_8bit(ceil(_m * (1. - _k / 255.) + _k));
434 let _b = 255 - clamp_to_8bit(ceil(_y * (1. - _k / 255.) + _k));
435
436 image_data_array[j] = _r as u8;
437 j += 1;
438 image_data_array[j] = _g as u8;
439 j += 1;
440 image_data_array[j] = _b as u8;
441 j += 1;
442 if self.format_as_rgba {
443 image_data_array[j] = 255;
444 j += 1;
445 }
446 }
447 }
448 }
449 _ => {
450 panic!("Unsupported color mode");
451 }
452 }
453
454 image
455 }
456
457 pub fn parse(&mut self, data: &[u8]) {
462 let max_resolution_in_pixels = self.max_resolution_in_mp * 1000 * 1000;
463 let mut reader = InputReader { data, offset: 0 };
464
465 let mut file_marker = reader.read_u16();
466 let mut malformed_data_offset: isize = -1;
467 if file_marker != 0xffd8 {
468 panic!("SOI not found");
470 }
471
472 file_marker = reader.read_u16();
473 while file_marker != 0xffd9 {
474 match file_marker {
476 0xff00 => {}
477 0xffe0 | 0xffe1 | 0xffe2 | 0xffe3 | 0xffe4 | 0xffe5 | 0xffe6 | 0xffe7 | 0xffe8 | 0xffe9 | 0xffea | 0xffeb | 0xffec | 0xffed | 0xffee | 0xffef | 0xfffe => {
494 let app_data = reader.read_block();
496
497 if file_marker == 0xfffe {
498 let comment = String::from_utf8_lossy(&app_data);
499 self.comments.push(comment.into());
500 }
501
502 if (file_marker == 0xffe0) && (
503 app_data[0] == 0x4a &&
504 app_data[1] == 0x46 &&
505 app_data[2] == 0x49 &&
506 app_data[3] == 0x46 &&
507 app_data[4] == 0
508 ) {
509 self.jfif = Some(JFIF {
511 version: JFIFVersion { major: app_data[5], minor: app_data[6] },
512 density_units: app_data[7] as usize,
513 x_density: ((app_data[8] as usize) << 8) | app_data[9] as usize,
514 y_density: ((app_data[10] as usize) << 8) | app_data[11] as usize,
515 thumb_width: app_data[12]as usize,
516 thumb_height: app_data[13]as usize,
517 thumb_data: app_data[14..14 + 3 * app_data[12] as usize * app_data[13] as usize].to_vec(),
518 });
519 }
520 if (file_marker == 0xffe1) && (
522 app_data[0] == 0x45 &&
523 app_data[1] == 0x78 &&
524 app_data[2] == 0x69 &&
525 app_data[3] == 0x66 &&
526 app_data[4] == 0
527 ) {
528 self.exif_buffer = Some(app_data[5..].to_vec());
530 }
531
532 if (file_marker == 0xffee) && (
533 app_data[0] == 0x41 &&
534 app_data[1] == 0x64 &&
535 app_data[2] == 0x6f &&
536 app_data[3] == 0x62 &&
537 app_data[4] == 0x65 &&
538 app_data[5] == 0
539 ) {
540 self.adobe = Some(Adobe {
542 version: app_data[6],
543 flags0: ((app_data[7] as usize) << 8) | app_data[8] as usize,
544 flags1: ((app_data[9] as usize) << 8) | app_data[10] as usize,
545 transform_code: app_data[11],
546 });
547 }
548 }
549
550 0xffdb => {
551 let quantization_tables_length = reader.read_u16() as usize;
553 let quantization_tables_end = quantization_tables_length + reader.offset - 2;
554 while reader.offset < quantization_tables_end {
555 let quantization_table_spec = data[reader.offset] as usize;
556 reader.offset += 1;
557 self.request_memory_allocation(64 * 4);
558 let mut table_data: Vec<i32> = vec![0; 64];
559 if quantization_table_spec >> 4 == 0 {
560 for j in 0..64 {
562 let z = self.dct_zig_zag[j] as usize;
563 table_data[z] = data[reader.offset] as i32;
564 reader.offset += 1;
565 }
566 } else if quantization_table_spec >> 4 == 1 {
567 for j in 0..64 {
569 let z = self.dct_zig_zag[j] as usize;
570 table_data[z] = reader.read_u16() as i32;
571 }
572 } else {
573 panic!("DQT: invalid table spec");
574 }
575 let quantize_table_idx = quantization_table_spec & 15;
576 ensure_len(&mut self.quantization_tables, quantize_table_idx, vec![]);
577 self.quantization_tables[quantization_table_spec & 15] = table_data;
578 }
579 }
580
581 0xffc0..=0xffc2 => {
584 reader.read_u16(); let precision = data[reader.offset];
587 reader.offset += 1;
588 let mut frame = JPEGFrame {
589 extended: file_marker == 0xffc1,
590 progressive: file_marker == 0xffc2,
591 precision,
592 scan_lines: reader.read_u16() as usize,
593 samples_per_line: reader.read_u16() as usize,
594 components: BTreeMap::default(),
595 components_order: vec![],
596 max_h: 0,
597 max_v: 0,
598 mcus_per_line: 0,
599 mcus_per_column: 0,
600 };
601
602 let pixels_in_frame = frame.scan_lines * frame.samples_per_line;
603 if pixels_in_frame > max_resolution_in_pixels {
604 let exceeded_amount = ceil((pixels_in_frame as f64 - max_resolution_in_pixels as f64) / 1e6);
605 panic!("max_resolution_in_mp limit exceeded by {exceeded_amount}MP");
606 }
607
608 let components_count = data[reader.offset];
609 reader.offset += 1;
610 for _ in 0..components_count {
611 let component_id = data[reader.offset] as i32;
612 let h = data[reader.offset + 1] as usize >> 4;
613 let v = data[reader.offset + 1] as usize & 15;
614 let q_id = data[reader.offset + 2];
615
616 frame.components_order.push(component_id);
621 frame.components.insert(component_id, Rc::new(RefCell::new(JPEGComponent {
622 h,
623 v,
624 quantization_idx: q_id as usize,
625 blocks_per_line: 0,
626 blocks_per_column: 0,
627 blocks: vec![],
628 huffman_table_dc: Rc::new(RefCell::new(vec![])),
629 huffman_table_ac: Rc::new(RefCell::new(vec![])),
630 pred: 0,
631 quantization_table: vec![],
632 dct_zig_zag: self.dct_zig_zag.clone(),
633 })));
634 reader.offset += 3;
635 }
636 self.prepare_components(&mut frame);
637 self.frames.push(frame);
638 }
639
640 0xffc4 => {
641 let huffman_length = reader.read_u16() as usize;
643 let mut i: usize = 2;
644 while i < huffman_length {
645 let huffman_table_spec = data[reader.offset] as usize;
646 reader.offset += 1;
647 let mut code_lengths: Vec<u8> = vec![0; 16];
648 let mut code_length_sum: usize = 0;
649 let mut j = 0;
650 while j < 16 {
651 code_lengths[j] = data[reader.offset];
652 code_length_sum += code_lengths[j] as usize;
653 j += 1;
654 reader.offset += 1;
655 }
656 self.request_memory_allocation(16 + code_length_sum);
657 let mut huffman_values: Vec<u8> = vec![0; code_length_sum];
658 j = 0;
659 while j < code_length_sum {
660 huffman_values[j] = data[reader.offset];
661 j += 1;
662 reader.offset += 1;
663 }
664 i += 17 + code_length_sum;
665
666 let huffman_table = if huffman_table_spec >> 4 == 0 { &mut self.huffman_tables_dc } else { &mut self.huffman_tables_ac };
667 let index = huffman_table_spec & 15;
668 ensure_len(huffman_table, index, HuffmanNode::Leaf(0));
669 huffman_table[
670 index
671 ] = HuffmanNode::Node(Rc::new(RefCell::new(build_huffman_table(&code_lengths, &huffman_values))));
672 }
673 }
674
675 0xffdd => { reader.read_u16(); self.reset_interval = reader.read_u16() as usize;
678 }
679
680 0xffdc => { reader.read_u16(); reader.read_u16(); }
684
685 0xffda => {
686 reader.read_u16(); let selectors_count = data[reader.offset];
689 reader.offset += 1;
690 let mut components: Vec<Rc<RefCell<JPEGComponent>>> = vec![];
691 let frame = &mut self.frames[0];
692 for _ in 0..selectors_count {
693 let component = frame.components.get(&(data[reader.offset] as i32)).unwrap();
694 reader.offset += 1;
695 let table_spec = data[reader.offset] as usize;
696 reader.offset += 1;
697 ensure_len(&mut self.huffman_tables_dc, table_spec >> 4, HuffmanNode::Leaf(0));
698 component.borrow_mut().huffman_table_dc = match &self.huffman_tables_dc[table_spec >> 4] {
699 HuffmanNode::Node(nodes) => nodes.clone(),
700 HuffmanNode::Leaf(_) => Rc::new(RefCell::new(vec![])),
701 };
702 ensure_len(&mut self.huffman_tables_ac, table_spec & 15, HuffmanNode::Leaf(0));
703 component.borrow_mut().huffman_table_ac = match &self.huffman_tables_ac[table_spec & 15] {
704 HuffmanNode::Node(nodes) => nodes.clone(),
705 HuffmanNode::Leaf(_) => Rc::new(RefCell::new(vec![])),
706 };
707 components.push(component.clone());
708 }
709 let spectral_start = data[reader.offset] as usize;
710 reader.offset += 1;
711 let spectral_end = data[reader.offset] as usize;
712 reader.offset += 1;
713 let successive_approximation = data[reader.offset];
714 reader.offset += 1;
715 let processed = decode_scan(
716 data,
717 reader.offset,
718 frame,
719 &components,
720 self.reset_interval,
721 spectral_start,
722 spectral_end,
723 (successive_approximation >> 4) as usize,
724 (successive_approximation & 15) as i32,
725 self.tolerant_decoding,
726 );
727 reader.offset += processed;
728 }
729
730 0xffff => { if data[reader.offset] != 0xff {
732 reader.offset -= 1;
734 }
735 }
736
737 _ => {
738 if data[reader.offset - 3] == 0xff && data[reader.offset - 2] >= 0xc0 && data[reader.offset - 2] <= 0xfe {
739 reader.offset -= 3;
742 } else if file_marker == 0xe0 || file_marker == 0xe1 {
743 if malformed_data_offset != -1 {
746 panic!(
747 "first unknown JPEG marker at offset {malformed_data_offset}, second unknown JPEG marker {file_marker} at offset {}", reader.offset - 1
748 );
749 }
750 malformed_data_offset = reader.offset as isize - 1;
751 let next_offset = reader.read_u16() as usize;
752 if data[reader.offset + next_offset - 2] == 0xff {
753 reader.offset += next_offset - 2;
754 }
755 } else {
756 panic!("unknown JPEG marker {file_marker}");
757 }
758 }
759 }
760 file_marker = reader.read_u16();
761 }
762 }
763
764 fn request_memory_allocation(&self, increase_amount: usize) {
769 let total_memory_impact_bytes = *self.total_bytes_allocated.borrow() + increase_amount;
770 if total_memory_impact_bytes > self.max_memory_usage_bytes {
771 let exceeded_amount = (total_memory_impact_bytes - self.max_memory_usage_bytes)
772 .div_ceil(1024)
773 .div_ceil(1024);
774 panic!("max_memory_usage_in_mb limit exceeded by at least ${exceeded_amount}MB");
775 }
776
777 *self.total_bytes_allocated.borrow_mut() = total_memory_impact_bytes;
778 }
779
780 fn get_result(&mut self) -> ParseResult {
785 if self.frames.is_empty() {
786 panic!("no frames were decoded");
787 } else if self.frames.len() > 1 {
788 panic!("more than one frame is not supported");
789 }
790
791 for i in 0..self.frames.len() {
793 let cp = &mut self.frames[i].components;
794 for comp in cp.values_mut() {
795 let index = comp.borrow().quantization_idx;
796 comp.borrow_mut().quantization_table = self.quantization_tables[index].clone();
797 }
798 }
799
800 let frame = &self.frames[0];
801 let JPEGFrame { components, components_order, .. } = frame;
802 let mut out_components: Vec<OutComponent> = vec![];
803 self.width = frame.samples_per_line;
804 let width = self.width;
805 self.height = frame.scan_lines;
806 let height = self.height;
807 let scale_x = self.width / width;
808 let scale_y = self.height / height;
809
810 for index in components_order.iter() {
811 let component = components.get(index).unwrap().borrow();
812 out_components.push(OutComponent {
813 lines: self.build_component_data(&component),
814 scale_x: component.h / frame.max_h,
815 scale_y: component.v / frame.max_v,
816 });
817 }
818
819 let mut offset = 0;
820 let mut ready = false;
821 let data_length = width * height * out_components.len();
822 self.request_memory_allocation(data_length);
823 let mut data = vec![0; data_length];
824
825 let mut no_mutation = || {
827 ready = true;
828 let mut oi = 0;
829 for y in 0..height {
830 for x in 0..width {
831 for component in &out_components {
832 data[oi] = component.lines[y * component.scale_y][x * component.scale_x];
833 oi += 1;
834 }
835 }
836 }
837 };
838
839 if self.skip_mutation {
840 no_mutation();
841 return ParseResult { data, ready, out_components };
842 }
843
844 match out_components.len() {
845 1 => {
846 let component1 = &out_components[0];
847 for y in 0..height {
848 let component1_line = &component1.lines[y * component1.scale_y * scale_y];
849 for x in 0..width {
850 let _y = component1_line[x * component1.scale_x * scale_x];
851
852 data[offset] = _y;
853 offset += 1;
854 }
855 }
856 }
857 2 => {
858 let component1 = &out_components[0];
860 let component2 = &out_components[1];
861 for y in 0..height {
862 let component1_line = &component1.lines[y * component1.scale_y * scale_y];
863 let component2_line = &component2.lines[y * component2.scale_y * scale_y];
864 for x in 0..width {
865 let mut _y = component1_line[x * component1.scale_x * scale_x];
866 data[offset] = _y;
867 offset += 1;
868 _y = component2_line[x * component2.scale_x * scale_x];
869 data[offset] = _y;
870 offset += 1;
871 }
872 }
873 }
874 3 => {
875 let mut color_transform = true;
877 if let Some(self_transform) = self.color_transform {
878 color_transform = self_transform
879 }
880
881 let component1 = &out_components[0];
882 let component2 = &out_components[1];
883 let component3 = &out_components[2];
884 for y in 0..height {
885 let component1_line = &component1.lines[y * component1.scale_y * scale_y];
886 let component2_line = &component2.lines[y * component2.scale_y * scale_y];
887 let component3_line = &component3.lines[y * component3.scale_y * scale_y];
888 for x in 0..width {
889 let _r;
890 let _g;
891 let _b;
892 if !color_transform {
893 _r = component1_line[x * component1.scale_x * scale_x];
894 _g = component2_line[x * component2.scale_x * scale_x];
895 _b = component3_line[x * component3.scale_x * scale_x];
896 } else {
897 let _y = component1_line[x * component1.scale_x * scale_x] as f64;
898 let _cb = component2_line[x * component2.scale_x * scale_x] as f64;
899 let _cr: f64 = component3_line[x * component3.scale_x * scale_x] as f64;
900
901 _r = clamp_to_8bit(_y + 1.402 * (_cr - 128.)) as u8;
902 _g = clamp_to_8bit(
903 _y - 0.3441363 * (_cb - 128.) - 0.71413636 * (_cr - 128.),
904 ) as u8;
905 _b = clamp_to_8bit(_y + 1.772 * (_cb - 128.)) as u8;
906 }
907
908 data[offset] = _r;
909 offset += 1;
910 data[offset] = _g;
911 offset += 1;
912 data[offset] = _b;
913 offset += 1;
914 }
915 }
916 }
917 4 => {
918 if self.adobe.is_none() {
919 no_mutation();
920 } else {
921 let mut color_transform = false;
923 let adobe = self.adobe.clone().unwrap_or_default();
924
925 if adobe.transform_code != 0 {
926 color_transform = true;
927 } else if let Some(self_transform) = self.color_transform {
928 color_transform = self_transform
929 }
930 let component1 = &out_components[0];
931 let component2 = &out_components[1];
932 let component3 = &out_components[2];
933 let component4 = &out_components[3];
934 for y in 0..height {
935 let component1_line = &component1.lines[y * component1.scale_y * scale_y];
936 let component2_line = &component2.lines[y * component2.scale_y * scale_y];
937 let component3_line = &component3.lines[y * component3.scale_y * scale_y];
938 let component4_line = &component4.lines[y * component4.scale_y * scale_y];
939 for x in 0..width {
940 let _c;
941 let _m;
942 let _ye;
943 let _k;
944 if !color_transform {
945 _c = component1_line[x * component1.scale_x * scale_x];
946 _m = component2_line[x * component2.scale_x * scale_x];
947 _ye = component3_line[x * component3.scale_x * scale_x];
948 _k = component4_line[x * component4.scale_x * scale_x];
949 } else {
950 let _y = component1_line[x * component1.scale_x * scale_x] as f64;
951 let _cb = component2_line[x * component2.scale_x * scale_x] as f64;
952 let _cr = component3_line[x * component3.scale_x * scale_x] as f64;
953 _k = component4_line[x * component4.scale_x * scale_x];
954
955 _c = 255 - clamp_to_8bit(_y + 1.402 * (_cr - 128.)) as u8;
956 _m = 255
957 - clamp_to_8bit(
958 _y - 0.3441363 * (_cb - 128.) - 0.71413636 * (_cr - 128.),
959 ) as u8;
960 _ye = 255 - clamp_to_8bit(_y + 1.772 * (_cb - 128.)) as u8;
961 }
962 data[offset] = 255 - _c;
963 offset += 1;
964 data[offset] = 255 - _m;
965 offset += 1;
966 data[offset] = 255 - _ye;
967 offset += 1;
968 data[offset] = 255 - _k;
969 offset += 1;
970 }
971 }
972 }
973 }
974 _ => panic!("Unsupported color mode"),
975 }
976
977 ParseResult { data, out_components, ready }
978 }
979
980 fn build_component_data(&self, component: &JPEGComponent) -> Vec<Vec<u8>> {
989 let mut lines = vec![];
990 let blocks_per_line = component.blocks_per_line;
991 let blocks_per_column = component.blocks_per_column;
992 let samples_per_line = blocks_per_line << 3;
993 let mut _r: Vec<i32> = vec![0; 64];
995 let mut r: Vec<u8> = vec![0; 64];
996
997 self.request_memory_allocation(samples_per_line * blocks_per_column * 8);
998
999 for block_row in 0..blocks_per_column {
1000 let scan_line = block_row << 3;
1001 for _ in 0..8 {
1002 lines.push(vec![0; samples_per_line]);
1003 }
1004 for block_col in 0..blocks_per_line {
1005 quantize_and_inverse(
1006 component,
1007 &component.blocks[block_row][block_col],
1008 &mut r,
1009 &mut _r,
1010 );
1011
1012 let mut offset = 0;
1013 let sample = block_col << 3;
1014 for j in 0..8 {
1015 let line = &mut lines[scan_line + j];
1016 for i in 0..8 {
1017 line[sample + i] = r[offset];
1018 offset += 1;
1019 }
1020 }
1021 }
1022 }
1023
1024 lines
1025 }
1026
1027 fn prepare_components(&self, frame: &mut JPEGFrame) {
1032 let mut max_h = 1;
1035 let mut max_v = 1;
1036 for component in frame.components.values() {
1037 let component = component.borrow();
1038 if max_h < component.h {
1039 max_h = component.h;
1040 }
1041 if max_v < component.v {
1042 max_v = component.v;
1043 }
1044 }
1045 let mcus_per_line = frame.samples_per_line.div_ceil(8).div_ceil(max_h);
1046 let mcus_per_column = frame.scan_lines.div_ceil(8).div_ceil(max_v);
1047 for component in frame.components.values_mut() {
1048 let component = &mut component.borrow_mut();
1049 let blocks_per_line =
1050 ((frame.samples_per_line.div_ceil(8)) * component.h).div_ceil(max_h);
1051 let blocks_per_column = ((frame.scan_lines.div_ceil(8)) * component.v).div_ceil(max_v);
1052 let blocks_per_line_for_mcu = mcus_per_line * component.h;
1053 let blocks_per_column_for_mcu = mcus_per_column * component.v;
1054 let blocks_to_allocate = blocks_per_column_for_mcu * blocks_per_line_for_mcu;
1055 let mut blocks = vec![];
1056
1057 self.request_memory_allocation(blocks_to_allocate * 256);
1059
1060 for _ in 0..blocks_per_column_for_mcu {
1061 let mut row = vec![];
1062 for _ in 0..blocks_per_line_for_mcu {
1063 row.push(vec![0; 64]);
1064 }
1065 blocks.push(row);
1066 }
1067 component.blocks_per_line = blocks_per_line;
1068 component.blocks_per_column = blocks_per_column;
1069 component.blocks = blocks;
1070 }
1071 frame.max_h = max_h;
1072 frame.max_v = max_v;
1073 frame.mcus_per_line = mcus_per_line;
1074 frame.mcus_per_column = mcus_per_column;
1075 }
1076}
1077
1078fn build_huffman_table(code_lengths: &[u8], values: &[u8]) -> Vec<HuffmanNode> {
1087 let mut k = 0;
1088 let mut code: Vec<Code> = vec![];
1089 let mut length = 16;
1090 while length > 0 && code_lengths[length - 1] == 0 {
1092 length -= 1;
1093 }
1094
1095 let root = Code::default();
1096 code.push(root.clone());
1097 let mut p = root.clone();
1098 let mut q: Code;
1099
1100 for (i, code_length) in code_lengths.iter().enumerate().take(length) {
1101 for _ in 0..(*code_length as usize) {
1102 p = code.pop().unwrap();
1103 let index = *p.index.borrow();
1104 ensure_len(&mut p.children.borrow_mut(), index, HuffmanNode::default());
1105 p.children.borrow_mut()[index] = HuffmanNode::Leaf(values[k]);
1106 while *p.index.borrow() > 0 {
1107 if code.is_empty() {
1108 panic!("Could not recreate Huffman Table");
1109 }
1110 p = code.pop().unwrap();
1111 }
1112 *p.index.borrow_mut() += 1;
1113 code.push(p.clone());
1114 while code.len() <= i {
1115 q = Code::default();
1116 code.push(q.clone());
1117 let index = *p.index.borrow();
1118 ensure_len(
1119 &mut p.children.borrow_mut(),
1120 index,
1121 HuffmanNode::Node(Rc::new(RefCell::new(vec![]))),
1122 );
1123 p.children.borrow_mut()[index] = HuffmanNode::Node(q.children.clone());
1124 p = q;
1125 }
1126 k += 1;
1127 }
1128 if i + 1 < length {
1129 q = Code::default();
1131 code.push(q.clone());
1132 let index = *p.index.borrow();
1133 ensure_len(
1134 &mut p.children.borrow_mut(),
1135 index,
1136 HuffmanNode::Node(Rc::new(RefCell::new(vec![]))),
1137 );
1138 p.children.borrow_mut()[index] = HuffmanNode::Node(q.children.clone());
1139 p = q;
1140 }
1141 }
1142
1143 root.children.borrow_mut().clone()
1144}
1145
1146fn read_bit(decode_scan: &mut DecodeScan) -> usize {
1149 if decode_scan.bits_count > 0 {
1150 decode_scan.bits_count -= 1;
1151 return (decode_scan.bits_data >> decode_scan.bits_count) & 1;
1152 }
1153 decode_scan.bits_data = decode_scan.data[decode_scan.offset] as usize;
1154 decode_scan.offset += 1;
1155 if decode_scan.bits_data == 0xff {
1156 let _next_byte = decode_scan.data[decode_scan.offset];
1157 decode_scan.offset += 1;
1158 }
1163 decode_scan.bits_count = 7;
1164 decode_scan.bits_data >> 7
1165}
1166
1167fn decode_huffman(decode_scan: &mut DecodeScan, tree: Rc<RefCell<Vec<HuffmanNode>>>) -> u8 {
1176 let mut node = tree;
1177 loop {
1178 let bit = read_bit(decode_scan);
1179 if let Some(n) = node.clone().borrow().get(bit) {
1180 node = match n {
1181 HuffmanNode::Node(children) => children.clone(),
1182 HuffmanNode::Leaf(value) => {
1183 return *value;
1184 }
1185 };
1186 } else {
1187 break;
1188 }
1189 }
1190 0
1191}
1192
1193fn receive(decode_scan: &mut DecodeScan, mut length: usize) -> usize {
1202 let mut n: usize = 0;
1203 while length > 0 {
1204 let bit = read_bit(decode_scan);
1205 n = (n << 1) | bit;
1206 length -= 1;
1207 }
1208
1209 n
1210}
1211
1212fn receive_and_extend(decode_scan: &mut DecodeScan, length: usize) -> isize {
1221 let n = receive(decode_scan, length) as isize;
1222 if n >= 1 << (length - 1) { n } else { n + (-1 << length) + 1 }
1223}
1224
1225fn decode_baseline(
1233 decode_scan: &mut DecodeScan,
1234 component: &mut JPEGComponent,
1235 block_row: usize,
1236 block_col: usize,
1237) {
1238 let t = decode_huffman(decode_scan, component.huffman_table_dc.clone());
1239 let diff = if t == 0 { 0 } else { receive_and_extend(decode_scan, t as usize) };
1240 component.pred += diff as i32;
1241 component.blocks[block_row][block_col][0] = component.pred;
1242 let mut k = 1;
1243 while k < 64 {
1244 let rs = decode_huffman(decode_scan, component.huffman_table_ac.clone());
1245 let s = rs & 15;
1246 let r = rs >> 4;
1247 if s == 0 {
1248 if r < 15 {
1249 break;
1250 }
1251 k += 16;
1252 continue;
1253 }
1254 k += r;
1255 let z = component.dct_zig_zag[k as usize];
1256 component.blocks[block_row][block_col][z as usize] =
1257 receive_and_extend(decode_scan, s as usize) as i32;
1258 k += 1;
1259 }
1260}
1261
1262fn decode_dc_first(
1270 decode_scan: &mut DecodeScan,
1271 component: &mut JPEGComponent,
1272 block_row: usize,
1273 block_col: usize,
1274) {
1275 let t = decode_huffman(decode_scan, component.huffman_table_dc.clone());
1276 let diff = if t == 0 {
1277 0
1278 } else {
1279 receive_and_extend(decode_scan, t as usize) << decode_scan.successive
1280 };
1281 component.pred += diff as i32;
1282 component.blocks[block_row][block_col][0] = component.pred;
1283}
1284
1285fn decode_dc_successive(
1293 decode_scan: &mut DecodeScan,
1294 component: &mut JPEGComponent,
1295 block_row: usize,
1296 block_col: usize,
1297) {
1298 component.blocks[block_row][block_col][0] |=
1299 (read_bit(decode_scan) as i32) << decode_scan.successive;
1300}
1301
1302fn decode_ac_first(
1310 decode_scan: &mut DecodeScan,
1311 component: &mut JPEGComponent,
1312 block_row: usize,
1313 block_col: usize,
1314) {
1315 if decode_scan.eobrun > 0 {
1316 decode_scan.eobrun -= 1;
1317 return;
1318 }
1319 let mut k = decode_scan.spectral_start;
1320 let e = decode_scan.spectral_end;
1321 while k <= e {
1322 let rs = decode_huffman(decode_scan, component.huffman_table_ac.clone());
1323 let s = rs & 15;
1324 let r = rs >> 4;
1325 if s == 0 {
1326 if r < 15 {
1327 decode_scan.eobrun = receive(decode_scan, r as usize) + (1 << r) - 1;
1328 break;
1329 }
1330 k += 16;
1331 continue;
1332 }
1333 k += r as usize;
1334 let z = component.dct_zig_zag[k];
1335 component.blocks[block_row][block_col][z as usize] =
1336 receive_and_extend(decode_scan, s as usize) as i32 * (1 << decode_scan.successive);
1337 k += 1;
1338 }
1339}
1340
1341fn decode_ac_successive(
1349 decode_scan: &mut DecodeScan,
1350 component: &mut JPEGComponent,
1351 block_row: usize,
1352 block_col: usize,
1353) {
1354 let mut k = decode_scan.spectral_start;
1355 let e = decode_scan.spectral_end;
1356 let mut r = 0;
1357 while k <= e {
1358 let z = component.dct_zig_zag[k] as usize;
1359 let direction = if component.blocks[block_row][block_col][z] < 0 { -1 } else { 1 };
1360 match decode_scan.successive_ac_state {
1361 0 => {
1362 let rs = decode_huffman(decode_scan, component.huffman_table_ac.clone());
1364 let s = rs & 15;
1365 r = rs >> 4;
1366 if s == 0 {
1367 if r < 15 {
1368 decode_scan.eobrun = receive(decode_scan, r as usize) + (1 << r);
1369 decode_scan.successive_ac_state = 4;
1370 } else {
1371 r = 16;
1372 decode_scan.successive_ac_state = 1;
1373 }
1374 } else {
1375 if s != 1 {
1376 panic!("invalid ACn encoding");
1377 }
1378 decode_scan.successive_ac_next_value =
1379 receive_and_extend(decode_scan, s as usize) as usize;
1380 decode_scan.successive_ac_state = if r != 0 { 2 } else { 3 };
1381 }
1382 continue;
1383 }
1384 1 | 2 => {
1386 if component.blocks[block_row][block_col][z] != 0 {
1387 component.blocks[block_row][block_col][z] +=
1388 (read_bit(decode_scan) << decode_scan.successive) as i32 * direction;
1389 } else {
1390 r -= 1;
1391 if r == 0 {
1392 decode_scan.successive_ac_state =
1393 if decode_scan.successive_ac_state == 2 { 3 } else { 0 };
1394 }
1395 }
1396 }
1397 3 => {
1398 if component.blocks[block_row][block_col][z] != 0 {
1400 component.blocks[block_row][block_col][z] +=
1401 (read_bit(decode_scan) << decode_scan.successive) as i32 * direction;
1402 } else {
1403 component.blocks[block_row][block_col][z] =
1404 (decode_scan.successive_ac_next_value as i32) << decode_scan.successive;
1405 decode_scan.successive_ac_state = 0;
1406 }
1407 }
1408 4 => {
1409 if component.blocks[block_row][block_col][z] != 0 {
1411 component.blocks[block_row][block_col][z] +=
1412 (read_bit(decode_scan) << decode_scan.successive) as i32 * direction;
1413 }
1414 }
1415 _ => {}
1416 }
1417 k += 1;
1418 }
1419 if decode_scan.successive_ac_state == 4 {
1420 decode_scan.eobrun -= 1;
1421 if decode_scan.eobrun == 0 {
1422 decode_scan.successive_ac_state = 0;
1423 }
1424 }
1425}
1426fn decode_mcu(
1435 decode_scan: &mut DecodeScan,
1436 component: &mut JPEGComponent,
1437 decode: fn(&mut DecodeScan, &mut JPEGComponent, block_row: usize, block_col: usize),
1438 tolerant_decoding: bool,
1439 mcu: usize,
1440 row: usize,
1441 col: usize,
1442) {
1443 let mcu_row = mcu / decode_scan.mcus_per_line;
1444 let mcu_col = mcu % decode_scan.mcus_per_line;
1445 let block_row = mcu_row * component.v + row;
1446 let block_col = mcu_col * component.h + col;
1447 if component.blocks.get(block_row).is_none() && tolerant_decoding {
1449 return;
1450 }
1451 decode(decode_scan, component, block_row, block_col);
1452}
1453
1454fn decode_block(
1461 decode_scan: &mut DecodeScan,
1462 component: &mut JPEGComponent,
1463 decode: fn(&mut DecodeScan, &mut JPEGComponent, block_row: usize, block_col: usize),
1464 tolerant_decoding: bool,
1465 mcu: usize,
1466) {
1467 let block_row = mcu / component.blocks_per_line;
1468 let block_col = mcu % component.blocks_per_line;
1469 if component.blocks.get(block_row).is_none() && tolerant_decoding {
1471 return;
1472 }
1473 decode(decode_scan, component, block_row, block_col);
1474}
1475
1476struct DecodeScan<'a> {
1477 bits_count: usize,
1478 bits_data: usize,
1479 offset: usize,
1480 mcus_per_line: usize,
1481 progressive: bool,
1482 data: &'a [u8],
1483 successive: i32,
1484 successive_ac_state: usize,
1485 successive_ac_next_value: usize,
1486 eobrun: usize,
1487 spectral_start: usize,
1488 spectral_end: usize,
1489}
1490
1491#[allow(clippy::too_many_arguments)]
1508fn decode_scan(
1509 data: &[u8],
1510 offset: usize,
1511 frame: &mut JPEGFrame,
1512 components: &[Rc<RefCell<JPEGComponent>>],
1513 mut reset_interval: usize,
1514 spectral_start: usize,
1515 spectral_end: usize,
1516 successive_prev: usize,
1517 successive: i32,
1518 tolerant_decoding: bool,
1519) -> usize {
1520 let start_offset = offset;
1521 let mut decode_scan = DecodeScan {
1522 bits_count: 0,
1523 bits_data: 0,
1524 offset,
1525 mcus_per_line: frame.mcus_per_line,
1526 progressive: frame.progressive,
1527 data,
1528 successive,
1529 successive_ac_state: 0,
1530 successive_ac_next_value: 0,
1531 eobrun: 0,
1532 spectral_start,
1533 spectral_end,
1534 };
1535
1536 let components_length = components.len();
1537 let decode_fn = if decode_scan.progressive {
1538 if spectral_start == 0 {
1539 if successive_prev == 0 { decode_dc_first } else { decode_dc_successive }
1540 } else if successive_prev == 0 {
1541 decode_ac_first
1542 } else {
1543 decode_ac_successive
1544 }
1545 } else {
1546 decode_baseline
1547 };
1548
1549 let mut mcu = 0;
1550 let mut marker: usize;
1551 let mcu_expected = if components_length == 1 {
1552 components[0].borrow().blocks_per_line * components[0].borrow().blocks_per_column
1553 } else {
1554 decode_scan.mcus_per_line * frame.mcus_per_column
1555 };
1556 if reset_interval == 0 {
1557 reset_interval = mcu_expected;
1558 }
1559
1560 let mut h;
1561 let mut v;
1562 while mcu < mcu_expected {
1563 for component in components.iter().take(components_length) {
1565 component.borrow_mut().pred = 0;
1566 }
1567 decode_scan.eobrun = 0;
1568
1569 if components_length == 1 {
1570 let component = &components[0];
1571 for _ in 0..reset_interval {
1572 decode_block(
1573 &mut decode_scan,
1574 &mut component.borrow_mut(),
1575 decode_fn,
1576 tolerant_decoding,
1577 mcu,
1578 );
1579 mcu += 1;
1580 }
1581 } else {
1582 for _ in 0..reset_interval {
1583 for component in components.iter().take(components_length) {
1584 h = component.borrow().h;
1585 v = component.borrow().v;
1586 for j in 0..v {
1587 for k in 0..h {
1588 decode_mcu(
1589 &mut decode_scan,
1590 &mut component.borrow_mut(),
1591 decode_fn,
1592 tolerant_decoding,
1593 mcu,
1594 j,
1595 k,
1596 );
1597 }
1598 }
1599 }
1600 mcu += 1;
1601
1602 if mcu == mcu_expected {
1604 break;
1605 }
1606 }
1607 }
1608
1609 if mcu == mcu_expected {
1610 loop {
1612 if (data[decode_scan.offset] == 0xff) && (data[decode_scan.offset + 1] != 0x00) {
1613 break;
1614 }
1615 decode_scan.offset += 1;
1616 if decode_scan.offset >= data.len() - 2 {
1617 break;
1618 }
1619 }
1620 }
1621
1622 decode_scan.bits_count = 0;
1624 marker = ((data[decode_scan.offset] as usize) << 8) | data[decode_scan.offset + 1] as usize;
1625 if marker < 0xff00 {
1626 panic!("marker was not found");
1627 }
1628
1629 if (0xffd0..=0xffd7).contains(&marker) {
1630 decode_scan.offset += 2;
1632 } else {
1633 break;
1634 }
1635 }
1636
1637 decode_scan.offset - start_offset
1638}
1639
1640fn quantize_and_inverse(
1650 component: &JPEGComponent,
1651 zz: &[i32],
1652 data_out: &mut [u8],
1653 data_in: &mut [i32],
1654) {
1655 let qt = &component.quantization_table;
1656 let mut v0;
1657 let mut v1;
1658 let mut v2;
1659 let mut v3;
1660 let mut v4;
1661 let mut v5;
1662 let mut v6;
1663 let mut v7;
1664 let mut t;
1665 let p = data_in;
1666
1667 for i in 0..64 {
1669 p[i] = zz[i] * qt[i];
1670 }
1671 for i in 0..8 {
1673 let row = 8 * i;
1674
1675 if p[1 + row] == 0
1677 && p[2 + row] == 0
1678 && p[3 + row] == 0
1679 && p[4 + row] == 0
1680 && p[5 + row] == 0
1681 && p[6 + row] == 0
1682 && p[7 + row] == 0
1683 {
1684 t = (DCT_SQRT2 * p[row] + 512) >> 10;
1685 p[row] = t;
1686 p[1 + row] = t;
1687 p[2 + row] = t;
1688 p[3 + row] = t;
1689 p[4 + row] = t;
1690 p[5 + row] = t;
1691 p[6 + row] = t;
1692 p[7 + row] = t;
1693 continue;
1694 }
1695
1696 v0 = (DCT_SQRT2 * p[row] + 128) >> 8;
1698 v1 = (DCT_SQRT2 * p[4 + row] + 128) >> 8;
1699 v2 = p[2 + row];
1700 v3 = p[6 + row];
1701 v4 = (DCT_SQRT1D2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
1702 v7 = (DCT_SQRT1D2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
1703 v5 = p[3 + row] << 4;
1704 v6 = p[5 + row] << 4;
1705
1706 t = (v0 - v1 + 1) >> 1;
1708 v0 = (v0 + v1 + 1) >> 1;
1709 v1 = t;
1710 t = (v2 * DCT_SIN6 + v3 * DCT_COS6 + 128) >> 8;
1711 v2 = (v2 * DCT_COS6 - v3 * DCT_SIN6 + 128) >> 8;
1712 v3 = t;
1713 t = (v4 - v6 + 1) >> 1;
1714 v4 = (v4 + v6 + 1) >> 1;
1715 v6 = t;
1716 t = (v7 + v5 + 1) >> 1;
1717 v5 = (v7 - v5 + 1) >> 1;
1718 v7 = t;
1719
1720 t = (v0 - v3 + 1) >> 1;
1722 v0 = (v0 + v3 + 1) >> 1;
1723 v3 = t;
1724 t = (v1 - v2 + 1) >> 1;
1725 v1 = (v1 + v2 + 1) >> 1;
1726 v2 = t;
1727 t = (v4 * DCT_SIN3 + v7 * DCT_COS3 + 2048) >> 12;
1728 v4 = (v4 * DCT_COS3 - v7 * DCT_SIN3 + 2048) >> 12;
1729 v7 = t;
1730 t = (v5 * DCT_SIN1 + v6 * DCT_COS1 + 2048) >> 12;
1731 v5 = (v5 * DCT_COS1 - v6 * DCT_SIN1 + 2048) >> 12;
1732 v6 = t;
1733
1734 p[row] = v0 + v7;
1736 p[7 + row] = v0 - v7;
1737 p[1 + row] = v1 + v6;
1738 p[6 + row] = v1 - v6;
1739 p[2 + row] = v2 + v5;
1740 p[5 + row] = v2 - v5;
1741 p[3 + row] = v3 + v4;
1742 p[4 + row] = v3 - v4;
1743 }
1744
1745 for i in 0..8 {
1747 let col = i;
1748
1749 if p[8 + col] == 0
1751 && p[2 * 8 + col] == 0
1752 && p[3 * 8 + col] == 0
1753 && p[4 * 8 + col] == 0
1754 && p[5 * 8 + col] == 0
1755 && p[6 * 8 + col] == 0
1756 && p[7 * 8 + col] == 0
1757 {
1758 t = (DCT_SQRT2 * p[i] + 8192) >> 14;
1759 p[col] = t;
1760 p[8 + col] = t;
1761 p[2 * 8 + col] = t;
1762 p[3 * 8 + col] = t;
1763 p[4 * 8 + col] = t;
1764 p[5 * 8 + col] = t;
1765 p[6 * 8 + col] = t;
1766 p[7 * 8 + col] = t;
1767 continue;
1768 }
1769
1770 v0 = (DCT_SQRT2 * p[col] + 2048) >> 12;
1772 v1 = (DCT_SQRT2 * p[4 * 8 + col] + 2048) >> 12;
1773 v2 = p[2 * 8 + col];
1774 v3 = p[6 * 8 + col];
1775 v4 = (DCT_SQRT1D2 * (p[8 + col] - p[7 * 8 + col]) + 2048) >> 12;
1776 v7 = (DCT_SQRT1D2 * (p[8 + col] + p[7 * 8 + col]) + 2048) >> 12;
1777 v5 = p[3 * 8 + col];
1778 v6 = p[5 * 8 + col];
1779
1780 t = (v0 - v1 + 1) >> 1;
1782 v0 = (v0 + v1 + 1) >> 1;
1783 v1 = t;
1784 t = (v2 * DCT_SIN6 + v3 * DCT_COS6 + 2048) >> 12;
1785 v2 = (v2 * DCT_COS6 - v3 * DCT_SIN6 + 2048) >> 12;
1786 v3 = t;
1787 t = (v4 - v6 + 1) >> 1;
1788 v4 = (v4 + v6 + 1) >> 1;
1789 v6 = t;
1790 t = (v7 + v5 + 1) >> 1;
1791 v5 = (v7 - v5 + 1) >> 1;
1792 v7 = t;
1793
1794 t = (v0 - v3 + 1) >> 1;
1796 v0 = (v0 + v3 + 1) >> 1;
1797 v3 = t;
1798 t = (v1 - v2 + 1) >> 1;
1799 v1 = (v1 + v2 + 1) >> 1;
1800 v2 = t;
1801 t = (v4 * DCT_SIN3 + v7 * DCT_COS3 + 2048) >> 12;
1802 v4 = (v4 * DCT_COS3 - v7 * DCT_SIN3 + 2048) >> 12;
1803 v7 = t;
1804 t = (v5 * DCT_SIN1 + v6 * DCT_COS1 + 2048) >> 12;
1805 v5 = (v5 * DCT_COS1 - v6 * DCT_SIN1 + 2048) >> 12;
1806 v6 = t;
1807
1808 p[col] = v0 + v7;
1810 p[7 * 8 + col] = v0 - v7;
1811 p[8 + col] = v1 + v6;
1812 p[6 * 8 + col] = v1 - v6;
1813 p[2 * 8 + col] = v2 + v5;
1814 p[5 * 8 + col] = v2 - v5;
1815 p[3 * 8 + col] = v3 + v4;
1816 p[4 * 8 + col] = v3 - v4;
1817 }
1818
1819 for i in 0..64 {
1821 let sample = 128 + ((p[i] + 8) >> 4);
1822 data_out[i] = if sample < 0 {
1823 0
1824 } else if sample > 0xff {
1825 0xff
1826 } else {
1827 sample as u8
1828 };
1829 }
1830}
1831
1832fn ensure_len<T: Clone>(vec: &mut Vec<T>, index: usize, default: T) {
1833 if vec.len() <= index {
1834 vec.resize(index + 1, default);
1835 }
1836}
1837
1838fn clamp_to_8bit(a: f64) -> i32 {
1846 a.clamp(0., 255.) as i32
1847}