Skip to main content

j2k_types/
lib.rs

1// j2k-coverage: shared-accelerator-host
2//! Shared JPEG 2000 and HTJ2K encode-stage contracts and helpers for j2k.
3//!
4//! This crate is the neutral public contract between the `j2k` facade, the
5//! `j2k-native` codec engine, and device adapters. It defines encode-stage
6//! jobs, outputs, dispatch reports, progression-order helpers, the shared
7//! accelerator trait, and its default CPU-only implementation.
8
9#![no_std]
10#![forbid(unsafe_code)]
11#![forbid(missing_docs)]
12
13extern crate alloc;
14
15use alloc::vec::Vec;
16use core::ops::Range;
17
18mod decode_payload;
19pub use decode_payload::{
20    HtCodeBlockPayloadRanges, J2kClassicCodeBlockPayload, J2kCodestreamRange,
21};
22mod limits;
23#[doc(hidden)]
24pub use limits::{MAX_JPEG2000_PART1_COMPONENTS, MAX_JPEG2000_PART1_SAMPLE_BIT_DEPTH};
25mod move_only;
26mod resident;
27#[doc(hidden)]
28pub use resident::{
29    J2kResidentEncodeInput, J2kResidentEncodeInputError, J2kResidentHtj2kTileEncodeJob,
30};
31mod stage_error;
32pub use stage_error::{J2kEncodeStageError, J2kEncodeStageErrorKind, J2kEncodeStageResult};
33
34/// Adapter classic J2K sub-band kind for backend experimentation.
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum J2kSubBandType {
37    /// Low-low sub-band.
38    LowLow,
39    /// High-low sub-band.
40    HighLow,
41    /// Low-high sub-band.
42    LowHigh,
43    /// High-high sub-band.
44    HighHigh,
45}
46
47/// Adapter classic J2K code-block style for backend experimentation.
48#[derive(Debug, Clone, Copy)]
49#[expect(
50    clippy::struct_excessive_bools,
51    reason = "the five booleans model independent JPEG 2000 COD code-block style flags"
52)]
53pub struct J2kCodeBlockStyle {
54    /// Selective arithmetic coding bypass was enabled.
55    pub selective_arithmetic_coding_bypass: bool,
56    /// Context probabilities reset after each pass.
57    pub reset_context_probabilities: bool,
58    /// Coding terminated after each pass.
59    pub termination_on_each_pass: bool,
60    /// Vertically causal context was enabled.
61    pub vertically_causal_context: bool,
62    /// Segmentation symbols were enabled.
63    pub segmentation_symbols: bool,
64}
65
66/// Adapter classic J2K coded segment for backend experimentation.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct J2kCodeBlockSegment {
69    /// Byte offset of this segment within the combined payload.
70    pub data_offset: u32,
71    /// Segment payload length in bytes.
72    pub data_length: u32,
73    /// First coding pass covered by this segment.
74    pub start_coding_pass: u8,
75    /// One-past-last coding pass covered by this segment.
76    pub end_coding_pass: u8,
77    /// Whether this segment is decoded through the arithmetic path.
78    pub use_arithmetic: bool,
79}
80
81/// Adapter encoded classic J2K code-block payload for backend experimentation.
82#[derive(Debug)]
83pub struct EncodedJ2kCodeBlock {
84    /// Combined payload bytes for all coded segments in this code block.
85    pub data: Vec<u8>,
86    /// Coded segments for the code block.
87    pub segments: Vec<J2kCodeBlockSegment>,
88    /// Number of coding passes present for this code block.
89    pub number_of_coding_passes: u8,
90    /// Missing most-significant bit planes for this code block.
91    pub missing_bit_planes: u8,
92}
93
94/// Adapter encoded HTJ2K cleanup/refinement code-block payload for backend experimentation.
95#[derive(Debug)]
96pub struct EncodedHtJ2kCodeBlock {
97    /// Combined cleanup/refinement bytes for this code block.
98    pub data: Vec<u8>,
99    /// Cleanup segment length in bytes.
100    pub cleanup_length: u32,
101    /// Refinement segment length in bytes.
102    pub refinement_length: u32,
103    /// Number of coding passes present for this code block.
104    pub num_coding_passes: u8,
105    /// Number of zero most-significant bitplanes before first inclusion.
106    pub num_zero_bitplanes: u8,
107}
108
109/// Adapter pixel deinterleave/level-shift job for backend experimentation.
110#[derive(Debug, Clone, Copy)]
111pub struct J2kDeinterleaveToF32Job<'a> {
112    /// Interleaved source pixel bytes.
113    pub pixels: &'a [u8],
114    /// Number of pixels to convert.
115    pub num_pixels: usize,
116    /// Number of interleaved components per pixel.
117    pub num_components: u16,
118    /// Source sample bit depth.
119    pub bit_depth: u8,
120    /// Whether source samples are signed.
121    pub signed: bool,
122}
123
124/// Adapter forward RCT job for backend experimentation.
125#[derive(Debug)]
126pub struct J2kForwardRctJob<'a> {
127    /// First component plane, updated in place.
128    pub plane0: &'a mut [f32],
129    /// Second component plane, updated in place.
130    pub plane1: &'a mut [f32],
131    /// Third component plane, updated in place.
132    pub plane2: &'a mut [f32],
133}
134
135/// Adapter forward ICT job for backend experimentation.
136#[derive(Debug)]
137pub struct J2kForwardIctJob<'a> {
138    /// First component plane, updated in place.
139    pub plane0: &'a mut [f32],
140    /// Second component plane, updated in place.
141    pub plane1: &'a mut [f32],
142    /// Third component plane, updated in place.
143    pub plane2: &'a mut [f32],
144}
145
146/// Adapter forward 5/3 DWT job for backend experimentation.
147#[derive(Debug, Clone, Copy)]
148pub struct J2kForwardDwt53Job<'a> {
149    /// Source samples in row-major order.
150    pub samples: &'a [f32],
151    /// Source width in samples.
152    pub width: u32,
153    /// Source height in samples.
154    pub height: u32,
155    /// Number of decomposition levels requested.
156    pub num_levels: u8,
157}
158
159/// Adapter forward 5/3 DWT output for backend experimentation.
160#[derive(Debug)]
161pub struct J2kForwardDwt53Output {
162    /// LL subband coefficients from the lowest decomposition level.
163    pub ll: Vec<f32>,
164    /// LL subband width.
165    pub ll_width: u32,
166    /// LL subband height.
167    pub ll_height: u32,
168    /// Higher resolution detail levels, ordered from lowest to highest.
169    pub levels: Vec<J2kForwardDwt53Level>,
170}
171
172/// Adapter forward 5/3 DWT detail level for backend experimentation.
173#[derive(Debug)]
174pub struct J2kForwardDwt53Level {
175    /// HL subband coefficients.
176    pub hl: Vec<f32>,
177    /// LH subband coefficients.
178    pub lh: Vec<f32>,
179    /// HH subband coefficients.
180    pub hh: Vec<f32>,
181    /// Full-resolution width represented by this level.
182    pub width: u32,
183    /// Full-resolution height represented by this level.
184    pub height: u32,
185    /// Low-pass width at this level.
186    pub low_width: u32,
187    /// Low-pass height at this level.
188    pub low_height: u32,
189    /// High-pass width at this level.
190    pub high_width: u32,
191    /// High-pass height at this level.
192    pub high_height: u32,
193}
194
195/// Adapter forward irreversible 9/7 DWT job for backend experimentation.
196#[derive(Debug, Clone, Copy)]
197pub struct J2kForwardDwt97Job<'a> {
198    /// Source samples in row-major order.
199    pub samples: &'a [f32],
200    /// Source width in samples.
201    pub width: u32,
202    /// Source height in samples.
203    pub height: u32,
204    /// Number of decomposition levels requested.
205    pub num_levels: u8,
206}
207
208/// Adapter forward 9/7 DWT output for backend experimentation.
209#[derive(Debug)]
210pub struct J2kForwardDwt97Output {
211    /// LL subband coefficients from the lowest decomposition level.
212    pub ll: Vec<f32>,
213    /// LL subband width.
214    pub ll_width: u32,
215    /// LL subband height.
216    pub ll_height: u32,
217    /// Higher resolution detail levels, ordered from lowest to highest.
218    pub levels: Vec<J2kForwardDwt97Level>,
219}
220
221/// Adapter forward 9/7 DWT detail level for backend experimentation.
222#[derive(Debug)]
223pub struct J2kForwardDwt97Level {
224    /// HL subband coefficients.
225    pub hl: Vec<f32>,
226    /// LH subband coefficients.
227    pub lh: Vec<f32>,
228    /// HH subband coefficients.
229    pub hh: Vec<f32>,
230    /// Full-resolution width represented by this level.
231    pub width: u32,
232    /// Full-resolution height represented by this level.
233    pub height: u32,
234    /// Low-pass width at this level.
235    pub low_width: u32,
236    /// Low-pass height at this level.
237    pub low_height: u32,
238    /// High-pass width at this level.
239    pub high_width: u32,
240    /// High-pass height at this level.
241    pub high_height: u32,
242}
243
244/// Adapter sub-band quantization job for backend experimentation.
245#[derive(Debug, Clone, Copy)]
246pub struct J2kQuantizeSubbandJob<'a> {
247    /// Source sub-band coefficients in row-major order.
248    pub coefficients: &'a [f32],
249    /// Quantization step-size exponent.
250    pub step_exponent: u16,
251    /// Quantization step-size mantissa.
252    pub step_mantissa: u16,
253    /// Nominal range bits for this sub-band.
254    pub range_bits: u8,
255    /// Whether to use reversible integer quantization.
256    pub reversible: bool,
257}
258
259/// Adapter Tier-1 classic J2K code-block encode job for backend experimentation.
260#[derive(Debug, Clone, Copy)]
261pub struct J2kTier1CodeBlockEncodeJob<'a> {
262    /// Quantized coefficients in row-major order.
263    pub coefficients: &'a [i32],
264    /// Code-block width in samples.
265    pub width: u32,
266    /// Code-block height in samples.
267    pub height: u32,
268    /// Subband kind containing this code-block.
269    pub sub_band_type: J2kSubBandType,
270    /// Total bitplanes for this subband/code-block.
271    pub total_bitplanes: u8,
272    /// Classic J2K code-block style flags.
273    pub style: J2kCodeBlockStyle,
274}
275
276/// Adapter HTJ2K code-block encode job for backend experimentation.
277#[derive(Debug, Clone, Copy)]
278pub struct J2kHtCodeBlockEncodeJob<'a> {
279    /// Quantized coefficients in row-major order.
280    pub coefficients: &'a [i32],
281    /// Code-block width in samples.
282    pub width: u32,
283    /// Code-block height in samples.
284    pub height: u32,
285    /// Total bitplanes for this subband/code-block.
286    pub total_bitplanes: u8,
287    /// Requested HT coding passes for this contribution.
288    ///
289    /// `1` is cleanup-only. `2` requests cleanup plus significance-propagation
290    /// refinement on the native CPU path. `3` additionally requests one
291    /// magnitude-refinement pass. Higher values require an accelerator and
292    /// must not be silently reduced by CPU fallback.
293    pub target_coding_passes: u8,
294}
295
296/// Adapter HTJ2K cleanup/refinement encode job for one unquantized sub-band.
297#[derive(Debug, Clone, Copy)]
298pub struct J2kHtSubbandEncodeJob<'a> {
299    /// Source sub-band coefficients in row-major order.
300    pub coefficients: &'a [f32],
301    /// Sub-band width in samples.
302    pub width: u32,
303    /// Sub-band height in samples.
304    pub height: u32,
305    /// Quantization step-size exponent.
306    pub step_exponent: u16,
307    /// Quantization step-size mantissa.
308    pub step_mantissa: u16,
309    /// Nominal range bits for this sub-band.
310    pub range_bits: u8,
311    /// Whether to use reversible integer quantization.
312    pub reversible: bool,
313    /// Code-block width in samples.
314    pub code_block_width: u32,
315    /// Code-block height in samples.
316    pub code_block_height: u32,
317    /// Total coded bitplanes for this sub-band.
318    pub total_bitplanes: u8,
319}
320
321/// Adapter HTJ2K tile-body encode job for backend-resident full-tile paths.
322#[derive(Debug, Clone, Copy)]
323pub struct J2kHtj2kTileEncodeJob<'a> {
324    /// Interleaved source pixel bytes.
325    pub pixels: &'a [u8],
326    /// Tile/image width in samples.
327    pub width: u32,
328    /// Tile/image height in samples.
329    pub height: u32,
330    /// Number of interleaved image components.
331    pub num_components: u16,
332    /// Source component bit depth.
333    pub bit_depth: u8,
334    /// Whether source samples are signed.
335    pub signed: bool,
336    /// Number of DWT decomposition levels.
337    pub num_decomposition_levels: u8,
338    /// Whether the codestream uses reversible coding.
339    pub reversible: bool,
340    /// Whether a multi-component transform should be applied.
341    pub use_mct: bool,
342    /// JPEG 2000 guard bits used to derive total coded bitplanes.
343    pub guard_bits: u8,
344    /// Code-block width in samples.
345    pub code_block_width: u32,
346    /// Code-block height in samples.
347    pub code_block_height: u32,
348    /// Packet progression order to emit.
349    pub progression_order: J2kPacketizationProgressionOrder,
350    /// Per-component sampling factors, as `(x_rsiz, y_rsiz)`.
351    pub component_sampling: &'a [(u8, u8)],
352    /// Quantization step sizes, as `(exponent, mantissa)`, in codestream order.
353    pub quantization_steps: &'a [(u16, u16)],
354}
355
356/// Adapter LRCP packetization code-block contribution for backend experimentation.
357#[derive(Debug, Clone, Copy, PartialEq, Eq)]
358pub struct J2kPacketizationCodeBlock<'a> {
359    /// Encoded Tier-1 bitstream bytes for this packet contribution.
360    pub data: &'a [u8],
361    /// HTJ2K cleanup segment length in bytes when using high-throughput coding.
362    pub ht_cleanup_length: u32,
363    /// HTJ2K refinement segment length in bytes when using high-throughput coding.
364    pub ht_refinement_length: u32,
365    /// Number of coding passes in this contribution.
366    pub num_coding_passes: u8,
367    /// Number of zero most-significant bitplanes before first inclusion.
368    pub num_zero_bitplanes: u8,
369    /// Whether this code-block was included in a previous packet.
370    pub previously_included: bool,
371    /// L-block value used for segment length coding.
372    pub l_block: u32,
373    /// Block coder used for this contribution.
374    pub block_coding_mode: J2kPacketizationBlockCodingMode,
375}
376
377/// Adapter packetization block coding mode for backend experimentation.
378#[derive(Debug, Clone, Copy, PartialEq, Eq)]
379pub enum J2kPacketizationBlockCodingMode {
380    /// Classic JPEG 2000 Part 1 EBCOT block coding.
381    Classic,
382    /// High-throughput JPEG 2000 Part 15 block coding.
383    HighThroughput,
384}
385
386/// Adapter packet progression order for backend packetization experimentation.
387#[derive(Debug, Clone, Copy, PartialEq, Eq)]
388pub enum J2kPacketizationProgressionOrder {
389    /// Layer-resolution-component-position progression.
390    Lrcp,
391    /// Resolution-layer-component-position progression.
392    Rlcp,
393    /// Resolution-position-component-layer progression.
394    Rpcl,
395    /// Position-component-resolution-layer progression.
396    Pcrl,
397    /// Component-position-resolution-layer progression.
398    Cprl,
399}
400
401impl J2kPacketizationProgressionOrder {
402    /// Return the JPEG 2000 COD progression-order byte for this order.
403    pub const fn codestream_order_code(self) -> u8 {
404        match self {
405            Self::Lrcp => 0x00,
406            Self::Rlcp => 0x01,
407            Self::Rpcl => 0x02,
408            Self::Pcrl => 0x03,
409            Self::Cprl => 0x04,
410        }
411    }
412}
413
414/// Adapter LRCP packetization subband precinct for backend experimentation.
415#[derive(Debug, PartialEq, Eq)]
416pub struct J2kPacketizationSubband<'a> {
417    /// Code-block contributions in row-major order.
418    pub code_blocks: Vec<J2kPacketizationCodeBlock<'a>>,
419    /// Number of code-blocks in the x direction.
420    pub num_cbs_x: u32,
421    /// Number of code-blocks in the y direction.
422    pub num_cbs_y: u32,
423}
424
425/// Adapter LRCP packetization resolution packet for backend experimentation.
426#[derive(Debug, PartialEq, Eq)]
427pub struct J2kPacketizationResolution<'a> {
428    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
429    pub subbands: Vec<J2kPacketizationSubband<'a>>,
430}
431
432/// Adapter explicit packet descriptor for backend packetization experimentation.
433#[derive(Debug, Clone, Copy, PartialEq, Eq)]
434pub struct J2kPacketizationPacketDescriptor {
435    /// Index into the packet contribution array.
436    pub packet_index: u32,
437    /// Persistent packet-state index for repeated layer/precinct packets.
438    pub state_index: u32,
439    /// Quality layer for inclusion tag-tree thresholds.
440    pub layer: u8,
441    /// Resolution index in the output progression.
442    pub resolution: u32,
443    /// Component index in the output progression.
444    pub component: u16,
445    /// Precinct index in the output progression.
446    pub precinct: u64,
447}
448
449/// Sort explicit packet descriptors according to a JPEG 2000 progression order.
450pub fn sort_packet_descriptors_for_progression(
451    descriptors: &mut [J2kPacketizationPacketDescriptor],
452    progression_order: J2kPacketizationProgressionOrder,
453) {
454    match progression_order {
455        J2kPacketizationProgressionOrder::Lrcp => descriptors.sort_by_key(|descriptor| {
456            (
457                descriptor.layer,
458                descriptor.resolution,
459                descriptor.component,
460                descriptor.precinct,
461            )
462        }),
463        J2kPacketizationProgressionOrder::Rlcp => descriptors.sort_by_key(|descriptor| {
464            (
465                descriptor.resolution,
466                descriptor.layer,
467                descriptor.component,
468                descriptor.precinct,
469            )
470        }),
471        J2kPacketizationProgressionOrder::Rpcl => descriptors.sort_by_key(|descriptor| {
472            (
473                descriptor.resolution,
474                descriptor.precinct,
475                descriptor.component,
476                descriptor.layer,
477            )
478        }),
479        J2kPacketizationProgressionOrder::Pcrl => descriptors.sort_by_key(|descriptor| {
480            (
481                descriptor.precinct,
482                descriptor.component,
483                descriptor.resolution,
484                descriptor.layer,
485            )
486        }),
487        J2kPacketizationProgressionOrder::Cprl => descriptors.sort_by_key(|descriptor| {
488            (
489                descriptor.component,
490                descriptor.precinct,
491                descriptor.resolution,
492                descriptor.layer,
493            )
494        }),
495    }
496}
497
498/// Adapter LRCP packetization job for backend experimentation.
499#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500pub struct J2kPacketizationEncodeJob<'a> {
501    /// Number of resolution packets prepared for packetization.
502    pub resolution_count: u32,
503    /// Number of layers to write.
504    pub num_layers: u8,
505    /// Number of image components.
506    pub num_components: u16,
507    /// Total number of code-block contributions.
508    pub code_block_count: u32,
509    /// Packet progression order to emit.
510    pub progression_order: J2kPacketizationProgressionOrder,
511    /// Explicit packet descriptors in output progression order.
512    pub packet_descriptors: &'a [J2kPacketizationPacketDescriptor],
513    /// Packet payload prepared by Tier-1, in LRCP packet order.
514    pub resolutions: &'a [J2kPacketizationResolution<'a>],
515}
516
517#[cfg(test)]
518mod packet_order_tests {
519    use super::{
520        sort_packet_descriptors_for_progression, J2kPacketizationPacketDescriptor,
521        J2kPacketizationProgressionOrder,
522    };
523
524    fn descriptors() -> [J2kPacketizationPacketDescriptor; 3] {
525        [
526            J2kPacketizationPacketDescriptor {
527                packet_index: 0,
528                state_index: 0,
529                layer: 1,
530                resolution: 0,
531                component: 2,
532                precinct: 1,
533            },
534            J2kPacketizationPacketDescriptor {
535                packet_index: 1,
536                state_index: 1,
537                layer: 0,
538                resolution: 1,
539                component: 1,
540                precinct: 0,
541            },
542            J2kPacketizationPacketDescriptor {
543                packet_index: 2,
544                state_index: 2,
545                layer: 0,
546                resolution: 0,
547                component: 0,
548                precinct: 2,
549            },
550        ]
551    }
552
553    #[test]
554    fn progression_order_codes_match_codestream_values() {
555        assert_eq!(
556            J2kPacketizationProgressionOrder::Lrcp.codestream_order_code(),
557            0
558        );
559        assert_eq!(
560            J2kPacketizationProgressionOrder::Rlcp.codestream_order_code(),
561            1
562        );
563        assert_eq!(
564            J2kPacketizationProgressionOrder::Rpcl.codestream_order_code(),
565            2
566        );
567        assert_eq!(
568            J2kPacketizationProgressionOrder::Pcrl.codestream_order_code(),
569            3
570        );
571        assert_eq!(
572            J2kPacketizationProgressionOrder::Cprl.codestream_order_code(),
573            4
574        );
575    }
576
577    #[test]
578    fn packet_descriptor_sort_uses_requested_progression_order() {
579        let mut lrcp = descriptors();
580        sort_packet_descriptors_for_progression(&mut lrcp, J2kPacketizationProgressionOrder::Lrcp);
581        assert_eq!(lrcp.map(|descriptor| descriptor.packet_index), [2, 1, 0]);
582
583        let mut pcrl = descriptors();
584        sort_packet_descriptors_for_progression(&mut pcrl, J2kPacketizationProgressionOrder::Pcrl);
585        assert_eq!(pcrl.map(|descriptor| descriptor.packet_index), [1, 0, 2]);
586    }
587}
588
589/// Adapter encode-stage dispatch counters for backend experimentation.
590#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
591pub struct J2kEncodeDispatchReport {
592    /// Pixel deinterleave/level-shift dispatch count.
593    pub deinterleave: usize,
594    /// Forward RCT kernel dispatch count.
595    pub forward_rct: usize,
596    /// Forward ICT kernel dispatch count.
597    pub forward_ict: usize,
598    /// Forward reversible 5/3 DWT kernel dispatch count.
599    pub forward_dwt53: usize,
600    /// Forward irreversible 9/7 DWT kernel dispatch count.
601    pub forward_dwt97: usize,
602    /// Sub-band quantization dispatch count.
603    pub quantize_subband: usize,
604    /// Tier-1 code-block encode dispatch count.
605    pub tier1_code_block: usize,
606    /// HTJ2K code-block encode dispatch count.
607    pub ht_code_block: usize,
608    /// Packetization dispatch count.
609    pub packetization: usize,
610}
611
612impl J2kEncodeDispatchReport {
613    /// Return the saturating per-stage delta from `before` to `self`.
614    #[must_use]
615    pub fn saturating_delta(self, before: Self) -> Self {
616        Self {
617            deinterleave: self.deinterleave.saturating_sub(before.deinterleave),
618            forward_rct: self.forward_rct.saturating_sub(before.forward_rct),
619            forward_ict: self.forward_ict.saturating_sub(before.forward_ict),
620            forward_dwt53: self.forward_dwt53.saturating_sub(before.forward_dwt53),
621            forward_dwt97: self.forward_dwt97.saturating_sub(before.forward_dwt97),
622            quantize_subband: self
623                .quantize_subband
624                .saturating_sub(before.quantize_subband),
625            tier1_code_block: self
626                .tier1_code_block
627                .saturating_sub(before.tier1_code_block),
628            ht_code_block: self.ht_code_block.saturating_sub(before.ht_code_block),
629            packetization: self.packetization.saturating_sub(before.packetization),
630        }
631    }
632
633    /// Return total dispatches across all encode stages.
634    #[must_use]
635    pub fn total(self) -> usize {
636        self.forward_rct
637            .saturating_add(self.deinterleave)
638            .saturating_add(self.forward_ict)
639            .saturating_add(self.forward_dwt53)
640            .saturating_add(self.forward_dwt97)
641            .saturating_add(self.quantize_subband)
642            .saturating_add(self.tier1_code_block)
643            .saturating_add(self.ht_code_block)
644            .saturating_add(self.packetization)
645    }
646
647    /// Return whether at least one encode stage dispatched.
648    #[must_use]
649    pub fn any(self) -> bool {
650        self.total() > 0
651    }
652}
653
654/// Adapter CPU-only encode accelerator that always falls back to native stages.
655#[derive(Debug, Default, Clone, Copy)]
656pub struct CpuOnlyJ2kEncodeStageAccelerator;
657
658/// Adapter JPEG 2000 encode-stage accelerator for backend experimentation.
659pub trait J2kEncodeStageAccelerator {
660    /// Report cumulative backend dispatches completed by this accelerator.
661    fn dispatch_report(&self) -> J2kEncodeDispatchReport {
662        J2kEncodeDispatchReport::default()
663    }
664
665    /// Optionally deinterleave interleaved pixel bytes into f32 component planes.
666    ///
667    /// Return `Ok(Some(components))` with one plane per component. Return
668    /// `Ok(None)` to use the CPU fallback.
669    fn encode_deinterleave(
670        &mut self,
671        _job: J2kDeinterleaveToF32Job<'_>,
672    ) -> J2kEncodeStageResult<Option<Vec<Vec<f32>>>> {
673        Ok(None)
674    }
675
676    /// Optionally apply forward RCT in place.
677    ///
678    /// Return `Ok(true)` after writing transformed planes. Return `Ok(false)`
679    /// to use the CPU fallback.
680    fn encode_forward_rct(&mut self, _job: J2kForwardRctJob<'_>) -> J2kEncodeStageResult<bool> {
681        Ok(false)
682    }
683
684    /// Optionally apply forward ICT in place.
685    ///
686    /// Return `Ok(true)` after writing transformed planes. Return `Ok(false)`
687    /// to use the CPU fallback.
688    fn encode_forward_ict(&mut self, _job: J2kForwardIctJob<'_>) -> J2kEncodeStageResult<bool> {
689        Ok(false)
690    }
691
692    /// Optionally run a forward reversible 5/3 DWT.
693    ///
694    /// Return `Ok(Some(output))` with all subbands populated. Return
695    /// `Ok(None)` to use the CPU fallback.
696    fn encode_forward_dwt53(
697        &mut self,
698        _job: J2kForwardDwt53Job<'_>,
699    ) -> J2kEncodeStageResult<Option<J2kForwardDwt53Output>> {
700        Ok(None)
701    }
702
703    /// Optionally run a forward irreversible 9/7 DWT.
704    ///
705    /// Return `Ok(Some(output))` with all subbands populated. Return
706    /// `Ok(None)` to use the CPU fallback.
707    fn encode_forward_dwt97(
708        &mut self,
709        _job: J2kForwardDwt97Job<'_>,
710    ) -> J2kEncodeStageResult<Option<J2kForwardDwt97Output>> {
711        Ok(None)
712    }
713
714    /// Optionally quantize one sub-band.
715    ///
716    /// Return `Ok(Some(coefficients))` with one quantized coefficient for each
717    /// input coefficient. Return `Ok(None)` to use the CPU fallback.
718    fn encode_quantize_subband(
719        &mut self,
720        _job: J2kQuantizeSubbandJob<'_>,
721    ) -> J2kEncodeStageResult<Option<Vec<i32>>> {
722        Ok(None)
723    }
724
725    /// Optionally encode one classic Tier-1 code-block.
726    ///
727    /// Return `Ok(Some(output))` with encoded bytes and pass metadata. Return
728    /// `Ok(None)` to use the CPU fallback.
729    fn encode_tier1_code_block(
730        &mut self,
731        _job: J2kTier1CodeBlockEncodeJob<'_>,
732    ) -> J2kEncodeStageResult<Option<EncodedJ2kCodeBlock>> {
733        Ok(None)
734    }
735
736    /// Optionally encode multiple classic Tier-1 code-blocks in one backend dispatch.
737    ///
738    /// Return `Ok(Some(outputs))` with one encoded output per input job. Return
739    /// `Ok(None)` to use the per-block hook or CPU fallback.
740    fn encode_tier1_code_blocks(
741        &mut self,
742        _jobs: &[J2kTier1CodeBlockEncodeJob<'_>],
743    ) -> J2kEncodeStageResult<Option<Vec<EncodedJ2kCodeBlock>>> {
744        Ok(None)
745    }
746
747    /// Optionally encode one HTJ2K code-block.
748    ///
749    /// Return `Ok(Some(output))` with encoded bytes and pass metadata. Return
750    /// `Ok(None)` to use the CPU fallback.
751    fn encode_ht_code_block(
752        &mut self,
753        _job: J2kHtCodeBlockEncodeJob<'_>,
754    ) -> J2kEncodeStageResult<Option<EncodedHtJ2kCodeBlock>> {
755        Ok(None)
756    }
757
758    /// Optionally encode multiple HTJ2K code-blocks in one backend dispatch.
759    ///
760    /// Return `Ok(Some(outputs))` with one encoded output per input job. Return
761    /// `Ok(None)` to use the per-block hook or CPU fallback.
762    fn encode_ht_code_blocks(
763        &mut self,
764        _jobs: &[J2kHtCodeBlockEncodeJob<'_>],
765    ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
766        Ok(None)
767    }
768
769    /// Optionally quantize and encode one HTJ2K cleanup/refinement sub-band.
770    ///
771    /// Return `Ok(Some(outputs))` with one encoded output per code block in
772    /// raster code-block order. Return `Ok(None)` to use the separate
773    /// quantization and code-block hooks or CPU fallback.
774    fn encode_ht_subband(
775        &mut self,
776        _job: J2kHtSubbandEncodeJob<'_>,
777    ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
778        Ok(None)
779    }
780
781    /// Optionally encode the complete HTJ2K tile packet body.
782    ///
783    /// Return `Ok(Some(bytes))` with the complete tile bitstream body. CPU
784    /// marker/header writing remains outside this hook. Return `Ok(None)` to
785    /// use the normal staged encode pipeline.
786    fn encode_htj2k_tile(
787        &mut self,
788        _job: J2kHtj2kTileEncodeJob<'_>,
789    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
790        Ok(None)
791    }
792
793    /// Optionally encode a complete HTJ2K tile whose pixels remain backend-resident.
794    ///
795    /// Unlike [`Self::encode_htj2k_tile`], this hook has no host sample slice.
796    /// A resident-input facade must treat `Ok(None)` as a hard decline because
797    /// there are no host pixels from which to run the CPU fallback pipeline.
798    fn encode_resident_htj2k_tile(
799        &mut self,
800        _job: J2kResidentHtj2kTileEncodeJob<'_>,
801    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
802        Ok(None)
803    }
804
805    /// Return whether native CPU code-block fallback should use internal rayon parallelism.
806    ///
807    /// External accelerators keep serial per-block fallback so their hooks still
808    /// observe every fallback block after a declined batch hook.
809    fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
810        false
811    }
812
813    /// Return whether whole-tile CPU-only batch encode may be parallelized by callers.
814    ///
815    /// This is narrower than [`Self::prefer_parallel_cpu_code_block_fallback`]:
816    /// callers must only bypass the supplied accelerator when it is known to
817    /// have no observable hooks.
818    fn prefer_parallel_cpu_tile_encode(&self) -> bool {
819        false
820    }
821
822    /// Optionally packetize prepared packet contributions.
823    ///
824    /// Return `Ok(Some(bytes))` with the complete tile bitstream. Return
825    /// `Ok(None)` to use the CPU fallback.
826    fn encode_packetization(
827        &mut self,
828        _job: J2kPacketizationEncodeJob<'_>,
829    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
830        Ok(None)
831    }
832}
833
834#[doc(hidden)]
835impl J2kEncodeStageAccelerator for CpuOnlyJ2kEncodeStageAccelerator {
836    fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
837        true
838    }
839
840    fn prefer_parallel_cpu_tile_encode(&self) -> bool {
841        true
842    }
843}
844
845/// Multipliers applied to irreversible 9/7 quantization step sizes by subband.
846#[derive(Debug, Clone, Copy, PartialEq)]
847pub struct IrreversibleQuantizationSubbandScales {
848    /// Multiplier for the LL subband.
849    pub low_low: f32,
850    /// Multiplier for HL subbands.
851    pub high_low: f32,
852    /// Multiplier for LH subbands.
853    pub low_high: f32,
854    /// Multiplier for HH subbands.
855    pub high_high: f32,
856}
857
858/// Public JPEG 2000 irreversible quantization step-size tuple.
859#[derive(Debug, Clone, Copy, PartialEq, Eq)]
860pub struct IrreversibleQuantizationStep {
861    /// Quantization step-size exponent.
862    pub exponent: u8,
863    /// Quantization step-size mantissa.
864    pub mantissa: u16,
865}
866
867impl Default for IrreversibleQuantizationSubbandScales {
868    fn default() -> Self {
869        Self {
870            low_low: 1.0,
871            high_low: 1.0,
872            low_high: 1.0,
873            high_high: 1.0,
874        }
875    }
876}
877
878/// Precomputed reversible 5/3 wavelet coefficients for one component.
879#[derive(Debug)]
880pub struct PrecomputedHtj2k53Component {
881    /// Horizontal SIZ sampling factor (`XRsiz`).
882    pub x_rsiz: u8,
883    /// Vertical SIZ sampling factor (`YRsiz`).
884    pub y_rsiz: u8,
885    /// Forward 5/3 DWT output, ordered as the encoder expects.
886    pub dwt: J2kForwardDwt53Output,
887}
888
889/// Precomputed reversible 5/3 wavelet image.
890#[derive(Debug)]
891pub struct PrecomputedHtj2k53Image {
892    /// Reference-grid image width.
893    pub width: u32,
894    /// Reference-grid image height.
895    pub height: u32,
896    /// Component precision in bits.
897    pub bit_depth: u8,
898    /// Whether component samples are signed.
899    pub signed: bool,
900    /// Components at their native resolution.
901    pub components: Vec<PrecomputedHtj2k53Component>,
902}
903
904/// Precomputed irreversible 9/7 wavelet coefficients for one component.
905#[derive(Debug)]
906pub struct PrecomputedHtj2k97Component {
907    /// Horizontal SIZ sampling factor (`XRsiz`).
908    pub x_rsiz: u8,
909    /// Vertical SIZ sampling factor (`YRsiz`).
910    pub y_rsiz: u8,
911    /// Forward 9/7 DWT output, ordered as the encoder expects.
912    pub dwt: J2kForwardDwt97Output,
913}
914
915/// Precomputed irreversible 9/7 wavelet image.
916#[derive(Debug)]
917pub struct PrecomputedHtj2k97Image {
918    /// Reference-grid image width.
919    pub width: u32,
920    /// Reference-grid image height.
921    pub height: u32,
922    /// Component precision in bits.
923    pub bit_depth: u8,
924    /// Whether component samples are signed.
925    pub signed: bool,
926    /// Components at their native resolution.
927    pub components: Vec<PrecomputedHtj2k97Component>,
928}
929
930/// Prequantized irreversible 9/7 HTJ2K code-block image.
931#[derive(Debug)]
932pub struct PrequantizedHtj2k97Image {
933    /// Reference-grid image width.
934    pub width: u32,
935    /// Reference-grid image height.
936    pub height: u32,
937    /// Component precision in bits.
938    pub bit_depth: u8,
939    /// Whether component samples are signed.
940    pub signed: bool,
941    /// Components at their native resolution.
942    pub components: Vec<PrequantizedHtj2k97Component>,
943}
944
945/// Prequantized irreversible 9/7 HTJ2K component.
946#[derive(Debug)]
947pub struct PrequantizedHtj2k97Component {
948    /// Horizontal SIZ sampling factor (`XRsiz`).
949    pub x_rsiz: u8,
950    /// Vertical SIZ sampling factor (`YRsiz`).
951    pub y_rsiz: u8,
952    /// Resolution packets for this component, ordered from lowest to highest.
953    pub resolutions: Vec<PrequantizedHtj2k97Resolution>,
954}
955
956/// One component resolution's prequantized HTJ2K subbands.
957#[derive(Debug)]
958pub struct PrequantizedHtj2k97Resolution {
959    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
960    pub subbands: Vec<PrequantizedHtj2k97Subband>,
961}
962
963/// One prequantized HTJ2K subband split into code-blocks.
964#[derive(Debug)]
965pub struct PrequantizedHtj2k97Subband {
966    /// Subband kind.
967    pub sub_band_type: J2kSubBandType,
968    /// Number of code-blocks in the x direction.
969    pub num_cbs_x: u32,
970    /// Number of code-blocks in the y direction.
971    pub num_cbs_y: u32,
972    /// Total bitplanes declared for every code-block in this subband.
973    pub total_bitplanes: u8,
974    /// Code-block coefficients in row-major code-block order.
975    pub code_blocks: Vec<PrequantizedHtj2k97CodeBlock>,
976}
977
978/// One prequantized HTJ2K code-block.
979#[derive(Debug)]
980pub struct PrequantizedHtj2k97CodeBlock {
981    /// Quantized coefficients in row-major order.
982    pub coefficients: Vec<i32>,
983    /// Code-block width in coefficients.
984    pub width: u32,
985    /// Code-block height in coefficients.
986    pub height: u32,
987}
988
989/// Preencoded irreversible 9/7 HTJ2K code-block image.
990#[derive(Debug)]
991pub struct PreencodedHtj2k97Image {
992    /// Reference-grid image width.
993    pub width: u32,
994    /// Reference-grid image height.
995    pub height: u32,
996    /// Component precision in bits.
997    pub bit_depth: u8,
998    /// Whether component samples are signed.
999    pub signed: bool,
1000    /// Components at their native resolution.
1001    pub components: Vec<PreencodedHtj2k97Component>,
1002}
1003
1004/// Preencoded irreversible 9/7 HTJ2K component.
1005#[derive(Debug)]
1006pub struct PreencodedHtj2k97Component {
1007    /// Horizontal SIZ sampling factor (`XRsiz`).
1008    pub x_rsiz: u8,
1009    /// Vertical SIZ sampling factor (`YRsiz`).
1010    pub y_rsiz: u8,
1011    /// Resolution packets for this component, ordered from lowest to highest.
1012    pub resolutions: Vec<PreencodedHtj2k97Resolution>,
1013}
1014
1015/// One component resolution's preencoded HTJ2K subbands.
1016#[derive(Debug)]
1017pub struct PreencodedHtj2k97Resolution {
1018    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
1019    pub subbands: Vec<PreencodedHtj2k97Subband>,
1020}
1021
1022/// One preencoded HTJ2K subband split into code-blocks.
1023#[derive(Debug)]
1024pub struct PreencodedHtj2k97Subband {
1025    /// Subband kind.
1026    pub sub_band_type: J2kSubBandType,
1027    /// Number of code-blocks in the x direction.
1028    pub num_cbs_x: u32,
1029    /// Number of code-blocks in the y direction.
1030    pub num_cbs_y: u32,
1031    /// Total bitplanes declared for every code-block in this subband.
1032    pub total_bitplanes: u8,
1033    /// Encoded code-block payloads in row-major code-block order.
1034    pub code_blocks: Vec<PreencodedHtj2k97CodeBlock>,
1035}
1036
1037/// One preencoded HTJ2K code-block.
1038#[derive(Debug)]
1039pub struct PreencodedHtj2k97CodeBlock {
1040    /// Code-block width in coefficients.
1041    pub width: u32,
1042    /// Code-block height in coefficients.
1043    pub height: u32,
1044    /// Encoded cleanup/refinement payload and packet metadata.
1045    pub encoded: EncodedHtJ2kCodeBlock,
1046}
1047
1048/// Preencoded irreversible 9/7 HTJ2K code-block image backed by one compact
1049/// payload buffer.
1050#[derive(Debug)]
1051pub struct PreencodedHtj2k97CompactImage {
1052    /// Reference-grid image width.
1053    pub width: u32,
1054    /// Reference-grid image height.
1055    pub height: u32,
1056    /// Component precision in bits.
1057    pub bit_depth: u8,
1058    /// Whether component samples are signed.
1059    pub signed: bool,
1060    /// Contiguous encoded code-block payload bytes.
1061    pub payload: Vec<u8>,
1062    /// Components at their native resolution.
1063    pub components: Vec<PreencodedHtj2k97CompactComponent>,
1064}
1065
1066/// Preencoded compact irreversible 9/7 HTJ2K component.
1067#[derive(Debug)]
1068pub struct PreencodedHtj2k97CompactComponent {
1069    /// Horizontal SIZ sampling factor (`XRsiz`).
1070    pub x_rsiz: u8,
1071    /// Vertical SIZ sampling factor (`YRsiz`).
1072    pub y_rsiz: u8,
1073    /// Resolution packets for this component, ordered from lowest to highest.
1074    pub resolutions: Vec<PreencodedHtj2k97CompactResolution>,
1075}
1076
1077/// One component resolution's compact preencoded HTJ2K subbands.
1078#[derive(Debug)]
1079pub struct PreencodedHtj2k97CompactResolution {
1080    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
1081    pub subbands: Vec<PreencodedHtj2k97CompactSubband>,
1082}
1083
1084/// One compact preencoded HTJ2K subband split into code-blocks.
1085#[derive(Debug)]
1086pub struct PreencodedHtj2k97CompactSubband {
1087    /// Subband kind.
1088    pub sub_band_type: J2kSubBandType,
1089    /// Number of code-blocks in the x direction.
1090    pub num_cbs_x: u32,
1091    /// Number of code-blocks in the y direction.
1092    pub num_cbs_y: u32,
1093    /// Total bitplanes declared for every code-block in this subband.
1094    pub total_bitplanes: u8,
1095    /// Code-block metadata in row-major code-block order.
1096    pub code_blocks: Vec<PreencodedHtj2k97CompactCodeBlock>,
1097}
1098
1099/// One compact preencoded HTJ2K code-block.
1100#[derive(Debug)]
1101pub struct PreencodedHtj2k97CompactCodeBlock {
1102    /// Code-block width in coefficients.
1103    pub width: u32,
1104    /// Code-block height in coefficients.
1105    pub height: u32,
1106    /// Byte range into the image-level compact payload.
1107    pub payload_range: Range<usize>,
1108    /// HTJ2K cleanup segment length in bytes.
1109    pub cleanup_length: u32,
1110    /// HTJ2K refinement segment length in bytes.
1111    pub refinement_length: u32,
1112    /// Number of coding passes in the encoded payload.
1113    pub num_coding_passes: u8,
1114    /// Number of missing most-significant bitplanes.
1115    pub num_zero_bitplanes: u8,
1116}
1117
1118move_only::assert_move_only!(
1119    EncodedJ2kCodeBlock,
1120    EncodedHtJ2kCodeBlock,
1121    J2kPacketizationSubband<'static>,
1122    J2kPacketizationResolution<'static>,
1123    J2kForwardDwt53Output,
1124    J2kForwardDwt53Level,
1125    J2kForwardDwt97Output,
1126    J2kForwardDwt97Level,
1127    PrecomputedHtj2k53Component,
1128    PrecomputedHtj2k53Image,
1129    PrecomputedHtj2k97Component,
1130    PrecomputedHtj2k97Image,
1131    PrequantizedHtj2k97Image,
1132    PrequantizedHtj2k97Component,
1133    PrequantizedHtj2k97Resolution,
1134    PrequantizedHtj2k97Subband,
1135    PrequantizedHtj2k97CodeBlock,
1136    PreencodedHtj2k97Image,
1137    PreencodedHtj2k97Component,
1138    PreencodedHtj2k97Resolution,
1139    PreencodedHtj2k97Subband,
1140    PreencodedHtj2k97CodeBlock,
1141    PreencodedHtj2k97CompactImage,
1142    PreencodedHtj2k97CompactComponent,
1143    PreencodedHtj2k97CompactResolution,
1144    PreencodedHtj2k97CompactSubband,
1145    PreencodedHtj2k97CompactCodeBlock,
1146);