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);