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