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