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