gistools/parsers/image/
jpeg.rs

1use alloc::{collections::BTreeMap, rc::Rc, string::String, vec, vec::Vec};
2use core::cell::RefCell;
3use libm::ceil;
4
5// TODO: Instead we should use https://gitlab.com/libtiff/libtiff/-/blob/master/libtiff/tif_jpeg.c?ref_type=heads
6
7// /* -*- tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
8// vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab:
9// Copyright 2011 notmasteryet
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13// http://www.apache.org/licenses/LICENSE-2.0
14// Unless required by applicable law or agreed to in writing, software
15// distributed under the License is distributed on an "AS IS" BASIS,
16// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17// See the License for the specific language governing permissions and
18// limitations under the License.
19// - The JPEG specification can be found in the ITU CCITT Recommendation T.81
20//   (www.w3.org/Graphics/JPEG/itu-t81.pdf)
21// - The JFIF specification can be found in the JPEG File Interchange Format
22//   (www.w3.org/Graphics/JPEG/jfif3.pdf)
23// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
24//   in PostScript Level 2, Technical Note #5116
25//   (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
26
27const DCT_COS1: i32 = 4017; // cos(pi/16)
28const DCT_SIN1: i32 = 799; // sin(pi/16)
29const DCT_COS3: i32 = 3406; // cos(3*pi/16)
30const DCT_SIN3: i32 = 2276; // sin(3*pi/16)
31const DCT_COS6: i32 = 1567; // cos(6*pi/16)
32const DCT_SIN6: i32 = 3784; // sin(6*pi/16)
33const DCT_SQRT2: i32 = 5793; // sqrt(2)
34const DCT_SQRT1D2: i32 = 2896; // sqrt(2) / 2
35
36/// JPEG Options
37#[derive(Debug, Clone)]
38pub struct JPEGOptions {
39    /// Skip mutation
40    pub skip_mutation: bool,
41    /// Color transform
42    pub color_transform: Option<bool>,
43    /// Format as RGBA
44    pub format_as_rgba: bool,
45    /// Tolerant decoding
46    pub tolerant_decoding: bool,
47    /// Don't decode more than 100 megapixels
48    pub max_resolution_in_mp: usize,
49    /// Don't decode if memory footprint is more than 512MB
50    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/// A Component of a JPEG image
66#[derive(Debug, Default, Clone)]
67struct JPEGComponent {
68    /// h
69    pub h: usize,
70    /// v
71    pub v: usize,
72    /// quantization IDX
73    pub quantization_idx: usize,
74    /// blocks per line
75    pub blocks_per_line: usize,
76    /// blocks per column
77    pub blocks_per_column: usize,
78    /// blocks
79    pub blocks: Vec<Vec<Vec<i32>>>,
80    /// huffman table DC
81    pub huffman_table_dc: Rc<RefCell<Vec<HuffmanNode>>>,
82    /// huffman table AC
83    pub huffman_table_ac: Rc<RefCell<Vec<HuffmanNode>>>,
84    /// quantization table
85    pub quantization_table: Vec<i32>,
86    /// prediction value
87    pub pred: i32,
88    /// zig zag dictionary
89    pub dct_zig_zag: Vec<i32>,
90}
91
92/// A Component of a JPEG image organized into lines
93#[derive(Debug, Default, Clone)]
94struct OutComponent {
95    /// lines
96    pub lines: Vec<Vec<u8>>,
97    /// scale x
98    pub scale_x: usize,
99    /// scale y
100    pub scale_y: usize,
101}
102
103/// A JPEG frame
104#[derive(Debug, Default, Clone)]
105pub struct JPEGFrame {
106    /// Exposing to hide the unused field warning
107    pub extended: bool,
108    progressive: bool,
109    /// Exposing to hide the unused field warning
110    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/// Adobe APP14 marker
122#[derive(Debug, Default, Clone)]
123pub struct Adobe {
124    /// Version
125    pub version: u8,
126    /// Flags 0
127    pub flags0: usize,
128    /// Flags 1
129    pub flags1: usize,
130    /// Color transform
131    pub transform_code: u8,
132}
133
134/// JFIF marker Version
135#[derive(Debug, Default, Clone)]
136pub struct JFIFVersion {
137    /// Major version
138    pub major: u8,
139    /// Minor version
140    pub minor: u8,
141}
142
143/// JFIF marker
144#[derive(Debug, Default, Clone)]
145pub struct JFIF {
146    /// JFIF version
147    pub version: JFIFVersion,
148    /// Density units
149    pub density_units: usize,
150    /// X Density
151    pub x_density: usize,
152    /// Y Density
153    pub y_density: usize,
154    /// Thumbnail width
155    pub thumb_width: usize,
156    /// Thumbnail height
157    pub thumb_height: usize,
158    /// Thumbnail data
159    pub thumb_data: Vec<u8>,
160}
161
162/// Represents a Huffman tree node where each node can contain either
163/// a number (leaf) or nested arrays of numbers (internal nodes).
164#[derive(Debug, Clone)]
165pub enum HuffmanNode {
166    /// A leaf node
167    Leaf(u8),
168    /// An internal node
169    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/// Represents a Huffman code node that can either contain child nodes
178/// or be a leaf containing a numeric value.
179#[derive(Debug, Default, Clone)]
180pub struct Code {
181    /// Internal node is Code[], leaf node is number
182    pub children: Rc<RefCell<Vec<HuffmanNode>>>,
183    /// Index
184    pub index: Rc<RefCell<usize>>,
185}
186
187/// The result of an individual parse */
188#[derive(Debug, Clone)]
189pub struct ParseResult {
190    data: Vec<u8>,
191    out_components: Vec<OutComponent>,
192    ready: bool,
193}
194
195/// An Image organized for the JPEG decoder
196#[derive(Debug, Clone)]
197pub struct Image {
198    /// The image width
199    pub width: usize,
200    /// The image height
201    pub height: usize,
202    /// The exif buffer
203    pub exif_buffer: Option<Vec<u8>>,
204    /// The image data
205    pub data: Vec<u8>,
206    /// The image comments
207    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
232/// Decodes a JPEG image
233///
234/// ## Parameters
235/// - `jpeg_data`: The JPEG data
236/// - `user_opts`: The user provided options
237/// - `jpeg_tables`: The JPEG tables (if provided)
238///
239/// ## Returns
240/// The decoded image
241pub 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    // If this constructor ever supports async decoding this will need to be done differently.
248    // Until then, treating as singleton limit is fine.
249    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
258/// Decodes a JPEG image
259///
260/// ## Parameters
261/// - `buffer`: The JPEG data
262/// - `jpeg_tables`: The JPEG tables (if provided)
263///
264/// ## Returns
265/// The decoded image as a buffer
266pub 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/// A JPEG stream reader
276#[derive(Debug)]
277pub struct JpegStreamReader {
278    color_transform: Option<bool>,
279    skip_mutation: bool,
280    format_as_rgba: bool,
281    tolerant_decoding: bool,
282    // Don't decode more than 100 megapixels
283    max_resolution_in_mp: usize,
284    // Don't decode if memory footprint is more than 512MB
285    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    /// Given the user provided options, Create a new JpegStreamReader
303    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    /// Reset the frames
334    pub fn reset_frames(&mut self) {
335        self.frames = vec![];
336    }
337
338    /// Reset the max memory usage
339    ///
340    /// ## Parameters
341    /// - `max_memory_usage_bytes`: The new max memory usage
342    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    /// Get the complete image data
348    ///
349    /// ## Returns
350    /// The image data
351    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    /// Parse the data into the frames
458    ///
459    /// ## Parameters
460    /// - `data`: The individual block of JPEG data to parse
461    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            // SOI (Start of Image)
469            panic!("SOI not found");
470        }
471
472        file_marker = reader.read_u16();
473        while file_marker != 0xffd9 {
474            // EOI (End of image)
475            match file_marker {
476                0xff00 => {}
477                0xffe0 | // APP0 (Application Specific)
478                0xffe1 | // APP1
479                0xffe2 | // APP2
480                0xffe3 | // APP3
481                0xffe4 | // APP4
482                0xffe5 | // APP5
483                0xffe6 | // APP6
484                0xffe7 | // APP7
485                0xffe8 | // APP8
486                0xffe9 | // APP9
487                0xffea | // APP10
488                0xffeb | // APP11
489                0xffec | // APP12
490                0xffed | // APP13
491                0xffee | // APP14
492                0xffef | // APP15
493                0xfffe => {
494                  // COM (Comment)
495                  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                    // 'JFIF\x00'
510                    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                  // TODO APP1 - Exif
521                  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                    // 'EXIF\x00'
529                    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                    // 'Adobe\x00'
541                    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                  // DQT (Define Quantization Tables)
552                  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                        // 8 bit values
561                        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                      // 16 bit
568                      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                // SOF0 (Start of Frame, Baseline DCT)
582                // SOF1 (Start of Frame, Extended DCT)
583                0xffc0..=0xffc2 => {
584                  // SOF2 (Start of Frame, Progressive DCT)
585                  reader.read_u16(); // skip data length
586                  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                    // if h <= 0 || v <= 0 {
617                    //   panic!("Invalid sampling factor, expected values above 0");
618                    // }
619
620                    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                  // DHT (Define Huffman Tables)
642                  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 => { // DRI (Define Restart Interval)
676                  reader.read_u16(); // skip data length
677                  self.reset_interval = reader.read_u16() as usize;
678                }
679
680                0xffdc => { // Number of Lines marker
681                    reader.read_u16(); // skip data length
682                    reader.read_u16(); // Ignore this data since it represents the image height
683                }
684
685                0xffda => {
686                    // SOS (Start of Scan)
687                    reader.read_u16(); // skip scan length
688                    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 => { // Fill bytes
731                  if data[reader.offset] != 0xff {
732                    // Avoid skipping a valid marker.
733                    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                    // could be incorrect encoding -- last 0xFF byte of the previous
740                    // block was eaten by the encoder
741                    reader.offset -= 3;
742                  } else if file_marker == 0xe0 || file_marker == 0xe1 {
743                    // Recover from malformed APP1 markers popular in some phone models.
744                    // See https://github.com/eugeneware/jpeg-js/issues/82
745                    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    /// Increase the max memory usage
765    ///
766    /// ## Parameters
767    /// - `increase_amount`: The amount to increase the max memory usage
768    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    /// Get a result of the frame decoding
781    ///
782    /// ## Returns
783    /// The result of the frame decoding
784    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        // set each frame's components quantization table
792        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        // No mutation function for parsing the data without mutation
826        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                // PDF might compress two component data in custom colorspace
859                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                // The default transform for three components is true
876                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                    // The default transform for four components is false
922                    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    /// Build the component data
981    ///
982    /// ## Parameters
983    /// - `component`: the component
984    /// - `reader`: the jpeg stream reader
985    ///
986    /// ## Returns
987    /// The component data
988    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        // Only 1 used per invocation of this function and garbage collected after invocation, so no need to account for its memory footprint.
994        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    /// Prepares the components of the frame
1028    ///
1029    /// ## Parameters
1030    /// - `frame`: The frame to parse
1031    fn prepare_components(&self, frame: &mut JPEGFrame) {
1032        // According to the JPEG standard, the sampling factor must be between 1 and 4
1033        // See https://github.com/libjpeg-turbo/libjpeg-turbo/blob/9abeff46d87bd201a952e276f3e4339556a403a3/libjpeg.txt#L1138-L1146
1034        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            // Each block is a Int32Array of length 64 (4 x 64 = 256 bytes)
1058            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
1078/// Builds a Huffman table from the input data
1079///
1080/// ## Parameters
1081/// - `code_lengths`: array of code lengths
1082/// - `values`: array of values
1083///
1084/// ## Returns
1085/// The Huffman table
1086fn 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    // Find the highest non-zero code length
1091    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            // p here points to last code
1130            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
1146/// ## Returns
1147/// The next bit
1148fn 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        // if next_byte.is_none() {
1159        //     panic!("unexpected marker: {}", (decode_scan.bits_data << 8));
1160        // }
1161        // unstuff 0
1162    }
1163    decode_scan.bits_count = 7;
1164    decode_scan.bits_data >> 7
1165}
1166
1167/// Decodes a Huffman Node tree
1168///
1169/// ## Parameters
1170/// - `decode_scan`: the decoder
1171/// - `tree`: the tree to decode with
1172///
1173/// ## Returns
1174/// The decoded value
1175fn 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
1193/// Receives a number
1194///
1195/// ## Parameters
1196/// - `decode_scan`: the decoder
1197/// - `length`: the number of bits
1198///
1199/// ## Returns
1200/// The number
1201fn 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
1212/// Recieves and extends a number
1213///
1214/// ## Parameters
1215/// - `decode_scan`: the decoder
1216/// - `length`: the number of bits
1217///
1218/// ## Returns
1219/// The extended number
1220fn 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
1225/// Decodes a baseline block
1226///
1227/// ## Parameters
1228/// - `decode_scan`: the decoder
1229/// - `component`: the component
1230/// - `block_row`: the block row
1231/// - `block_col`: the block column
1232fn 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
1262/// Decodes a DC coefficient first pass
1263///
1264/// ## Parameters
1265/// - `decode_scan`: the decoder
1266/// - `component`: the component
1267/// - `block_row`: the block row
1268/// - `block_col`: the block column
1269fn 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
1285/// Decodes a successive approximation block
1286///
1287/// ## Parameters
1288/// - `decode_scan`: the decoder
1289/// - `component`: the component
1290/// - `block_row`: the block row
1291/// - `block_col`: the block column
1292fn 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
1302/// Decodes an AC block first pass
1303///
1304/// ## Parameters
1305/// - `decode_scan`: the decoder
1306/// - `component`: the component
1307/// - `block_row`: the block row
1308/// - `block_col`: the block column
1309fn 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
1341/// Decodes a successive approximation block
1342///
1343/// ## Parameters
1344/// - `decode_scan`: the decoder
1345/// - `component`: the component
1346/// - `block_row`: the block row
1347/// - `block_col`: the block column
1348fn 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                // initial state
1363                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            // skipping r zero items
1385            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                // set value for a zero item
1399                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                // eob
1410                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}
1426/// Decodes an MCU
1427///
1428/// ## Parameters
1429/// - `component`: The component
1430/// - `decode`: The decoder
1431/// - `mcu`: The mcu
1432/// - `row`: The row
1433/// - `col`: The column
1434fn 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 the block is missing and we're in tolerant mode, just skip it.
1448    if component.blocks.get(block_row).is_none() && tolerant_decoding {
1449        return;
1450    }
1451    decode(decode_scan, component, block_row, block_col);
1452}
1453
1454/// Decodes a block
1455///
1456/// ## Parameters
1457/// - `component`: The component
1458/// - `decode`: The decoder
1459/// - `mcu`: The mcu value
1460fn 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 the block is missing and we're in tolerant mode, just skip it.
1470    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/// Decodes a JPEG scan
1492///
1493/// ## Parameters
1494/// - `data`: the JPEG data
1495/// - `offset`: the offset in the JPEG data
1496/// - `frame`: the frame
1497/// - `components`: the components of the frame
1498/// - `reset_interval`: the reset interval
1499/// - `spectral_start`: the spectral start
1500/// - `spectral_end`: the spectral end
1501/// - `successive_prev`: the successive prev
1502/// - `successive`: the successive number
1503/// - `opts`: the options passed to the reader
1504///
1505/// ## Returns
1506/// The decoded scan size
1507#[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        // reset interval stuff
1564        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 we've reached our expected MCU's, stop decoding
1603                if mcu == mcu_expected {
1604                    break;
1605                }
1606            }
1607        }
1608
1609        if mcu == mcu_expected {
1610            // Skip trailing bytes at the end of the scan - until we reach the next marker
1611            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        // find marker
1623        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            // RSTx
1631            decode_scan.offset += 2;
1632        } else {
1633            break;
1634        }
1635    }
1636
1637    decode_scan.offset - start_offset
1638}
1639
1640/// A port of poppler's IDCT method which in turn is taken from:
1641/// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
1642/// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
1643/// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,988-991.
1644///
1645/// ## Parameters
1646/// - `zz`: the 8x8 block
1647/// - `data_out`: the 8x8 block
1648/// - `data_in`: the 8x8 block
1649fn 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    // dequant
1668    for i in 0..64 {
1669        p[i] = zz[i] * qt[i];
1670    }
1671    // inverse DCT on rows
1672    for i in 0..8 {
1673        let row = 8 * i;
1674
1675        // check for all-zero AC coefficients
1676        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        // stage 4
1697        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        // stage 3
1707        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        // stage 2
1721        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        // stage 1
1735        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    // inverse DCT on columns
1746    for i in 0..8 {
1747        let col = i;
1748
1749        // check for all-zero AC coefficients
1750        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        // stage 4
1771        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        // stage 3
1781        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        // stage 2
1795        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        // stage 1
1809        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    // convert to 8-bit integers
1820    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
1838/// Clamp a number to a uint8 [0-255]
1839///
1840/// ## Parameters
1841/// - `a`: the number
1842///
1843/// ## Returns
1844/// The clamped number
1845fn clamp_to_8bit(a: f64) -> i32 {
1846    a.clamp(0., 255.) as i32
1847}