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