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    /// Report the exact maximum cleanup magnitude from the most recent
688    /// successful fused HT sub-band encode, when the backend observed it.
689    ///
690    /// Native encoding uses this value for the Part 15 CAP magnitude bound.
691    /// Backends that do not report it retain the conservative fallback.
692    fn ht_subband_maximum_cleanup_magnitude(&self) -> Option<u64> {
693        None
694    }
695
696    /// Report the exact Part 15 magnitude bound derived by the most recent
697    /// successful complete HT tile encode, when the backend observed it.
698    fn ht_tile_required_magnitude_bound(&self) -> Option<u8> {
699        None
700    }
701
702    /// Optionally deinterleave interleaved pixel bytes into f32 component planes.
703    ///
704    /// Return `Ok(Some(components))` with one plane per component. Return
705    /// `Ok(None)` to use the CPU fallback.
706    fn encode_deinterleave(
707        &mut self,
708        _job: J2kDeinterleaveToF32Job<'_>,
709    ) -> J2kEncodeStageResult<Option<Vec<Vec<f32>>>> {
710        Ok(None)
711    }
712
713    /// Optionally apply forward RCT in place.
714    ///
715    /// Return `Ok(true)` after writing transformed planes. Return `Ok(false)`
716    /// to use the CPU fallback.
717    fn encode_forward_rct(&mut self, _job: J2kForwardRctJob<'_>) -> J2kEncodeStageResult<bool> {
718        Ok(false)
719    }
720
721    /// Optionally apply forward ICT in place.
722    ///
723    /// Return `Ok(true)` after writing transformed planes. Return `Ok(false)`
724    /// to use the CPU fallback.
725    fn encode_forward_ict(&mut self, _job: J2kForwardIctJob<'_>) -> J2kEncodeStageResult<bool> {
726        Ok(false)
727    }
728
729    /// Optionally run a forward reversible 5/3 DWT.
730    ///
731    /// Return `Ok(Some(output))` with all subbands populated. Return
732    /// `Ok(None)` to use the CPU fallback.
733    fn encode_forward_dwt53(
734        &mut self,
735        _job: J2kForwardDwt53Job<'_>,
736    ) -> J2kEncodeStageResult<Option<J2kForwardDwt53Output>> {
737        Ok(None)
738    }
739
740    /// Optionally run a forward irreversible 9/7 DWT.
741    ///
742    /// Return `Ok(Some(output))` with all subbands populated. Return
743    /// `Ok(None)` to use the CPU fallback.
744    fn encode_forward_dwt97(
745        &mut self,
746        _job: J2kForwardDwt97Job<'_>,
747    ) -> J2kEncodeStageResult<Option<J2kForwardDwt97Output>> {
748        Ok(None)
749    }
750
751    /// Optionally quantize one sub-band.
752    ///
753    /// Return `Ok(Some(coefficients))` with one quantized coefficient for each
754    /// input coefficient. Return `Ok(None)` to use the CPU fallback.
755    fn encode_quantize_subband(
756        &mut self,
757        _job: J2kQuantizeSubbandJob<'_>,
758    ) -> J2kEncodeStageResult<Option<Vec<i32>>> {
759        Ok(None)
760    }
761
762    /// Optionally encode one classic Tier-1 code-block.
763    ///
764    /// Return `Ok(Some(output))` with encoded bytes and pass metadata. Return
765    /// `Ok(None)` to use the CPU fallback.
766    fn encode_tier1_code_block(
767        &mut self,
768        _job: J2kTier1CodeBlockEncodeJob<'_>,
769    ) -> J2kEncodeStageResult<Option<EncodedJ2kCodeBlock>> {
770        Ok(None)
771    }
772
773    /// Optionally encode multiple classic Tier-1 code-blocks in one backend dispatch.
774    ///
775    /// Return `Ok(Some(outputs))` with one encoded output per input job. Return
776    /// `Ok(None)` to use the per-block hook or CPU fallback.
777    fn encode_tier1_code_blocks(
778        &mut self,
779        _jobs: &[J2kTier1CodeBlockEncodeJob<'_>],
780    ) -> J2kEncodeStageResult<Option<Vec<EncodedJ2kCodeBlock>>> {
781        Ok(None)
782    }
783
784    /// Optionally encode one HTJ2K code-block.
785    ///
786    /// Return `Ok(Some(output))` with encoded bytes and pass metadata. Return
787    /// `Ok(None)` to use the CPU fallback.
788    fn encode_ht_code_block(
789        &mut self,
790        _job: J2kHtCodeBlockEncodeJob<'_>,
791    ) -> J2kEncodeStageResult<Option<EncodedHtJ2kCodeBlock>> {
792        Ok(None)
793    }
794
795    /// Optionally encode multiple HTJ2K code-blocks in one backend dispatch.
796    ///
797    /// Return `Ok(Some(outputs))` with one encoded output per input job. Return
798    /// `Ok(None)` to use the per-block hook or CPU fallback.
799    fn encode_ht_code_blocks(
800        &mut self,
801        _jobs: &[J2kHtCodeBlockEncodeJob<'_>],
802    ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
803        Ok(None)
804    }
805
806    /// Optionally quantize and encode one HTJ2K cleanup/refinement sub-band.
807    ///
808    /// Return `Ok(Some(outputs))` with one encoded output per code block in
809    /// raster code-block order. Return `Ok(None)` to use the separate
810    /// quantization and code-block hooks or CPU fallback.
811    fn encode_ht_subband(
812        &mut self,
813        _job: J2kHtSubbandEncodeJob<'_>,
814    ) -> J2kEncodeStageResult<Option<Vec<EncodedHtJ2kCodeBlock>>> {
815        Ok(None)
816    }
817
818    /// Optionally encode the complete HTJ2K tile packet body.
819    ///
820    /// Return `Ok(Some(bytes))` with the complete tile bitstream body. CPU
821    /// marker/header writing remains outside this hook. Return `Ok(None)` to
822    /// use the normal staged encode pipeline.
823    fn encode_htj2k_tile(
824        &mut self,
825        _job: J2kHtj2kTileEncodeJob<'_>,
826    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
827        Ok(None)
828    }
829
830    /// Optionally encode a complete HTJ2K tile whose pixels remain backend-resident.
831    ///
832    /// Unlike [`Self::encode_htj2k_tile`], this hook has no host sample slice.
833    /// A resident-input facade must treat `Ok(None)` as a hard decline because
834    /// there are no host pixels from which to run the CPU fallback pipeline.
835    fn encode_resident_htj2k_tile(
836        &mut self,
837        _job: J2kResidentHtj2kTileEncodeJob<'_>,
838    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
839        Ok(None)
840    }
841
842    /// Return whether native CPU code-block fallback should use internal rayon parallelism.
843    ///
844    /// External accelerators keep serial per-block fallback so their hooks still
845    /// observe every fallback block after a declined batch hook.
846    fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
847        false
848    }
849
850    /// Return whether whole-tile CPU-only batch encode may be parallelized by callers.
851    ///
852    /// This is narrower than [`Self::prefer_parallel_cpu_code_block_fallback`]:
853    /// callers must only bypass the supplied accelerator when it is known to
854    /// have no observable hooks.
855    fn prefer_parallel_cpu_tile_encode(&self) -> bool {
856        false
857    }
858
859    /// Optionally packetize prepared packet contributions.
860    ///
861    /// Return `Ok(Some(bytes))` with the complete tile bitstream. Return
862    /// `Ok(None)` to use the CPU fallback.
863    fn encode_packetization(
864        &mut self,
865        _job: J2kPacketizationEncodeJob<'_>,
866    ) -> J2kEncodeStageResult<Option<Vec<u8>>> {
867        Ok(None)
868    }
869}
870
871#[doc(hidden)]
872impl J2kEncodeStageAccelerator for CpuOnlyJ2kEncodeStageAccelerator {
873    fn prefer_parallel_cpu_code_block_fallback(&self) -> bool {
874        true
875    }
876
877    fn prefer_parallel_cpu_tile_encode(&self) -> bool {
878        true
879    }
880}
881
882/// Multipliers applied to irreversible 9/7 quantization step sizes by subband.
883#[derive(Debug, Clone, Copy, PartialEq)]
884pub struct IrreversibleQuantizationSubbandScales {
885    /// Multiplier for the LL subband.
886    pub low_low: f32,
887    /// Multiplier for HL subbands.
888    pub high_low: f32,
889    /// Multiplier for LH subbands.
890    pub low_high: f32,
891    /// Multiplier for HH subbands.
892    pub high_high: f32,
893}
894
895/// Public JPEG 2000 irreversible quantization step-size tuple.
896#[derive(Debug, Clone, Copy, PartialEq, Eq)]
897pub struct IrreversibleQuantizationStep {
898    /// Quantization step-size exponent.
899    pub exponent: u8,
900    /// Quantization step-size mantissa.
901    pub mantissa: u16,
902}
903
904impl Default for IrreversibleQuantizationSubbandScales {
905    fn default() -> Self {
906        Self {
907            low_low: 1.0,
908            high_low: 1.0,
909            low_high: 1.0,
910            high_high: 1.0,
911        }
912    }
913}
914
915/// Precomputed reversible 5/3 wavelet coefficients for one component.
916#[derive(Debug)]
917pub struct PrecomputedHtj2k53Component {
918    /// Horizontal SIZ sampling factor (`XRsiz`).
919    pub x_rsiz: u8,
920    /// Vertical SIZ sampling factor (`YRsiz`).
921    pub y_rsiz: u8,
922    /// Forward 5/3 DWT output, ordered as the encoder expects.
923    pub dwt: J2kForwardDwt53Output,
924}
925
926/// Precomputed reversible 5/3 wavelet image.
927#[derive(Debug)]
928pub struct PrecomputedHtj2k53Image {
929    /// Reference-grid image width.
930    pub width: u32,
931    /// Reference-grid image height.
932    pub height: u32,
933    /// Component precision in bits.
934    pub bit_depth: u8,
935    /// Whether component samples are signed.
936    pub signed: bool,
937    /// Components at their native resolution.
938    pub components: Vec<PrecomputedHtj2k53Component>,
939}
940
941/// Precomputed irreversible 9/7 wavelet coefficients for one component.
942#[derive(Debug)]
943pub struct PrecomputedHtj2k97Component {
944    /// Horizontal SIZ sampling factor (`XRsiz`).
945    pub x_rsiz: u8,
946    /// Vertical SIZ sampling factor (`YRsiz`).
947    pub y_rsiz: u8,
948    /// Forward 9/7 DWT output, ordered as the encoder expects.
949    pub dwt: J2kForwardDwt97Output,
950}
951
952/// Precomputed irreversible 9/7 wavelet image.
953#[derive(Debug)]
954pub struct PrecomputedHtj2k97Image {
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<PrecomputedHtj2k97Component>,
965}
966
967/// Prequantized irreversible 9/7 HTJ2K code-block image.
968#[derive(Debug)]
969pub struct PrequantizedHtj2k97Image {
970    /// Reference-grid image width.
971    pub width: u32,
972    /// Reference-grid image height.
973    pub height: u32,
974    /// Component precision in bits.
975    pub bit_depth: u8,
976    /// Whether component samples are signed.
977    pub signed: bool,
978    /// Components at their native resolution.
979    pub components: Vec<PrequantizedHtj2k97Component>,
980}
981
982/// Prequantized irreversible 9/7 HTJ2K component.
983#[derive(Debug)]
984pub struct PrequantizedHtj2k97Component {
985    /// Horizontal SIZ sampling factor (`XRsiz`).
986    pub x_rsiz: u8,
987    /// Vertical SIZ sampling factor (`YRsiz`).
988    pub y_rsiz: u8,
989    /// Resolution packets for this component, ordered from lowest to highest.
990    pub resolutions: Vec<PrequantizedHtj2k97Resolution>,
991}
992
993/// One component resolution's prequantized HTJ2K subbands.
994#[derive(Debug)]
995pub struct PrequantizedHtj2k97Resolution {
996    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
997    pub subbands: Vec<PrequantizedHtj2k97Subband>,
998}
999
1000/// One prequantized HTJ2K subband split into code-blocks.
1001#[derive(Debug)]
1002pub struct PrequantizedHtj2k97Subband {
1003    /// Subband kind.
1004    pub sub_band_type: J2kSubBandType,
1005    /// Number of code-blocks in the x direction.
1006    pub num_cbs_x: u32,
1007    /// Number of code-blocks in the y direction.
1008    pub num_cbs_y: u32,
1009    /// Total bitplanes declared for every code-block in this subband.
1010    pub total_bitplanes: u8,
1011    /// Code-block coefficients in row-major code-block order.
1012    pub code_blocks: Vec<PrequantizedHtj2k97CodeBlock>,
1013}
1014
1015/// One prequantized HTJ2K code-block.
1016#[derive(Debug)]
1017pub struct PrequantizedHtj2k97CodeBlock {
1018    /// Quantized coefficients in row-major order.
1019    pub coefficients: Vec<i32>,
1020    /// Code-block width in coefficients.
1021    pub width: u32,
1022    /// Code-block height in coefficients.
1023    pub height: u32,
1024}
1025
1026/// Preencoded irreversible 9/7 HTJ2K code-block image.
1027#[derive(Debug)]
1028pub struct PreencodedHtj2k97Image {
1029    /// Reference-grid image width.
1030    pub width: u32,
1031    /// Reference-grid image height.
1032    pub height: u32,
1033    /// Component precision in bits.
1034    pub bit_depth: u8,
1035    /// Whether component samples are signed.
1036    pub signed: bool,
1037    /// Components at their native resolution.
1038    pub components: Vec<PreencodedHtj2k97Component>,
1039}
1040
1041/// Preencoded irreversible 9/7 HTJ2K component.
1042#[derive(Debug)]
1043pub struct PreencodedHtj2k97Component {
1044    /// Horizontal SIZ sampling factor (`XRsiz`).
1045    pub x_rsiz: u8,
1046    /// Vertical SIZ sampling factor (`YRsiz`).
1047    pub y_rsiz: u8,
1048    /// Resolution packets for this component, ordered from lowest to highest.
1049    pub resolutions: Vec<PreencodedHtj2k97Resolution>,
1050}
1051
1052/// One component resolution's preencoded HTJ2K subbands.
1053#[derive(Debug)]
1054pub struct PreencodedHtj2k97Resolution {
1055    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
1056    pub subbands: Vec<PreencodedHtj2k97Subband>,
1057}
1058
1059/// One preencoded HTJ2K subband split into code-blocks.
1060#[derive(Debug)]
1061pub struct PreencodedHtj2k97Subband {
1062    /// Subband kind.
1063    pub sub_band_type: J2kSubBandType,
1064    /// Number of code-blocks in the x direction.
1065    pub num_cbs_x: u32,
1066    /// Number of code-blocks in the y direction.
1067    pub num_cbs_y: u32,
1068    /// Total bitplanes declared for every code-block in this subband.
1069    pub total_bitplanes: u8,
1070    /// Encoded code-block payloads in row-major code-block order.
1071    pub code_blocks: Vec<PreencodedHtj2k97CodeBlock>,
1072}
1073
1074/// One preencoded HTJ2K code-block.
1075#[derive(Debug)]
1076pub struct PreencodedHtj2k97CodeBlock {
1077    /// Code-block width in coefficients.
1078    pub width: u32,
1079    /// Code-block height in coefficients.
1080    pub height: u32,
1081    /// Encoded cleanup/refinement payload and packet metadata.
1082    pub encoded: EncodedHtJ2kCodeBlock,
1083}
1084
1085/// Preencoded irreversible 9/7 HTJ2K code-block image backed by one compact
1086/// payload buffer.
1087#[derive(Debug)]
1088pub struct PreencodedHtj2k97CompactImage {
1089    /// Reference-grid image width.
1090    pub width: u32,
1091    /// Reference-grid image height.
1092    pub height: u32,
1093    /// Component precision in bits.
1094    pub bit_depth: u8,
1095    /// Whether component samples are signed.
1096    pub signed: bool,
1097    /// Contiguous encoded code-block payload bytes.
1098    pub payload: Vec<u8>,
1099    /// Components at their native resolution.
1100    pub components: Vec<PreencodedHtj2k97CompactComponent>,
1101}
1102
1103/// Preencoded compact irreversible 9/7 HTJ2K component.
1104#[derive(Debug)]
1105pub struct PreencodedHtj2k97CompactComponent {
1106    /// Horizontal SIZ sampling factor (`XRsiz`).
1107    pub x_rsiz: u8,
1108    /// Vertical SIZ sampling factor (`YRsiz`).
1109    pub y_rsiz: u8,
1110    /// Resolution packets for this component, ordered from lowest to highest.
1111    pub resolutions: Vec<PreencodedHtj2k97CompactResolution>,
1112}
1113
1114/// One component resolution's compact preencoded HTJ2K subbands.
1115#[derive(Debug)]
1116pub struct PreencodedHtj2k97CompactResolution {
1117    /// Subbands in packet order: LL for resolution 0, then HL/LH/HH.
1118    pub subbands: Vec<PreencodedHtj2k97CompactSubband>,
1119}
1120
1121/// One compact preencoded HTJ2K subband split into code-blocks.
1122#[derive(Debug)]
1123pub struct PreencodedHtj2k97CompactSubband {
1124    /// Subband kind.
1125    pub sub_band_type: J2kSubBandType,
1126    /// Number of code-blocks in the x direction.
1127    pub num_cbs_x: u32,
1128    /// Number of code-blocks in the y direction.
1129    pub num_cbs_y: u32,
1130    /// Total bitplanes declared for every code-block in this subband.
1131    pub total_bitplanes: u8,
1132    /// Code-block metadata in row-major code-block order.
1133    pub code_blocks: Vec<PreencodedHtj2k97CompactCodeBlock>,
1134}
1135
1136/// One compact preencoded HTJ2K code-block.
1137#[derive(Debug)]
1138pub struct PreencodedHtj2k97CompactCodeBlock {
1139    /// Code-block width in coefficients.
1140    pub width: u32,
1141    /// Code-block height in coefficients.
1142    pub height: u32,
1143    /// Byte range into the image-level compact payload.
1144    pub payload_range: Range<usize>,
1145    /// HTJ2K cleanup segment length in bytes.
1146    pub cleanup_length: u32,
1147    /// HTJ2K refinement segment length in bytes.
1148    pub refinement_length: u32,
1149    /// Number of coding passes in the encoded payload.
1150    pub num_coding_passes: u8,
1151    /// Number of missing most-significant bitplanes.
1152    pub num_zero_bitplanes: u8,
1153}
1154
1155move_only::assert_move_only!(
1156    EncodedJ2kCodeBlock,
1157    EncodedHtJ2kCodeBlock,
1158    J2kPacketizationSubband<'static>,
1159    J2kPacketizationResolution<'static>,
1160    J2kForwardDwt53Output,
1161    J2kForwardDwt53Level,
1162    J2kForwardDwt97Output,
1163    J2kForwardDwt97Level,
1164    PrecomputedHtj2k53Component,
1165    PrecomputedHtj2k53Image,
1166    PrecomputedHtj2k97Component,
1167    PrecomputedHtj2k97Image,
1168    PrequantizedHtj2k97Image,
1169    PrequantizedHtj2k97Component,
1170    PrequantizedHtj2k97Resolution,
1171    PrequantizedHtj2k97Subband,
1172    PrequantizedHtj2k97CodeBlock,
1173    PreencodedHtj2k97Image,
1174    PreencodedHtj2k97Component,
1175    PreencodedHtj2k97Resolution,
1176    PreencodedHtj2k97Subband,
1177    PreencodedHtj2k97CodeBlock,
1178    PreencodedHtj2k97CompactImage,
1179    PreencodedHtj2k97CompactComponent,
1180    PreencodedHtj2k97CompactResolution,
1181    PreencodedHtj2k97CompactSubband,
1182    PreencodedHtj2k97CompactCodeBlock,
1183);