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