Skip to main content

pdfluent_jpeg2000/j2c/
decode.rs

1//! Decoding JPEG2000 code streams.
2//!
3//! This is the "core" module of the crate that orchestrates all
4//! stages in such a way that a given codestream is decoded into its
5//! component channels.
6
7use alloc::boxed::Box;
8use alloc::vec::Vec;
9
10use super::bitplane::{BitPlaneDecodeBuffers, BitPlaneDecodeContext};
11use super::build::{CodeBlock, Decomposition, Layer, Precinct, Segment, SubBand, SubBandType};
12use super::codestream::{
13    ComponentInfo, Header, ProgressionOrder, QuantizationStyle, WaveletTransform,
14};
15use super::idwt::IDWTOutput;
16use super::progression::{
17    IteratorInput, ProgressionData, component_position_resolution_layer_progression,
18    layer_resolution_component_position_progression,
19    position_component_resolution_layer_progression,
20    resolution_layer_component_position_progression,
21    resolution_position_component_layer_progression,
22};
23use super::tag_tree::TagNode;
24use super::tile::{ComponentTile, ResolutionTile, Tile};
25use super::{ComponentData, bitplane, build, idwt, mct, segment, tile};
26use crate::error::{DecodingError, Result, TileError, ValidationError, bail};
27use crate::j2c::segment::MAX_BITPLANE_COUNT;
28use crate::math::SimdBuffer;
29use crate::reader::BitReader;
30use core::ops::Range;
31
32pub(crate) fn decode<'a>(
33    data: &'a [u8],
34    header: &'a Header<'a>,
35    ctx: &mut DecoderContext<'a>,
36) -> Result<()> {
37    let mut reader = BitReader::new(data);
38    let tiles = tile::parse(&mut reader, header)?;
39
40    if tiles.is_empty() {
41        bail!(TileError::Invalid);
42    }
43
44    ctx.reset(header, &tiles[0])?;
45
46    for tile in &tiles {
47        trace!(
48            "tile {} rect [{},{} {}x{}]",
49            tile.idx,
50            tile.rect.x0,
51            tile.rect.y0,
52            tile.rect.width(),
53            tile.rect.height(),
54        );
55
56        let iter_input = IteratorInput::new(tile);
57
58        let progression_iterator: Box<dyn Iterator<Item = ProgressionData>> =
59            match tile.progression_order {
60                ProgressionOrder::LayerResolutionComponentPosition => {
61                    Box::new(layer_resolution_component_position_progression(iter_input))
62                }
63                ProgressionOrder::ResolutionLayerComponentPosition => {
64                    Box::new(resolution_layer_component_position_progression(iter_input))
65                }
66                ProgressionOrder::ResolutionPositionComponentLayer => Box::new(
67                    resolution_position_component_layer_progression(iter_input)
68                        .ok_or(DecodingError::InvalidProgressionIterator)?,
69                ),
70                ProgressionOrder::PositionComponentResolutionLayer => Box::new(
71                    position_component_resolution_layer_progression(iter_input)
72                        .ok_or(DecodingError::InvalidProgressionIterator)?,
73                ),
74                ProgressionOrder::ComponentPositionResolutionLayer => Box::new(
75                    component_position_resolution_layer_progression(iter_input)
76                        .ok_or(DecodingError::InvalidProgressionIterator)?,
77                ),
78            };
79
80        decode_tile(
81            tile,
82            header,
83            progression_iterator,
84            &mut ctx.tile_decode_context,
85            &mut ctx.channel_data,
86            &mut ctx.storage,
87        )?;
88    }
89
90    // Note that this assumes that either all tiles have MCT or none of them.
91    // In theory, only some could have it... But hopefully no such cursed
92    // images exist!
93    if tiles[0].mct {
94        mct::apply_inverse(&mut ctx.channel_data, &tiles[0].component_infos, header)?;
95    }
96
97    apply_sign_shift(&mut ctx.channel_data, &header.component_infos);
98
99    Ok(())
100}
101
102/// A decoder context for decoding JPEG2000 images.
103#[derive(Default)]
104pub struct DecoderContext<'a> {
105    tile_decode_context: TileDecodeContext,
106    /// The raw, decoded samples for each channel.
107    pub(crate) channel_data: Vec<ComponentData>,
108    storage: DecompositionStorage<'a>,
109}
110
111impl DecoderContext<'_> {
112    fn reset(&mut self, header: &Header<'_>, initial_tile: &Tile<'_>) -> Result<()> {
113        self.tile_decode_context.reset();
114        self.storage.reset();
115
116        self.channel_data.clear();
117        let sample_count = (header.size_data.image_width() as usize)
118            .checked_mul(header.size_data.image_height() as usize)
119            .ok_or(ValidationError::ImageTooLarge)?;
120        // TODO: SIMD Buffers should be reused across runs!
121        for info in &initial_tile.component_infos {
122            self.channel_data.push(ComponentData {
123                container: SimdBuffer::zeros(sample_count),
124                bit_depth: info.size_info.precision,
125            });
126        }
127
128        Ok(())
129    }
130}
131
132fn decode_tile<'a, 'b>(
133    tile: &'b Tile<'a>,
134    header: &Header<'_>,
135    progression_iterator: Box<dyn Iterator<Item = ProgressionData> + '_>,
136    tile_ctx: &mut TileDecodeContext,
137    channel_data: &mut [ComponentData],
138    storage: &mut DecompositionStorage<'a>,
139) -> Result<()> {
140    storage.reset();
141
142    // This is the method that orchestrates all steps.
143
144    // First, we build the decompositions, including their sub-bands, precincts
145    // and code blocks.
146    build::build(tile, storage, header.skipped_resolution_levels)?;
147    // Next, we parse the layers/segments for each code block.
148    segment::parse(tile, progression_iterator, header, storage)?;
149    // We then decode the bitplanes of each code block, yielding the
150    // (possibly dequantized) coefficients of each code block.
151    decode_component_tile_bit_planes(tile, tile_ctx, storage, header)?;
152
153    // Unlike before, we interleave the apply_idwt and store stages
154    // for each component tile so we can reuse allocations better.
155    for (idx, component_info) in header.component_infos.iter().enumerate() {
156        // Next, we apply the inverse discrete wavelet transform.
157        idwt::apply(
158            storage,
159            tile_ctx,
160            idx,
161            header,
162            component_info.wavelet_transform(),
163        );
164        // Finally, we store the raw samples for the tile area in the correct
165        // location. Note that in case we have MCT, we are not applying it yet.
166        // It will be applied in the very end once all tiles have been processed.
167        // The reason we do this is that applying MCT requires access to the
168        // data from _all_ components. If we didn't defer this until the end
169        // we would have to collect the IDWT outputs of all components before
170        // applying it. By not applying MCT here, we can get away with doing
171        // IDWT and store on a per-component basis. Thus, we only need to
172        // store one IDWT output at a time, allowing for better reuse of
173        // allocations.
174        store(
175            tile,
176            header,
177            tile_ctx,
178            &mut channel_data[idx],
179            component_info,
180        );
181    }
182
183    Ok(())
184}
185
186/// All decompositions for a single tile.
187#[derive(Clone)]
188pub(crate) struct TileDecompositions {
189    pub(crate) first_ll_sub_band: usize,
190    pub(crate) decompositions: Range<usize>,
191}
192
193impl TileDecompositions {
194    pub(crate) fn sub_band_iter(
195        &self,
196        resolution: u8,
197        decompositions: &[Decomposition],
198    ) -> SubBandIter {
199        let indices = if resolution == 0 {
200            [
201                self.first_ll_sub_band,
202                self.first_ll_sub_band,
203                self.first_ll_sub_band,
204            ]
205        } else {
206            decompositions[self.decompositions.clone()][resolution as usize - 1].sub_bands
207        };
208
209        SubBandIter {
210            next_idx: 0,
211            indices,
212            resolution,
213        }
214    }
215}
216
217#[derive(Clone)]
218pub(crate) struct SubBandIter {
219    resolution: u8,
220    next_idx: usize,
221    indices: [usize; 3],
222}
223
224impl Iterator for SubBandIter {
225    type Item = usize;
226
227    fn next(&mut self) -> Option<Self::Item> {
228        let value = if self.resolution == 0 {
229            if self.next_idx > 0 {
230                None
231            } else {
232                Some(self.indices[0])
233            }
234        } else if self.next_idx >= self.indices.len() {
235            None
236        } else {
237            Some(self.indices[self.next_idx])
238        };
239
240        self.next_idx += 1;
241
242        value
243    }
244}
245
246/// A buffer so that we can reuse allocations for layers/code blocks/etc.
247/// across different tiles.
248#[derive(Default)]
249pub(crate) struct DecompositionStorage<'a> {
250    pub(crate) segments: Vec<Segment<'a>>,
251    pub(crate) layers: Vec<Layer>,
252    pub(crate) code_blocks: Vec<CodeBlock>,
253    pub(crate) precincts: Vec<Precinct>,
254    pub(crate) tag_tree_nodes: Vec<TagNode>,
255    pub(crate) coefficients: Vec<f32>,
256    pub(crate) sub_bands: Vec<SubBand>,
257    pub(crate) decompositions: Vec<Decomposition>,
258    pub(crate) tile_decompositions: Vec<TileDecompositions>,
259}
260
261impl DecompositionStorage<'_> {
262    fn reset(&mut self) {
263        self.segments.clear();
264        self.layers.clear();
265        self.code_blocks.clear();
266        // No need to clear the coefficients, as they will be resized
267        // and then overridden.
268        // self.coefficients.clear();
269        self.precincts.clear();
270        self.sub_bands.clear();
271        self.decompositions.clear();
272        self.tile_decompositions.clear();
273        self.tag_tree_nodes.clear();
274    }
275}
276
277/// A reusable context used during the decoding of a single tile.
278///
279/// Some of the fields are temporary in nature and reset after moving on to the
280/// next tile, some contain global state.
281#[derive(Default)]
282pub(crate) struct TileDecodeContext {
283    /// A reusable buffer for the IDWT output.
284    pub(crate) idwt_output: IDWTOutput,
285    /// A scratch buffer used during IDWT.
286    pub(crate) idwt_scratch_buffer: Vec<f32>,
287    /// A reusable context for decoding code blocks.
288    pub(crate) bit_plane_decode_context: BitPlaneDecodeContext,
289    /// Reusable buffers for decoding bitplanes.
290    pub(crate) bit_plane_decode_buffers: BitPlaneDecodeBuffers,
291}
292
293impl TileDecodeContext {
294    fn reset(&mut self) {
295        // This method doesn't do anything, just keeping it there in case
296        // it's needed in the future.
297        // Bitplane decode context and buffers will be reset in the
298        // corresponding methods. IDWT output and scratch buffer will be
299        // overridden on demand, so those don't need to be reset either.
300    }
301}
302
303fn decode_component_tile_bit_planes<'a>(
304    tile: &Tile<'a>,
305    tile_ctx: &mut TileDecodeContext,
306    storage: &mut DecompositionStorage<'a>,
307    header: &Header<'_>,
308) -> Result<()> {
309    for (tile_decompositions_idx, component_info) in tile.component_infos.iter().enumerate() {
310        // Only decode the resolution levels we actually care about.
311        for resolution in
312            0..component_info.num_resolution_levels() - header.skipped_resolution_levels
313        {
314            let tile_composition = &storage.tile_decompositions[tile_decompositions_idx];
315            let sub_band_iter = tile_composition.sub_band_iter(resolution, &storage.decompositions);
316
317            for sub_band_idx in sub_band_iter {
318                decode_sub_band_bitplanes(
319                    sub_band_idx,
320                    resolution,
321                    component_info,
322                    tile_ctx,
323                    storage,
324                    header,
325                )?;
326            }
327        }
328    }
329
330    Ok(())
331}
332
333fn decode_sub_band_bitplanes(
334    sub_band_idx: usize,
335    resolution: u8,
336    component_info: &ComponentInfo,
337    tile_ctx: &mut TileDecodeContext,
338    storage: &mut DecompositionStorage<'_>,
339    header: &Header<'_>,
340) -> Result<()> {
341    let sub_band = &storage.sub_bands[sub_band_idx];
342
343    let quantised =
344        component_info.quantization_info.quantization_style != QuantizationStyle::NoQuantization;
345    let irreversible = component_info.wavelet_transform() == WaveletTransform::Irreversible97;
346    let dequantization_step = {
347        if !quantised {
348            1.0
349        } else {
350            let (exponent, mantissa) =
351                component_info.exponent_mantissa(sub_band.sub_band_type, resolution)?;
352
353            let r_b = {
354                let log_gain = match sub_band.sub_band_type {
355                    SubBandType::LowLow => 0,
356                    SubBandType::LowHigh => 1,
357                    SubBandType::HighLow => 1,
358                    SubBandType::HighHigh => 2,
359                };
360
361                component_info.size_info.precision as u16 + log_gain
362            };
363
364            crate::math::pow2i(r_b as i32 - exponent as i32) * (1.0 + (mantissa as f32) / 2048.0)
365        }
366    };
367
368    let num_bitplanes = {
369        let (exponent, _) = component_info.exponent_mantissa(sub_band.sub_band_type, resolution)?;
370        // Equation (E-2)
371        let num_bitplanes = (component_info.quantization_info.guard_bits as u16)
372            .checked_add(exponent)
373            .and_then(|x| x.checked_sub(1))
374            .ok_or(DecodingError::InvalidBitplaneCount)?;
375
376        if num_bitplanes > MAX_BITPLANE_COUNT as u16 {
377            bail!(DecodingError::TooManyBitplanes);
378        }
379
380        num_bitplanes as u8
381    };
382
383    for precinct in sub_band
384        .precincts
385        .clone()
386        .map(|idx| &storage.precincts[idx])
387    {
388        for code_block in precinct
389            .code_blocks
390            .clone()
391            .map(|idx| &storage.code_blocks[idx])
392        {
393            bitplane::decode(
394                code_block,
395                sub_band.sub_band_type,
396                num_bitplanes,
397                &component_info.coding_style.parameters.code_block_style,
398                tile_ctx,
399                storage,
400                header.strict,
401            )?;
402
403            // Turn the signs and magnitudes into singular coefficients and
404            // copy them into the sub-band.
405
406            let x_offset = code_block.rect.x0 - sub_band.rect.x0;
407            let y_offset = code_block.rect.y0 - sub_band.rect.y0;
408
409            let base_store = &mut storage.coefficients[sub_band.coefficients.clone()];
410            let mut base_idx = (y_offset * sub_band.rect.width()) as usize + x_offset as usize;
411
412            for (coefficients, coefficient_states) in
413                tile_ctx.bit_plane_decode_context.coefficient_rows()
414            {
415                let out_row = &mut base_store[base_idx..];
416
417                for ((output, coefficient), coefficient_state) in
418                    out_row.iter_mut().zip(coefficients).zip(coefficient_states)
419                {
420                    *output = coefficient.reconstructed(coefficient_state, irreversible);
421                    *output *= dequantization_step;
422                }
423
424                base_idx += sub_band.rect.width() as usize;
425            }
426        }
427    }
428
429    Ok(())
430}
431
432fn apply_sign_shift(channel_data: &mut [ComponentData], component_infos: &[ComponentInfo]) {
433    use crate::math::{Level, dispatch, f32x8};
434
435    for (channel, component_info) in channel_data.iter_mut().zip(component_infos.iter()) {
436        let offset = (1_u32 << (component_info.size_info.precision - 1)) as f32;
437        dispatch!(Level::new(), simd => {
438            let offset_v = f32x8::splat(simd, offset);
439            for chunk in channel.container.chunks_exact_mut(8) {
440                let v = f32x8::from_slice(simd, chunk);
441                (v + offset_v).store(chunk);
442            }
443        });
444    }
445}
446
447fn store<'a>(
448    tile: &'a Tile<'a>,
449    header: &Header<'_>,
450    tile_ctx: &mut TileDecodeContext,
451    channel_data: &mut ComponentData,
452    component_info: &ComponentInfo,
453) {
454    let idwt_output = &mut tile_ctx.idwt_output;
455
456    let component_tile = ComponentTile::new(tile, component_info);
457    let resolution_tile = ResolutionTile::new(
458        component_tile,
459        component_info.num_resolution_levels() - 1 - header.skipped_resolution_levels,
460    );
461
462    let (scale_x, scale_y) = (
463        component_info.size_info.horizontal_resolution,
464        component_info.size_info.vertical_resolution,
465    );
466
467    let (image_x_offset, image_y_offset) = (
468        header.size_data.image_area_x_offset,
469        header.size_data.image_area_y_offset,
470    );
471
472    if scale_x == 1 && scale_y == 1 {
473        // If no sub-sampling, use a fast path where we copy rows of coefficients
474        // at once.
475
476        // The rect of the IDWT output corresponds to the rect of the highest
477        // decomposition level of the tile, which is usually not 1:1 aligned
478        // with the actual tile rectangle. We also need to account for the
479        // offset of the reference grid.
480
481        let skip_x = image_x_offset.saturating_sub(idwt_output.rect.x0);
482        let skip_y = image_y_offset.saturating_sub(idwt_output.rect.y0);
483
484        let input_row_iter = idwt_output
485            .coefficients
486            .chunks_exact(idwt_output.rect.width() as usize)
487            .skip(skip_y as usize)
488            .take(idwt_output.rect.height() as usize);
489
490        let output_row_iter = channel_data
491            .container
492            .chunks_exact_mut(header.size_data.image_width() as usize)
493            .skip(resolution_tile.rect.y0.saturating_sub(image_y_offset) as usize);
494
495        for (input_row, output_row) in input_row_iter.zip(output_row_iter) {
496            let input_row = &input_row[skip_x as usize..];
497            let output_row = &mut output_row
498                [resolution_tile.rect.x0.saturating_sub(image_x_offset) as usize..]
499                [..input_row.len()];
500
501            output_row.copy_from_slice(input_row);
502        }
503    } else {
504        let image_width = header.size_data.image_width();
505        let image_height = header.size_data.image_height();
506
507        let x_shrink_factor = header.size_data.x_shrink_factor;
508        let y_shrink_factor = header.size_data.y_shrink_factor;
509
510        let x_offset = header
511            .size_data
512            .image_area_x_offset
513            .div_ceil(x_shrink_factor);
514        let y_offset = header
515            .size_data
516            .image_area_y_offset
517            .div_ceil(y_shrink_factor);
518
519        // Otherwise, copy sample by sample.
520        for y in resolution_tile.rect.y0..resolution_tile.rect.y1 {
521            let relative_y = (y - component_tile.rect.y0) as usize;
522            let reference_grid_y = (scale_y as u32 * y) / y_shrink_factor;
523
524            for x in resolution_tile.rect.x0..resolution_tile.rect.x1 {
525                let relative_x = (x - component_tile.rect.x0) as usize;
526                let reference_grid_x = (scale_x as u32 * x) / x_shrink_factor;
527
528                let sample = idwt_output.coefficients
529                    [relative_y * idwt_output.rect.width() as usize + relative_x];
530
531                for x_position in u32::max(reference_grid_x, x_offset)
532                    ..u32::min(reference_grid_x + scale_x as u32, image_width + x_offset)
533                {
534                    for y_position in u32::max(reference_grid_y, y_offset)
535                        ..u32::min(reference_grid_y + scale_y as u32, image_height + y_offset)
536                    {
537                        let pos = (y_position - y_offset) as usize * image_width as usize
538                            + (x_position - x_offset) as usize;
539
540                        channel_data.container[pos] = sample;
541                    }
542                }
543            }
544        }
545    }
546}