Skip to main content

signinum_j2k_native/j2c/
codestream.rs

1//! Read and decode a JPEG2000 codestream, as described in Annex A.
2
3use alloc::vec;
4use alloc::vec::Vec;
5
6use super::bitplane::BITPLANE_BIT_SIZE;
7use super::build::SubBandType;
8use super::DecodeSettings;
9use crate::error::{bail, err, DecodingError, MarkerError, Result, ValidationError};
10use crate::reader::BitReader;
11use crate::{MAX_J2K_SPEC_COMPONENTS, MAX_NATIVE_DECODE_COMPONENTS};
12
13const MAX_LAYER_COUNT: u8 = 32;
14const MAX_RESOLUTION_COUNT: u8 = 32;
15const MAX_PRECINCT_EXPONENT: u8 = 31;
16
17#[derive(Debug)]
18pub(crate) struct Header<'a> {
19    pub(crate) size_data: SizeData,
20    pub(crate) global_coding_style: CodingStyleDefault,
21    pub(crate) component_infos: Vec<ComponentInfo>,
22    pub(crate) progression_changes: Vec<ProgressionChange>,
23    pub(crate) plm_packet_lengths: Vec<u32>,
24    pub(crate) ppm_packets: Vec<PpmPacket<'a>>,
25    pub(crate) skipped_resolution_levels: u8,
26    /// Whether strict mode is enabled for decoding.
27    pub(crate) strict: bool,
28}
29
30#[derive(Debug, Clone)]
31pub(crate) struct PpmMarkerData<'a> {
32    pub(crate) sequence_idx: u8,
33    pub(crate) packets: Vec<PpmPacket<'a>>,
34}
35
36#[derive(Debug, Clone)]
37pub(crate) struct PpmPacket<'a> {
38    pub(crate) data: &'a [u8],
39}
40
41#[derive(Debug, Clone)]
42pub(crate) struct PacketLengthMarker {
43    pub(crate) sequence_idx: u8,
44    pub(crate) packet_lengths: Vec<u32>,
45}
46
47pub(crate) fn read_header<'a>(
48    reader: &mut BitReader<'a>,
49    settings: &DecodeSettings,
50) -> Result<Header<'a>> {
51    if reader.read_marker()? != markers::SIZ {
52        bail!(MarkerError::Expected("SIZ"));
53    }
54
55    let mut size_data = size_marker(reader)?;
56
57    let mut cod = None;
58    let mut qcd = None;
59
60    let num_components = size_data.component_sizes.len() as u16;
61    let mut cod_components = vec![None; num_components as usize];
62    let mut qcd_components = vec![None; num_components as usize];
63    let mut rgn_components = vec![None; num_components as usize];
64    let mut progression_changes = vec![];
65    let mut plm_markers = vec![];
66    let mut ppm_markers = vec![];
67
68    loop {
69        match reader.peek_marker().ok_or(MarkerError::Invalid)? {
70            markers::SOT => break,
71            markers::CAP | markers::CPF => {
72                reader.read_marker()?;
73                skip_marker_segment(reader).ok_or(MarkerError::ParseFailure("CAP/CPF"))?;
74            }
75            markers::COD => {
76                reader.read_marker()?;
77                cod = Some(cod_marker(reader).ok_or(MarkerError::ParseFailure("COD"))?);
78            }
79            markers::COC => {
80                reader.read_marker()?;
81                let (component_index, coc) =
82                    coc_marker(reader, num_components).ok_or(MarkerError::ParseFailure("COC"))?;
83                *cod_components
84                    .get_mut(component_index as usize)
85                    .ok_or(MarkerError::ParseFailure("COC"))? = Some(coc);
86            }
87            markers::QCD => {
88                reader.read_marker()?;
89                qcd = Some(qcd_marker(reader).ok_or(MarkerError::ParseFailure("QCD"))?);
90            }
91            markers::QCC => {
92                reader.read_marker()?;
93                let (component_index, qcc) =
94                    qcc_marker(reader, num_components).ok_or(MarkerError::ParseFailure("QCC"))?;
95                *qcd_components
96                    .get_mut(component_index as usize)
97                    .ok_or(MarkerError::ParseFailure("QCC"))? = Some(qcc);
98            }
99            markers::POC => {
100                reader.read_marker()?;
101                let num_layers = cod
102                    .as_ref()
103                    .ok_or(MarkerError::ParseFailure("POC"))?
104                    .num_layers;
105                progression_changes.extend(
106                    poc_marker(reader, num_components, num_layers)
107                        .ok_or(MarkerError::ParseFailure("POC"))?,
108                );
109            }
110            markers::RGN => {
111                reader.read_marker()?;
112                let rgn =
113                    rgn_marker(reader, num_components).ok_or(MarkerError::ParseFailure("RGN"))?;
114                if rgn.style != 0 {
115                    bail!(DecodingError::UnsupportedFeature("explicit ROI coding"));
116                }
117                *rgn_components
118                    .get_mut(rgn.component_index as usize)
119                    .ok_or(MarkerError::ParseFailure("RGN"))? = Some(rgn.shift);
120            }
121            markers::TLM => {
122                reader.read_marker()?;
123                tlm_marker(reader).ok_or(MarkerError::ParseFailure("TLM"))?;
124            }
125            markers::PLM => {
126                reader.read_marker()?;
127                plm_markers.push(plm_marker(reader).ok_or(MarkerError::ParseFailure("PLM"))?);
128            }
129            markers::COM => {
130                reader.read_marker()?;
131                com_marker(reader).ok_or(MarkerError::ParseFailure("COM"))?;
132            }
133            markers::PPM => {
134                reader.read_marker()?;
135                ppm_markers.push(ppm_marker(reader).ok_or(MarkerError::ParseFailure("PPM"))?);
136            }
137            markers::CRG => {
138                reader.read_marker()?;
139                skip_marker_segment(reader);
140            }
141            (0x30..=0x3F) => {
142                // "All markers with the marker code between 0xFF30 and 0xFF3F
143                // have no marker segment parameters. They shall be skipped by
144                // the decoder."
145                reader.read_marker()?;
146                // skip_marker_segment(reader);
147            }
148            _ => {
149                bail!(MarkerError::Unsupported);
150            }
151        }
152    }
153
154    let cod = cod.ok_or(MarkerError::Missing("COD"))?;
155    let qcd = qcd.ok_or(MarkerError::Missing("QCD"))?;
156
157    let component_infos: Vec<ComponentInfo> = size_data
158        .component_sizes
159        .iter()
160        .enumerate()
161        .map(|(idx, csi)| ComponentInfo {
162            size_info: *csi,
163            coding_style: cod_components[idx]
164                .clone()
165                .map(|mut c| {
166                    c.flags.raw |= cod.component_parameters.flags.raw;
167
168                    c
169                })
170                .unwrap_or(cod.component_parameters.clone()),
171            quantization_info: qcd_components[idx].clone().unwrap_or(qcd.clone()),
172            roi_shift: rgn_components[idx].unwrap_or(0),
173        })
174        .collect();
175
176    // Components can have different number of resolution levels. In that case, we
177    // can only skip as many resolution levels as the component with the smallest
178    // number of resolution levels.
179    let min_num_resolution_levels = component_infos
180        .iter()
181        .map(|c| c.num_resolution_levels())
182        .min()
183        .ok_or(ValidationError::InvalidComponentMetadata)?;
184    let skipped_resolution_levels =
185        if let Some((target_width, target_height)) = settings.target_resolution {
186            if target_width == 0 || target_height == 0 {
187                bail!(ValidationError::InvalidDimensions);
188            }
189            let width_log = (size_data.image_width() / target_width)
190                .checked_ilog2()
191                .unwrap_or(0);
192            let height_log = (size_data.image_height() / target_height)
193                .checked_ilog2()
194                .unwrap_or(0);
195
196            width_log.min(height_log) as u8
197        } else {
198            0
199        }
200        .min(min_num_resolution_levels - 1);
201
202    // If the user defined a maximum resolution level that is lower than the
203    // maximum available one, the final image needs to be shrunk further.
204    size_data.x_resolution_shrink_factor *= 1 << skipped_resolution_levels;
205    size_data.y_resolution_shrink_factor *= 1 << skipped_resolution_levels;
206
207    ppm_markers.sort_by_key(|ppm_marker| ppm_marker.sequence_idx);
208    plm_markers.sort_by_key(|plm_marker| plm_marker.sequence_idx);
209
210    let header = Header {
211        size_data,
212        global_coding_style: cod.clone(),
213        component_infos,
214        progression_changes,
215        plm_packet_lengths: plm_markers
216            .into_iter()
217            .flat_map(|marker| marker.packet_lengths)
218            .collect(),
219        ppm_packets: ppm_markers
220            .into_iter()
221            .flat_map(|i| i.packets)
222            .filter_map(|p| if p.data.is_empty() { None } else { Some(p) })
223            .collect(),
224        skipped_resolution_levels,
225        strict: settings.strict,
226    };
227
228    validate(&header)?;
229
230    Ok(header)
231}
232
233fn validate(header: &Header<'_>) -> Result<()> {
234    for info in &header.component_infos {
235        let max_resolution_idx = info.coding_style.parameters.num_resolution_levels - 1;
236        let quantization_style = info.quantization_info.quantization_style;
237        let num_precinct_exponents = info.quantization_info.step_sizes.len();
238
239        if num_precinct_exponents == 0 {
240            bail!(ValidationError::MissingPrecinctExponents);
241        } else if matches!(
242            quantization_style,
243            QuantizationStyle::NoQuantization | QuantizationStyle::ScalarExpounded
244        ) {
245            // See the accesses in the `exponent_mantissa` method. The largest
246            // access is 1 + (max_resolution_idx - 1) * 3 + 2.
247
248            if max_resolution_idx == 0 {
249                if num_precinct_exponents == 0 {
250                    bail!(ValidationError::InsufficientExponents);
251                }
252            } else if 1 + (max_resolution_idx as usize - 1) * 3 + 2 >= num_precinct_exponents {
253                bail!(ValidationError::InsufficientExponents);
254            }
255        }
256    }
257
258    Ok(())
259}
260
261#[derive(Debug, Clone)]
262pub(crate) struct ComponentInfo {
263    pub(crate) size_info: ComponentSizeInfo,
264    pub(crate) coding_style: CodingStyleComponent,
265    pub(crate) quantization_info: QuantizationInfo,
266    pub(crate) roi_shift: u8,
267}
268
269impl ComponentInfo {
270    pub(crate) fn exponent_mantissa(
271        &self,
272        sub_band_type: SubBandType,
273        resolution: u8,
274    ) -> Result<(u16, u16)> {
275        let n_ll = self.coding_style.parameters.num_decomposition_levels;
276
277        let sb_index = match sub_band_type {
278            // LL only has a quantization entry at resolution 0; non-zero LL
279            // lookups fall through to the missing-step error below.
280            SubBandType::LowLow => u16::MAX,
281            SubBandType::HighLow => 0,
282            SubBandType::LowHigh => 1,
283            SubBandType::HighHigh => 2,
284        };
285
286        let step_sizes = &self.quantization_info.step_sizes;
287        match self.quantization_info.quantization_style {
288            QuantizationStyle::NoQuantization | QuantizationStyle::ScalarExpounded => {
289                let entry = if resolution == 0 {
290                    step_sizes.first()
291                } else {
292                    step_sizes.get(1 + (resolution as usize - 1) * 3 + sb_index as usize)
293                };
294
295                Ok(entry
296                    .map(|s| (s.exponent, s.mantissa))
297                    .ok_or(ValidationError::MissingStepSize)?)
298            }
299            QuantizationStyle::ScalarDerived => {
300                let (e_0, mantissa) = step_sizes
301                    .first()
302                    .map(|s| (s.exponent, s.mantissa))
303                    .ok_or(ValidationError::MissingStepSize)?;
304                let n_b = if resolution == 0 {
305                    n_ll as u16
306                } else {
307                    n_ll as u16 + 1 - resolution as u16
308                };
309
310                let exponent = e_0
311                    .checked_sub(n_ll as u16)
312                    .and_then(|e| e.checked_add(n_b))
313                    .ok_or(ValidationError::InvalidExponents)?;
314
315                Ok((exponent, mantissa))
316            }
317        }
318    }
319
320    pub(crate) fn wavelet_transform(&self) -> WaveletTransform {
321        self.coding_style.parameters.transformation
322    }
323
324    pub(crate) fn num_resolution_levels(&self) -> u8 {
325        self.coding_style.parameters.num_resolution_levels
326    }
327
328    pub(crate) fn num_decomposition_levels(&self) -> u8 {
329        self.coding_style.parameters.num_decomposition_levels
330    }
331
332    pub(crate) fn code_block_style(&self) -> CodeBlockStyle {
333        self.coding_style.parameters.code_block_style
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use super::*;
340    use crate::J2kWaveletTransform;
341
342    #[test]
343    fn wavelet_transform_converts_to_external_selector() {
344        assert_eq!(
345            J2kWaveletTransform::from(WaveletTransform::Reversible53),
346            J2kWaveletTransform::Reversible53
347        );
348        assert_eq!(
349            J2kWaveletTransform::from(WaveletTransform::Irreversible97),
350            J2kWaveletTransform::Irreversible97
351        );
352    }
353}
354
355/// Progression order (Table A.16).
356#[derive(Debug, Clone, Copy)]
357pub(crate) enum ProgressionOrder {
358    LayerResolutionComponentPosition,
359    ResolutionLayerComponentPosition,
360    ResolutionPositionComponentLayer,
361    PositionComponentResolutionLayer,
362    ComponentPositionResolutionLayer,
363}
364
365#[derive(Debug, Clone)]
366pub(crate) struct ProgressionChange {
367    pub(crate) resolution_start: u8,
368    pub(crate) component_start: u8,
369    pub(crate) layer_end: u8,
370    pub(crate) resolution_end: u8,
371    pub(crate) component_end: u8,
372    pub(crate) progression_order: ProgressionOrder,
373}
374
375impl ProgressionOrder {
376    fn from_u8(value: u8) -> Result<Self> {
377        match value {
378            0 => Ok(Self::LayerResolutionComponentPosition),
379            1 => Ok(Self::ResolutionLayerComponentPosition),
380            2 => Ok(Self::ResolutionPositionComponentLayer),
381            3 => Ok(Self::PositionComponentResolutionLayer),
382            4 => Ok(Self::ComponentPositionResolutionLayer),
383            _ => err!(ValidationError::InvalidProgressionOrder),
384        }
385    }
386}
387
388/// Wavelet transformation type (Table A.20).
389#[derive(Debug, Clone, Copy, PartialEq, Eq)]
390pub(crate) enum WaveletTransform {
391    Irreversible97,
392    Reversible53,
393}
394
395impl WaveletTransform {
396    fn from_u8(value: u8) -> Result<Self> {
397        match value {
398            0 => Ok(Self::Irreversible97),
399            1 => Ok(Self::Reversible53),
400            _ => err!(ValidationError::InvalidTransformation),
401        }
402    }
403}
404
405impl From<WaveletTransform> for crate::J2kWaveletTransform {
406    fn from(transform: WaveletTransform) -> Self {
407        match transform {
408            WaveletTransform::Reversible53 => Self::Reversible53,
409            WaveletTransform::Irreversible97 => Self::Irreversible97,
410        }
411    }
412}
413
414/// Coding style flags (Table A.13).
415#[derive(Debug, Clone, Copy, Default)]
416pub(crate) struct CodingStyleFlags {
417    pub(crate) raw: u8,
418}
419
420impl CodingStyleFlags {
421    fn from_u8(value: u8) -> Self {
422        Self { raw: value }
423    }
424
425    pub(crate) fn has_precincts(&self) -> bool {
426        (self.raw & 0x01) != 0
427    }
428
429    pub(crate) fn may_use_sop_markers(&self) -> bool {
430        (self.raw & 0x02) != 0
431    }
432
433    pub(crate) fn uses_eph_marker(&self) -> bool {
434        (self.raw & 0x04) != 0
435    }
436}
437
438/// Code-block style flags (Table A.19).
439#[derive(Debug, Clone, Copy, Default)]
440pub(crate) struct CodeBlockStyle {
441    pub(crate) selective_arithmetic_coding_bypass: bool,
442    pub(crate) reset_context_probabilities: bool,
443    pub(crate) termination_on_each_pass: bool,
444    pub(crate) vertically_causal_context: bool,
445    pub(crate) segmentation_symbols: bool,
446    pub(crate) high_throughput_block_coding: bool,
447}
448
449impl CodeBlockStyle {
450    fn from_u8(value: u8) -> Self {
451        Self {
452            selective_arithmetic_coding_bypass: (value & 0x01) != 0,
453            reset_context_probabilities: (value & 0x02) != 0,
454            termination_on_each_pass: (value & 0x04) != 0,
455            vertically_causal_context: (value & 0x08) != 0,
456            // The predictable termination flag is only informative and
457            // can therefore be ignored.
458            segmentation_symbols: (value & 0x20) != 0,
459            high_throughput_block_coding: (value & 0x40) != 0,
460        }
461    }
462
463    pub(crate) fn uses_high_throughput_block_coding(&self) -> bool {
464        self.high_throughput_block_coding
465    }
466}
467
468/// Quantization style (Table A.28).
469#[derive(Debug, Clone, Copy, PartialEq, Eq)]
470pub(crate) enum QuantizationStyle {
471    NoQuantization,
472    ScalarDerived,
473    ScalarExpounded,
474}
475
476impl QuantizationStyle {
477    fn from_u8(value: u8) -> Result<Self> {
478        match value & 0x1F {
479            0 => Ok(Self::NoQuantization),
480            1 => Ok(Self::ScalarDerived),
481            2 => Ok(Self::ScalarExpounded),
482            _ => err!(ValidationError::InvalidQuantizationStyle),
483        }
484    }
485}
486
487#[derive(Clone, Copy, Debug)]
488pub(crate) struct StepSize {
489    pub(crate) mantissa: u16,
490    pub(crate) exponent: u16,
491}
492
493/// Quantization properties, from the QCD and QCC markers (A.6.4 and A.6.5).
494#[derive(Clone, Debug)]
495pub(crate) struct QuantizationInfo {
496    pub(crate) quantization_style: QuantizationStyle,
497    pub(crate) guard_bits: u8,
498    pub(crate) step_sizes: Vec<StepSize>,
499}
500
501/// Default values for coding style, from the COD marker (A.6.1).
502#[derive(Debug, Clone)]
503pub(crate) struct CodingStyleDefault {
504    pub(crate) progression_order: ProgressionOrder,
505    pub(crate) num_layers: u8,
506    pub(crate) mct: bool,
507    // This is the default used for all components, if not overridden by COC.
508    pub(crate) component_parameters: CodingStyleComponent,
509}
510
511/// Values of coding style for each component, from the COC marker (A.6.2).
512#[derive(Clone, Debug)]
513pub(crate) struct CodingStyleComponent {
514    pub(crate) flags: CodingStyleFlags,
515    pub(crate) parameters: CodingStyleParameters,
516}
517
518/// Shared parameters between the COC and COD marker (A.6.1 and A.6.2).
519#[derive(Clone, Debug)]
520pub(crate) struct CodingStyleParameters {
521    pub(crate) num_decomposition_levels: u8,
522    pub(crate) num_resolution_levels: u8,
523    pub(crate) code_block_width: u8,
524    pub(crate) code_block_height: u8,
525    pub(crate) code_block_style: CodeBlockStyle,
526    pub(crate) transformation: WaveletTransform,
527    pub(crate) precinct_exponents: Vec<(u8, u8)>,
528}
529
530#[derive(Debug)]
531pub(crate) struct SizeData {
532    /// Width of the reference grid (Xsiz).
533    pub(crate) reference_grid_width: u32,
534    /// Height of the reference grid (Ysiz).
535    pub(crate) reference_grid_height: u32,
536    /// Horizontal offset from the origin of the reference grid to the
537    /// left side of the image area (`XOsiz`).
538    pub(crate) image_area_x_offset: u32,
539    /// Vertical offset from the origin of the reference grid to the top side of the image area (`YOsiz`).
540    pub(crate) image_area_y_offset: u32,
541    /// Width of one reference tile with respect to the reference grid (`XTSiz`).
542    pub(crate) tile_width: u32,
543    /// Height of one reference tile with respect to the reference grid (`YTSiz`).
544    pub(crate) tile_height: u32,
545    /// Horizontal offset from the origin of the reference grid to the left side of the first tile (`XTOSiz`).
546    pub(crate) tile_x_offset: u32,
547    /// Vertical offset from the origin of the reference grid to the top side of the first tile (`YTOSiz`).
548    pub(crate) tile_y_offset: u32,
549    /// Component information (SSiz/XRSiz/YRSiz).
550    pub(crate) component_sizes: Vec<ComponentSizeInfo>,
551    /// Shrink factor in the x direction. See the comment in the parsing method.
552    pub(crate) x_shrink_factor: u32,
553    /// Shrink factor in the y direction. See the comment in the parsing method.
554    pub(crate) y_shrink_factor: u32,
555    /// Shrink factor in the x direction due to requesting a lower resolution level.
556    pub(crate) x_resolution_shrink_factor: u32,
557    /// Shrink factor in the y direction due to requesting a lower resolution level.
558    pub(crate) y_resolution_shrink_factor: u32,
559}
560
561impl SizeData {
562    pub(crate) fn tile_x_coord(&self, idx: u32) -> u32 {
563        // See B-6.
564        idx % self.num_x_tiles()
565    }
566
567    pub(crate) fn tile_y_coord(&self, idx: u32) -> u32 {
568        // See B-6.
569        idx / self.num_x_tiles()
570    }
571}
572
573/// Component information (A.5.1 and Table A.11).
574#[derive(Debug, Clone, Copy)]
575pub(crate) struct ComponentSizeInfo {
576    pub(crate) precision: u8,
577    pub(crate) horizontal_resolution: u8,
578    pub(crate) vertical_resolution: u8,
579}
580
581impl SizeData {
582    /// The number of tiles in the x direction.
583    pub(crate) fn num_x_tiles(&self) -> u32 {
584        // See formula B-5.
585        (self.reference_grid_width - self.tile_x_offset).div_ceil(self.tile_width)
586    }
587
588    /// The number of tiles in the y direction.
589    pub(crate) fn num_y_tiles(&self) -> u32 {
590        // See formula B-5.
591        (self.reference_grid_height - self.tile_y_offset).div_ceil(self.tile_height)
592    }
593
594    /// The total number of tiles.
595    ///
596    /// Saturating: `size_marker` rejects grids beyond `MAX_TILES`, so any
597    /// validated header stays far below the saturation point; saturation only
598    /// keeps unvalidated values panic-free.
599    pub(crate) fn num_tiles(&self) -> u32 {
600        self.num_x_tiles().saturating_mul(self.num_y_tiles())
601    }
602
603    /// Return the overall width of the image.
604    pub(crate) fn image_width(&self) -> u32 {
605        (self.reference_grid_width - self.image_area_x_offset)
606            .div_ceil(self.x_shrink_factor * self.x_resolution_shrink_factor)
607    }
608
609    /// Return the overall height of the image.
610    pub(crate) fn image_height(&self) -> u32 {
611        (self.reference_grid_height - self.image_area_y_offset)
612            .div_ceil(self.y_shrink_factor * self.y_resolution_shrink_factor)
613    }
614}
615
616/// SIZ marker (A.5.1).
617fn size_marker(reader: &mut BitReader<'_>) -> Result<SizeData> {
618    let size_data = size_marker_inner(reader)?;
619
620    if size_data.tile_width == 0
621        || size_data.tile_height == 0
622        || size_data.reference_grid_width == 0
623        || size_data.reference_grid_height == 0
624    {
625        bail!(ValidationError::InvalidDimensions);
626    }
627
628    if size_data.tile_x_offset >= size_data.reference_grid_width
629        || size_data.tile_y_offset >= size_data.reference_grid_height
630    {
631        bail!(ValidationError::InvalidDimensions);
632    }
633
634    // The tile grid offsets (XTOsiz, YTOsiz) are constrained to be no greater than the
635    // image area offsets (B-3).
636    if size_data.tile_x_offset > size_data.image_area_x_offset
637        || size_data.tile_y_offset > size_data.image_area_y_offset
638    {
639        bail!(crate::TileError::InvalidOffsets);
640    }
641
642    // Also, the tile size plus the tile offset shall be greater than the image area offset.
643    // This ensures that the first tile (tile 0) will contain at least one reference grid point
644    // from the image area (B-4).
645    if size_data
646        .tile_x_offset
647        .checked_add(size_data.tile_width)
648        .ok_or(crate::TileError::InvalidOffsets)?
649        <= size_data.image_area_x_offset
650        || size_data
651            .tile_y_offset
652            .checked_add(size_data.tile_height)
653            .ok_or(crate::TileError::InvalidOffsets)?
654            <= size_data.image_area_y_offset
655    {
656        bail!(crate::TileError::InvalidOffsets);
657    }
658
659    for comp in &size_data.component_sizes {
660        if comp.precision == 0 || comp.vertical_resolution == 0 || comp.horizontal_resolution == 0 {
661            bail!(ValidationError::InvalidComponentMetadata);
662        }
663    }
664
665    if size_data.image_width() > crate::MAX_J2K_IMAGE_DIMENSION
666        || size_data.image_height() > crate::MAX_J2K_IMAGE_DIMENSION
667    {
668        bail!(ValidationError::ImageTooLarge);
669    }
670
671    // Isot is a u16, so no conforming codestream addresses more than 65,536
672    // tiles (the encoder enforces the same ceiling). Rejecting here also stops
673    // crafted SIZ values from overflowing num_tiles() or driving the eager
674    // per-tile allocation in tile parsing.
675    let num_tiles = u64::from(size_data.num_x_tiles()) * u64::from(size_data.num_y_tiles());
676    if num_tiles > crate::MAX_J2K_TILE_COUNT {
677        bail!(ValidationError::TooManyTiles);
678    }
679
680    Ok(size_data)
681}
682
683fn read_siz_byte(reader: &mut BitReader<'_>) -> Result<u8> {
684    reader
685        .read_byte()
686        .ok_or(MarkerError::ParseFailure("SIZ").into())
687}
688
689fn read_siz_u16(reader: &mut BitReader<'_>) -> Result<u16> {
690    reader
691        .read_u16()
692        .ok_or(MarkerError::ParseFailure("SIZ").into())
693}
694
695fn read_siz_u32(reader: &mut BitReader<'_>) -> Result<u32> {
696    reader
697        .read_u32()
698        .ok_or(MarkerError::ParseFailure("SIZ").into())
699}
700
701fn size_marker_inner(reader: &mut BitReader<'_>) -> Result<SizeData> {
702    // Length.
703    let _ = read_siz_u16(reader)?;
704    // Decoder capabilities.
705    let _ = read_siz_u16(reader)?;
706
707    let xsiz = read_siz_u32(reader)?;
708    let ysiz = read_siz_u32(reader)?;
709    let x_osiz = read_siz_u32(reader)?;
710    let y_osiz = read_siz_u32(reader)?;
711    let xt_siz = read_siz_u32(reader)?;
712    let yt_siz = read_siz_u32(reader)?;
713    let xto_siz = read_siz_u32(reader)?;
714    let yto_siz = read_siz_u32(reader)?;
715    let csiz = read_siz_u16(reader)?;
716
717    if x_osiz >= xsiz || y_osiz >= ysiz {
718        bail!(ValidationError::InvalidDimensions);
719    }
720
721    if csiz == 0 {
722        bail!(ValidationError::InvalidComponentMetadata);
723    }
724
725    if csiz > MAX_J2K_SPEC_COMPONENTS || csiz > MAX_NATIVE_DECODE_COMPONENTS {
726        bail!(ValidationError::TooManyChannels);
727    }
728
729    let mut components = Vec::with_capacity(csiz as usize);
730    for _ in 0..csiz {
731        let ssiz = read_siz_byte(reader)?;
732        let x_rsiz = read_siz_byte(reader)?;
733        let y_rsiz = read_siz_byte(reader)?;
734
735        let precision = (ssiz & 0x7F) + 1;
736        // No idea how to process signed images, but as far as I can tell
737        // openjpeg and others just accept it as is, so let's do the same.
738        let _is_signed = (ssiz & 0x80) != 0;
739
740        // In theory up to 38 is allowed, but we don't support more than that.
741        if precision as u32 > BITPLANE_BIT_SIZE {
742            bail!(ValidationError::InvalidComponentMetadata);
743        }
744
745        components.push(ComponentSizeInfo {
746            precision,
747            horizontal_resolution: x_rsiz,
748            vertical_resolution: y_rsiz,
749        });
750    }
751
752    // In case all components are sub-sampled at the same level, we
753    // don't want to render them at the original resolution but instead
754    // reduce their dimension so that we can assume a resolution of 1 for
755    // all components. This makes the images much smaller.
756
757    let mut x_shrink_factor = 1;
758    let mut y_shrink_factor = 1;
759
760    let hr = components[0].horizontal_resolution;
761    let vr = components[0].vertical_resolution;
762    let mut same_resolution = true;
763
764    for component in &components[1..] {
765        same_resolution &= component.horizontal_resolution == hr;
766        same_resolution &= component.vertical_resolution == vr;
767    }
768
769    if same_resolution {
770        x_shrink_factor = hr as u32;
771        y_shrink_factor = vr as u32;
772    }
773
774    Ok(SizeData {
775        reference_grid_width: xsiz,
776        reference_grid_height: ysiz,
777        image_area_x_offset: x_osiz,
778        image_area_y_offset: y_osiz,
779        tile_width: xt_siz,
780        tile_height: yt_siz,
781        tile_x_offset: xto_siz,
782        tile_y_offset: yto_siz,
783        component_sizes: components,
784        x_shrink_factor,
785        y_shrink_factor,
786        x_resolution_shrink_factor: 1,
787        y_resolution_shrink_factor: 1,
788    })
789}
790
791fn coding_style_parameters(
792    reader: &mut BitReader<'_>,
793    coding_style: &CodingStyleFlags,
794) -> Option<CodingStyleParameters> {
795    let num_decomposition_levels = reader.read_byte()?;
796
797    if num_decomposition_levels > MAX_RESOLUTION_COUNT {
798        return None;
799    }
800
801    let num_resolution_levels = num_decomposition_levels.checked_add(1)?;
802    let code_block_width = reader.read_byte()?.checked_add(2)?;
803    let code_block_height = reader.read_byte()?.checked_add(2)?;
804    let code_block_style = CodeBlockStyle::from_u8(reader.read_byte()?);
805    let transformation = WaveletTransform::from_u8(reader.read_byte()?).ok()?;
806
807    let mut precinct_exponents = Vec::new();
808    if coding_style.has_precincts() {
809        // "Entropy coder with precincts defined below."
810        for _ in 0..num_resolution_levels {
811            // Table A.21.
812            let precinct_size = reader.read_byte()?;
813            let width_exp = precinct_size & 0xF;
814            let height_exp = precinct_size >> 4;
815
816            if width_exp > MAX_PRECINCT_EXPONENT || height_exp > MAX_PRECINCT_EXPONENT {
817                return None;
818            }
819
820            precinct_exponents.push((width_exp, height_exp));
821        }
822    } else {
823        // "Entropy coder, precincts with PPx = 15 and PPy = 15"
824        for _ in 0..num_resolution_levels {
825            precinct_exponents.push((15, 15));
826        }
827    }
828
829    Some(CodingStyleParameters {
830        num_decomposition_levels,
831        num_resolution_levels,
832        code_block_width,
833        code_block_height,
834        code_block_style,
835        transformation,
836        precinct_exponents,
837    })
838}
839
840/// COM Marker (A.9.2).
841fn com_marker(reader: &mut BitReader<'_>) -> Option<()> {
842    skip_marker_segment(reader)
843}
844
845/// TLM marker (A.7.1).
846fn tlm_marker(reader: &mut BitReader<'_>) -> Option<()> {
847    skip_marker_segment(reader)
848}
849
850/// PLM marker (A.7.2).
851fn plm_marker(reader: &mut BitReader<'_>) -> Option<PacketLengthMarker> {
852    let segment_len = reader.read_u16()?.checked_sub(2)? as usize;
853    let segment = reader.read_bytes(segment_len)?;
854    let mut reader = BitReader::new(segment);
855
856    let sequence_idx = reader.read_byte()?;
857    let mut packet_lengths = vec![];
858
859    while !reader.at_end() {
860        let length_data_len = reader.read_u32()? as usize;
861        let length_data = reader.read_bytes(length_data_len)?;
862        packet_lengths.extend(decode_packet_lengths(length_data)?);
863    }
864
865    Some(PacketLengthMarker {
866        sequence_idx,
867        packet_lengths,
868    })
869}
870
871/// PLT marker (A.7.3).
872pub(crate) fn plt_marker(reader: &mut BitReader<'_>) -> Option<PacketLengthMarker> {
873    let segment_len = reader.read_u16()?.checked_sub(2)? as usize;
874    let segment = reader.read_bytes(segment_len)?;
875    let mut reader = BitReader::new(segment);
876
877    let sequence_idx = reader.read_byte()?;
878    let packet_lengths = decode_packet_lengths(reader.tail()?)?;
879
880    Some(PacketLengthMarker {
881        sequence_idx,
882        packet_lengths,
883    })
884}
885
886pub(crate) fn decode_packet_lengths(data: &[u8]) -> Option<Vec<u32>> {
887    let mut packet_lengths = vec![];
888    let mut value = 0_u32;
889    let mut in_progress = false;
890
891    for byte in data {
892        value = value.checked_shl(7)?.checked_add(u32::from(byte & 0x7F))?;
893        in_progress = true;
894
895        if byte & 0x80 == 0 {
896            packet_lengths.push(value);
897            value = 0;
898            in_progress = false;
899        }
900    }
901
902    if in_progress {
903        return None;
904    }
905
906    Some(packet_lengths)
907}
908
909/// PPM marker (A.7.4).
910fn ppm_marker<'a>(reader: &mut BitReader<'a>) -> Option<PpmMarkerData<'a>> {
911    let segment_len = reader.read_u16()?.checked_sub(2)? as usize;
912    let ppm_data = reader.read_bytes(segment_len)?;
913    let mut packets = vec![];
914
915    let mut reader = BitReader::new(ppm_data);
916    let sequence_idx = reader.read_byte()?;
917
918    // This parser handles complete packet payloads carried by the current PPM
919    // marker. Continuations across multiple PPM markers are rejected by normal
920    // length parsing until a multi-marker accumulator is added.
921    while !reader.at_end() {
922        let packet_len = reader.read_u16()? as usize;
923        let data = reader.read_bytes(packet_len)?;
924
925        packets.push(PpmPacket { data });
926    }
927
928    Some(PpmMarkerData {
929        sequence_idx,
930        packets,
931    })
932}
933
934/// RGN marker (A.6.3).
935pub(crate) fn rgn_marker(reader: &mut BitReader<'_>, csiz: u16) -> Option<RgnMarkerData> {
936    let length = reader.read_u16()?;
937    let component_index_bytes = if csiz < 257 { 1 } else { 2 };
938    if length != 4 + component_index_bytes {
939        return None;
940    }
941
942    let component_index = read_component_index(reader, csiz)?;
943    if component_index >= csiz {
944        return None;
945    }
946
947    let style = reader.read_byte()?;
948    let shift = reader.read_byte()?;
949
950    Some(RgnMarkerData {
951        component_index,
952        style,
953        shift,
954    })
955}
956
957#[derive(Debug, Clone, Copy, PartialEq, Eq)]
958pub(crate) struct RgnMarkerData {
959    pub(crate) component_index: u16,
960    pub(crate) style: u8,
961    pub(crate) shift: u8,
962}
963
964pub(crate) fn skip_marker_segment(reader: &mut BitReader<'_>) -> Option<()> {
965    let length = reader.read_u16()?.checked_sub(2)?;
966    reader.skip_bytes(length as usize)?;
967
968    Some(())
969}
970
971/// COD marker (A.6.1).
972pub(crate) fn cod_marker(reader: &mut BitReader<'_>) -> Option<CodingStyleDefault> {
973    // Length.
974    let _ = reader.read_u16()?;
975
976    let coding_style_flags = CodingStyleFlags::from_u8(reader.read_byte()?);
977    let progression_order = ProgressionOrder::from_u8(reader.read_byte()?).ok()?;
978
979    let num_layers = reader.read_u16()?;
980
981    // We don't support more than 32-bit (and thus 32 layers).
982    if num_layers == 0 || num_layers > MAX_LAYER_COUNT as u16 {
983        return None;
984    }
985
986    let mct = reader.read_byte()? == 1;
987
988    let coding_style_parameters = coding_style_parameters(reader, &coding_style_flags)?;
989
990    Some(CodingStyleDefault {
991        progression_order,
992        num_layers: num_layers as u8,
993        mct,
994        component_parameters: CodingStyleComponent {
995            flags: coding_style_flags,
996            parameters: coding_style_parameters,
997        },
998    })
999}
1000
1001/// COC marker (A.6.2).
1002pub(crate) fn coc_marker(
1003    reader: &mut BitReader<'_>,
1004    csiz: u16,
1005) -> Option<(u16, CodingStyleComponent)> {
1006    // Length.
1007    let _ = reader.read_u16()?;
1008
1009    let component_index = if csiz < 257 {
1010        reader.read_byte()? as u16
1011    } else {
1012        reader.read_u16()?
1013    };
1014    let coding_style = CodingStyleFlags::from_u8(reader.read_byte()?);
1015
1016    let parameters = coding_style_parameters(reader, &coding_style)?;
1017
1018    let coc = CodingStyleComponent {
1019        flags: coding_style,
1020        parameters,
1021    };
1022
1023    Some((component_index, coc))
1024}
1025
1026/// QCD marker (A.6.4).
1027pub(crate) fn qcd_marker(reader: &mut BitReader<'_>) -> Option<QuantizationInfo> {
1028    // Length.
1029    let length = reader.read_u16()?;
1030
1031    let sqcd_val = reader.read_byte()?;
1032    let quantization_style = QuantizationStyle::from_u8(sqcd_val & 0x1F).ok()?;
1033    let guard_bits = (sqcd_val >> 5) & 0x07;
1034
1035    let remaining_bytes = length.checked_sub(3)? as usize;
1036
1037    let mut parameters = quantization_parameters(reader, quantization_style, remaining_bytes)?;
1038    parameters.guard_bits = guard_bits;
1039
1040    Some(parameters)
1041}
1042
1043/// QCC marker (A.6.5).
1044pub(crate) fn qcc_marker(reader: &mut BitReader<'_>, csiz: u16) -> Option<(u16, QuantizationInfo)> {
1045    let length = reader.read_u16()?;
1046
1047    let component_index = if csiz < 257 {
1048        reader.read_byte()? as u16
1049    } else {
1050        reader.read_u16()?
1051    };
1052
1053    let sqcc_val = reader.read_byte()?;
1054    let quantization_style = QuantizationStyle::from_u8(sqcc_val & 0x1F).ok()?;
1055    let guard_bits = (sqcc_val >> 5) & 0x07;
1056
1057    let component_index_size = if csiz < 257 { 1 } else { 2 };
1058    let remaining_bytes = length
1059        .checked_sub(2)?
1060        .checked_sub(component_index_size)?
1061        .checked_sub(1)? as usize;
1062
1063    let mut parameters = quantization_parameters(reader, quantization_style, remaining_bytes)?;
1064    parameters.guard_bits = guard_bits;
1065
1066    Some((component_index, parameters))
1067}
1068
1069/// POC marker (A.6.6).
1070pub(crate) fn poc_marker(
1071    reader: &mut BitReader<'_>,
1072    csiz: u16,
1073    _num_layers: u8,
1074) -> Option<Vec<ProgressionChange>> {
1075    let length = reader.read_u16()?;
1076    let remaining_bytes = length.checked_sub(2)?;
1077    let component_index_size = if csiz < 257 { 1u16 } else { 2u16 };
1078    let change_size = 1 + component_index_size + 2 + 1 + component_index_size + 1;
1079    if remaining_bytes == 0 || remaining_bytes % change_size != 0 {
1080        return None;
1081    }
1082
1083    let change_count = remaining_bytes / change_size;
1084    let mut changes = Vec::with_capacity(change_count as usize);
1085    for _ in 0..change_count {
1086        let resolution_start = reader.read_byte()?;
1087        let component_start = read_component_index(reader, csiz)?;
1088        let layer_end = reader.read_u16()?;
1089        let resolution_end = reader.read_byte()?;
1090        let component_end = read_component_index(reader, csiz)?;
1091        let progression_order = ProgressionOrder::from_u8(reader.read_byte()?).ok()?;
1092
1093        if resolution_start >= resolution_end
1094            || component_start >= component_end
1095            || component_start >= csiz
1096            || layer_end == 0
1097            || layer_end > u16::from(u8::MAX)
1098            || component_end > u16::from(u8::MAX)
1099        {
1100            return None;
1101        }
1102
1103        changes.push(ProgressionChange {
1104            resolution_start,
1105            component_start: component_start as u8,
1106            layer_end: layer_end as u8,
1107            resolution_end,
1108            component_end: component_end as u8,
1109            progression_order,
1110        });
1111    }
1112
1113    Some(changes)
1114}
1115
1116fn read_component_index(reader: &mut BitReader<'_>, csiz: u16) -> Option<u16> {
1117    if csiz < 257 {
1118        Some(u16::from(reader.read_byte()?))
1119    } else {
1120        reader.read_u16()
1121    }
1122}
1123
1124fn quantization_parameters(
1125    reader: &mut BitReader<'_>,
1126    quantization_style: QuantizationStyle,
1127    remaining_bytes: usize,
1128) -> Option<QuantizationInfo> {
1129    let mut step_sizes = Vec::new();
1130
1131    let irreversible = |val: u16| {
1132        let exponent = val >> 11;
1133        let mantissa = val & ((1 << 11) - 1);
1134
1135        StepSize { exponent, mantissa }
1136    };
1137
1138    match quantization_style {
1139        QuantizationStyle::NoQuantization => {
1140            // 8 bits per band (5 bits exponent, 3 bits reserved)
1141            for _ in 0..remaining_bytes {
1142                let value = reader.read_byte()? as u16;
1143                step_sizes.push(StepSize {
1144                    // Unused.
1145                    mantissa: 0,
1146                    exponent: (value >> 3),
1147                });
1148            }
1149        }
1150        QuantizationStyle::ScalarDerived => {
1151            let value = reader.read_u16()?;
1152            step_sizes.push(irreversible(value));
1153        }
1154        QuantizationStyle::ScalarExpounded => {
1155            let num_bands = remaining_bytes / 2;
1156            for _ in 0..num_bands {
1157                let value = reader.read_u16()?;
1158
1159                step_sizes.push(irreversible(value));
1160            }
1161        }
1162    }
1163
1164    Some(QuantizationInfo {
1165        quantization_style,
1166        guard_bits: 0,
1167        step_sizes,
1168    })
1169}
1170
1171#[allow(
1172    unused,
1173    reason = "Not all marker codes are used in every decoding path yet"
1174)]
1175/// Marker codes (Table A.2).
1176pub(crate) mod markers {
1177    /// Start of codestream - 'SOC'.
1178    pub(crate) const SOC: u8 = 0x4F;
1179    /// Start of tile-part - 'SOT'.
1180    pub(crate) const SOT: u8 = 0x90;
1181    /// Start of data - 'SOD'.
1182    pub(crate) const SOD: u8 = 0x93;
1183    /// End of codestream - 'EOC'.
1184    pub(crate) const EOC: u8 = 0xD9;
1185
1186    /// Extended capabilities - 'CAP'.
1187    pub(crate) const CAP: u8 = 0x50;
1188    /// Image and tile size - 'SIZ'.
1189    pub(crate) const SIZ: u8 = 0x51;
1190
1191    /// Coding style default - 'COD'.
1192    pub(crate) const COD: u8 = 0x52;
1193    /// Coding component - 'COC'.
1194    pub(crate) const COC: u8 = 0x53;
1195    /// Region-of-interest - 'RGN'.
1196    pub(crate) const RGN: u8 = 0x5E;
1197    /// Quantization default - 'QCD'.
1198    pub(crate) const QCD: u8 = 0x5C;
1199    /// Quantization component - 'QCC'.
1200    pub(crate) const QCC: u8 = 0x5D;
1201    /// Progression order change - 'POC'.
1202    pub(crate) const POC: u8 = 0x5F;
1203
1204    /// Tile-part lengths - 'TLM'.
1205    pub(crate) const TLM: u8 = 0x55;
1206    /// Packet length, main header - 'PLM'.
1207    pub(crate) const PLM: u8 = 0x57;
1208    /// Packet length, tile-part header - 'PLT'.
1209    pub(crate) const PLT: u8 = 0x58;
1210    /// Corresponding profile - 'CPF'.
1211    pub(crate) const CPF: u8 = 0x59;
1212    /// Packed packet headers, main header - 'PPM'.
1213    pub(crate) const PPM: u8 = 0x60;
1214    /// Packed packet headers, tile-part header - 'PPT'.
1215    pub(crate) const PPT: u8 = 0x61;
1216
1217    /// Start of packet - 'SOP'.
1218    pub(crate) const SOP: u8 = 0x91;
1219    /// End of packet header - 'EPH'.
1220    pub(crate) const EPH: u8 = 0x92;
1221
1222    /// Component registration - 'CRG'.
1223    pub(crate) const CRG: u8 = 0x63;
1224    /// Comment - 'COM'.
1225    pub(crate) const COM: u8 = 0x64;
1226
1227    pub(crate) fn to_string(marker: u8) -> &'static str {
1228        match marker {
1229            // Delimiting markers.
1230            SOC => "SOC",
1231            SOT => "SOT",
1232            SOD => "SOD",
1233            EOC => "EOC",
1234
1235            // Fixed information.
1236            CAP => "CAP",
1237            SIZ => "SIZ",
1238
1239            // Functional markers.
1240            COD => "COD",
1241            COC => "COC",
1242            RGN => "RGN",
1243            QCD => "QCD",
1244            QCC => "QCC",
1245            POC => "POC",
1246
1247            // Pointer markers.
1248            TLM => "TLM",
1249            PLM => "PLM",
1250            PLT => "PLT",
1251            CPF => "CPF",
1252            PPM => "PPM",
1253            PPT => "PPT",
1254
1255            // In-bit-stream markers.
1256            SOP => "SOP",
1257            EPH => "EPH",
1258
1259            // Informational markers.
1260            CRG => "CRG",
1261            COM => "COM",
1262
1263            _ => "UNKNOWN",
1264        }
1265    }
1266}