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