1#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
67#![forbid(unsafe_code)]
68#![forbid(missing_docs)]
69extern crate alloc;
70
71#[cfg(test)]
72use alloc::vec;
73use alloc::vec::Vec;
74
75use crate::error::bail;
76#[cfg(test)]
77use crate::jp2::colr::CieLab;
78
79macro_rules! define_ht_code_block_job {
80 (
81 $(#[$meta:meta])*
82 pub struct $name:ident $(<$lt:lifetime>)? {
83 $($prefix:tt)*
84 }
85 ) => {
86 $(#[$meta])*
87 pub struct $name $(<$lt>)? {
88 $($prefix)*
89 pub cleanup_length: u32,
91 pub refinement_length: u32,
93 pub width: u32,
95 pub height: u32,
97 pub output_stride: usize,
99 pub missing_bit_planes: u8,
101 pub number_of_coding_passes: u8,
103 pub num_bitplanes: u8,
105 pub roi_shift: u8,
107 pub stripe_causal: bool,
109 pub strict: bool,
111 pub dequantization_step: f32,
113 }
114 };
115}
116
117#[doc(hidden)]
118#[macro_export]
119macro_rules! __j2k_component_plane_metadata_accessors {
120 () => {
121 #[must_use]
123 pub fn dimensions(&self) -> (u32, u32) {
124 self.dimensions
125 }
126
127 #[must_use]
129 pub fn sampling(&self) -> (u8, u8) {
130 self.sampling
131 }
132
133 #[must_use]
135 pub fn bit_depth(&self) -> u8 {
136 self.bit_depth
137 }
138
139 #[must_use]
141 pub fn signed(&self) -> bool {
142 self.signed
143 }
144 };
145}
146mod backend;
147mod color;
148mod error;
149mod ht_adapter;
150mod inspect;
151#[macro_use]
152pub(crate) mod log;
153mod direct_cpu;
154mod direct_plan;
155mod direct_roi;
156pub(crate) mod math;
157mod move_only;
158#[doc(hidden)]
159pub mod packet_math;
160pub(crate) mod profile;
161mod roi;
162pub(crate) mod writer;
163#[cfg(test)]
164use crate::math::{dispatch, Level};
165#[cfg(test)]
166use color::cielab_to_rgb;
167pub(crate) use color::{
168 convert_color_space, interleave_and_convert_after_mct, interleave_and_convert_region,
169 resolve_alpha_and_color_space, resolve_palette_indices, validate_and_reorder_channels,
170 validate_interleaved_output_buffer,
171};
172pub use color::{
173 Bitmap, ColorSpace, ComponentPlane, DecodedComponents, DecodedNativeComponents,
174 NativeComponentPlane, RawBitmap,
175};
176#[doc(hidden)]
177pub use color::{ComponentPlaneParts, ComponentRowSink, NativeComponentPlaneParts};
178#[doc(hidden)]
179pub use color::{DecodedComponentsParts, DecodedNativeComponentsParts};
180#[doc(hidden)]
181pub use direct_cpu::{
182 execute_direct_color_plan_rgb8_into, execute_direct_color_plan_rgba8_into,
183 execute_referenced_classic_entropy_job, execute_referenced_classic_plan,
184 execute_referenced_classic_plan_from_payloads, execute_referenced_htj2k_entropy_job,
185 execute_referenced_htj2k_plan, execute_referenced_htj2k_plan_from_payloads,
186 finish_referenced_classic_staged, finish_referenced_classic_tile_staged,
187 finish_referenced_htj2k_staged, finish_referenced_htj2k_tile_staged,
188 prepare_referenced_classic_entropy_workspace, prepare_referenced_classic_staged,
189 prepare_referenced_classic_tile_staged, prepare_referenced_htj2k_entropy_workspace,
190 prepare_referenced_htj2k_staged, prepare_referenced_htj2k_tile_staged, J2kDirectCodeBlockIndex,
191 J2kDirectCpuEntropyWorkspace, J2kDirectCpuScratch, J2kDirectDecodedComponents,
192 J2kDirectDecodedPlane,
193};
194#[doc(hidden)]
195pub use direct_plan::{
196 HtCodeBlockPayloadRanges, HtOwnedCodeBlockBatchJob, HtOwnedSubBandPlan,
197 J2kClassicCodeBlockPayload, J2kCodestreamRange, J2kDirectBandId, J2kDirectColorPlan,
198 J2kDirectGrayscalePlan, J2kDirectGrayscaleStep, J2kDirectIdwtStep, J2kDirectRgbaPlan,
199 J2kDirectStoreStep, J2kOwnedCodeBlockBatchJob, J2kOwnedSubBandPlan, J2kReferencedClassicPlan,
200 J2kReferencedHtj2kPlan, J2kReferencedImageGeometry, J2kReferencedPayloadRecordSpan,
201 J2kReferencedTileGeometry, J2kReferencedTilePlan,
202};
203#[doc(hidden)]
204pub use direct_roi::{
205 idwt_required_input_window_for_rects, idwt_required_input_windows, idwt_required_output_margin,
206 window_referenced_classic_plan_to_stores, window_referenced_htj2k_plan_to_stores,
207 J2kIdwtRequiredInputWindows, J2kRequiredBandRegion,
208};
209pub use inspect::{
210 inspect_htj2k_capabilities, inspect_j2k_codestream_header, looks_like_j2k_codestream,
211 J2kCodestreamComponentHeader, J2kCodestreamHeaderError, J2kCodestreamHeaderMetadata,
212};
213#[doc(hidden)]
214pub use j2c::capabilities::required_magnitude_bound as htj2k_required_magnitude_bound;
215pub use j2c::capabilities::{Htj2kCapabilities, Htj2kCapabilityMode, J2kCorrespondingProfile};
216#[doc(hidden)]
217pub use jp2::{
218 extract_jp2_codestream_payload, inspect_jp2_container, Jp2ChannelAssociation,
219 Jp2ChannelDefinition, Jp2ChannelType, Jp2ColorSpec, Jp2ComponentMapping,
220 Jp2ComponentMappingType, Jp2ComponentMetadata, Jp2Container, Jp2FileKind, Jp2FileMetadata,
221 Jp2ImageHeaderMetadata, Jp2PaletteColumn, Jp2PaletteMetadata,
222};
223#[doc(hidden)]
224pub use roi::idwt_band_index;
225pub(crate) use roi::{add_roi_shift_to_bitplanes, apply_roi_maxshift_inverse_i64, validate_roi};
226#[cfg(test)]
227pub(crate) use roi::{apply_roi_maxshift_inverse_f32, apply_roi_maxshift_inverse_i32};
228
229pub use error::{
230 ColorError, DecodeError, DecodeErrorClass, DecodingError, DirectPlanUnsupportedReason,
231 EncodeError, EncodeResult, FormatError, MarkerError, Result, TileError, ValidationError,
232};
233#[cfg(test)]
234pub(crate) use j2c::encode::NativeEncodeRetainedInput;
235pub use j2c::encode::{
236 encode, encode_component_planes_53, encode_htj2k, encode_htj2k_with_qfactor,
237 encode_htj2k_with_qfactor_and_accelerator, encode_precomputed_htj2k_53,
238 encode_precomputed_htj2k_53_with_accelerator,
239 encode_precomputed_htj2k_53_with_accelerator_and_max_host_bytes,
240 encode_precomputed_htj2k_53_with_mct, encode_precomputed_htj2k_53_with_mct_and_accelerator,
241 encode_precomputed_htj2k_97, encode_precomputed_htj2k_97_batch_owned_with_accelerator,
242 encode_precomputed_htj2k_97_batch_owned_with_accelerator_and_max_host_bytes,
243 encode_precomputed_htj2k_97_batch_with_accelerator,
244 encode_precomputed_htj2k_97_with_accelerator,
245 encode_precomputed_htj2k_97_with_accelerator_and_max_host_bytes, encode_precomputed_j2k_53,
246 encode_precomputed_j2k_53_with_accelerator, encode_precomputed_j2k_53_with_mct,
247 encode_precomputed_j2k_53_with_mct_and_accelerator, encode_preencoded_htj2k_97,
248 encode_preencoded_htj2k_97_compact_owned_with_accelerator,
249 encode_preencoded_htj2k_97_compact_owned_with_accelerator_and_max_host_bytes,
250 encode_preencoded_htj2k_97_compact_owned_with_accelerator_and_max_host_bytes_and_required_magnitude_bound,
251 encode_preencoded_htj2k_97_owned_with_accelerator,
252 encode_preencoded_htj2k_97_owned_with_accelerator_and_max_host_bytes,
253 encode_preencoded_htj2k_97_owned_with_accelerator_and_max_host_bytes_and_required_magnitude_bound,
254 encode_preencoded_htj2k_97_with_accelerator, encode_prequantized_htj2k_97,
255 encode_prequantized_htj2k_97_with_accelerator,
256 encode_prequantized_htj2k_97_with_accelerator_and_max_host_bytes,
257 encode_resident_htj2k_with_accelerator, encode_typed_component_planes_53,
258 encode_with_accelerator, encode_with_accelerator_and_roi_regions, encode_with_roi_regions,
259 irreversible_quantization_profile_scale_ceiling, irreversible_quantization_scale_bounds,
260 irreversible_quantization_step_for_subband, EncodeComponentPlane, EncodeOptions,
261 EncodeProgressionOrder, EncodeRoiRegion, EncodeTypedComponentPlane, IrreversibleScaleEncoder,
262 ResidentHtj2kEncodeError,
263};
264pub use j2c::{
265 CpuDecodeParallelism, DecoderContext, DecoderWorkspace, DecoderWorkspaceStats,
266 Reversible53CoefficientImage,
267};
268#[doc(hidden)]
269pub use j2k_types::{
270 sort_packet_descriptors_for_progression, CpuOnlyJ2kEncodeStageAccelerator,
271 EncodedHtJ2kCodeBlock, EncodedHtJ2kCodeBlockSet, EncodedJ2kCodeBlock,
272 IrreversibleQuantizationStep, IrreversibleQuantizationSubbandScales, J2kCodeBlockSegment,
273 J2kCodeBlockStyle, J2kDeinterleaveMctToF32Job, J2kDeinterleaveToF32Job, J2kEncodeContext,
274 J2kEncodeDispatchReport, J2kEncodeStageAccelerator, J2kEncodeStageError,
275 J2kEncodeStageErrorKind, J2kEncodeStageResult, J2kForwardDwt53Job, J2kForwardDwt53Level,
276 J2kForwardDwt53Output, J2kForwardDwt97Job, J2kForwardDwt97Level, J2kForwardDwt97Output,
277 J2kForwardIctJob, J2kForwardRctJob, J2kHtCodeBlockEncodeJob, J2kHtCodeBlockSetEncodeJob,
278 J2kHtSubbandEncodeJob, J2kHtj2kTileEncodeJob, J2kPacketizationBlockCodingMode,
279 J2kPacketizationCodeBlock, J2kPacketizationEncodeJob, J2kPacketizationPacketDescriptor,
280 J2kPacketizationProgressionOrder, J2kPacketizationResolution, J2kPacketizationSubband,
281 J2kQuantizeSubbandJob, J2kResidentEncodeInput, J2kResidentEncodeInputError,
282 J2kResidentHtj2kTileEncodeJob, J2kSubBandType, J2kTier1CodeBlockEncodeJob,
283 PrecomputedHtj2k53Component, PrecomputedHtj2k53Image, PrecomputedHtj2k97Component,
284 PrecomputedHtj2k97Image, PreencodedHtj2k97CodeBlock, PreencodedHtj2k97CompactCodeBlock,
285 PreencodedHtj2k97CompactComponent, PreencodedHtj2k97CompactImage,
286 PreencodedHtj2k97CompactResolution, PreencodedHtj2k97CompactSubband,
287 PreencodedHtj2k97Component, PreencodedHtj2k97Image, PreencodedHtj2k97Resolution,
288 PreencodedHtj2k97Subband, PrequantizedHtj2k97CodeBlock, PrequantizedHtj2k97Component,
289 PrequantizedHtj2k97Image, PrequantizedHtj2k97Resolution, PrequantizedHtj2k97Subband,
290};
291pub use j2k_types::{
292 WaveletBand, WaveletBandKind, WaveletComponent, WaveletImage, WaveletRect, WaveletSamples,
293 WaveletSelection, WaveletTile, WaveletTransform,
294};
295
296mod j2c;
297mod jp2;
298pub(crate) mod reader;
299#[doc(hidden)]
300pub use j2c::ht_encode_tables::HtUvlcTableEntry;
301
302const MAX_CLASSIC_DECODE_BITPLANES: u8 = j2c::MAX_BITPLANE_COUNT;
303const MAX_DEINTERLEAVE_REFERENCE_BIT_DEPTH: u8 = j2k_types::MAX_JPEG2000_PART1_SAMPLE_BIT_DEPTH;
304pub(crate) use j2k_types::MAX_JPEG2000_PART1_COMPONENTS as MAX_J2K_SPEC_COMPONENTS;
305pub(crate) const MAX_J2K_TILE_COUNT: u64 = u16::MAX as u64 + 1;
306#[doc(hidden)]
307pub use j2k_types::{DEFAULT_MAX_CODEC_BYTES, DEFAULT_MAX_DECODE_BYTES};
308
309#[inline]
310pub(crate) fn checked_decode_usize_product2(left: usize, right: usize) -> Result<usize> {
311 left.checked_mul(right)
312 .ok_or(ValidationError::ImageTooLarge.into())
313}
314
315#[inline]
316fn checked_decode_byte_cap(len: usize) -> Result<usize> {
317 if len > DEFAULT_MAX_DECODE_BYTES {
318 bail!(ValidationError::ImageTooLarge);
319 }
320 Ok(len)
321}
322
323#[inline]
324pub(crate) fn checked_decode_byte_len2(left: usize, right: usize) -> Result<usize> {
325 checked_decode_byte_cap(checked_decode_usize_product2(left, right)?)
326}
327
328#[inline]
329pub(crate) fn checked_decode_byte_len3(first: usize, second: usize, third: usize) -> Result<usize> {
330 let partial = checked_decode_usize_product2(first, second)?;
331 checked_decode_byte_cap(checked_decode_usize_product2(partial, third)?)
332}
333
334#[inline]
335pub(crate) fn checked_decode_byte_len4(
336 first: usize,
337 second: usize,
338 third: usize,
339 fourth: usize,
340) -> Result<usize> {
341 let partial = checked_decode_usize_product2(first, second)?;
342 let partial = checked_decode_usize_product2(partial, third)?;
343 checked_decode_byte_cap(checked_decode_usize_product2(partial, fourth)?)
344}
345
346#[inline]
347pub(crate) fn try_reserve_decode_elements<T>(values: &mut Vec<T>, target_len: usize) -> Result<()> {
348 checked_decode_byte_len2(target_len, core::mem::size_of::<T>())?;
349 if target_len > values.capacity() {
350 values
351 .try_reserve_exact(target_len - values.len())
352 .map_err(|_| DecodingError::HostAllocationFailed)?;
353 }
354 Ok(())
355}
356
357#[inline]
358pub(crate) fn try_resize_decode_elements<T: Clone>(
359 values: &mut Vec<T>,
360 target_len: usize,
361 value: T,
362) -> Result<()> {
363 try_reserve_decode_elements(values, target_len)?;
364 values.resize(target_len, value);
365 Ok(())
366}
367
368#[inline]
369pub(crate) fn checked_decode_sample_count(width: u32, height: u32) -> Result<usize> {
370 #[cfg(target_pointer_width = "64")]
371 {
372 usize::try_from(u64::from(width) * u64::from(height))
373 .map_err(|_| ValidationError::ImageTooLarge.into())
374 }
375
376 #[cfg(not(target_pointer_width = "64"))]
377 {
378 checked_decode_usize_product2(width as usize, height as usize)
379 }
380}
381
382#[inline]
383fn native_bytes_per_sample(bit_depth: u8) -> Result<usize> {
384 if bit_depth == 0 || bit_depth > 63 {
385 bail!(ValidationError::ImageTooLarge);
386 }
387 Ok(usize::from(bit_depth).div_ceil(8).max(1))
388}
389
390#[doc(hidden)]
391pub use backend::{
392 HtCleanupEncodeDistribution, HtCodeBlockBatchJob, HtCodeBlockDecodeJob,
393 HtCodeBlockDecodePhaseLimit, HtCodeBlockDecoder, HtSubBandDecodeJob, J2kClassicReconstruction,
394 J2kCodeBlockBatchJob, J2kCodeBlockDecodeJob, J2kIdwtBand, J2kIdwtNormalization,
395 J2kInverseMctJob, J2kRect, J2kSingleDecompositionIdwtJob, J2kStoreComponentJob,
396 J2kSubBandDecodeJob, J2kTier1TokenSegment, J2kWaveletTransform,
397};
398#[doc(hidden)]
399pub use ht_adapter::{
400 decode_ht_sigprop_benchmark_state, ht_uvlc_encode_table, ht_uvlc_encode_table_bytes,
401 ht_uvlc_table0, ht_uvlc_table1, ht_vlc_encode_table0, ht_vlc_encode_table1, ht_vlc_table0,
402 ht_vlc_table1, prepare_ht_sigprop_benchmark_state, HtSigPropBenchmarkState,
403};
404
405mod scalar;
406#[doc(hidden)]
407pub use scalar::{
408 collect_ht_cleanup_encode_distribution, decode_ht_code_block_scalar,
409 decode_ht_code_block_scalar_until_phase, decode_ht_code_block_scalar_with_workspace,
410 decode_ht_code_block_scalar_with_workspace_midpoint,
411 decode_ht_code_block_scalar_with_workspace_midpoint_profiled,
412 decode_ht_code_block_scalar_with_workspace_profiled, decode_j2k_code_block_scalar,
413 decode_j2k_code_block_scalar_profiled, decode_j2k_code_block_scalar_with_workspace,
414 decode_j2k_code_block_scalar_with_workspace_midpoint,
415 decode_j2k_code_block_scalar_with_workspace_midpoint_profiled,
416 decode_j2k_code_block_scalar_with_workspace_profiled, decode_j2k_sub_band_scalar,
417 encode_ht_code_block_scalar, encode_ht_code_block_scalar_with_passes,
418 encode_ht_code_block_scalar_with_passes_and_workspace, encode_j2k_code_block_scalar_with_style,
419 encode_j2k_packetization_scalar, forward_dwt53_reference, forward_dwt97_reference,
420 forward_ict_reference, forward_rct_reference, inverse_dwt97_reference, inverse_ict_reference,
421 pack_j2k_code_block_scalar_from_tier1_tokens, quantize_reversible_reference,
422 quantize_subband_reference, try_deinterleave_reference, HtCodeBlockDecodeProfile,
423 HtCodeBlockDecodeWorkspace, HtCodeBlockEncodeWorkspace, J2kCodeBlockDecodeProfile,
424 J2kCodeBlockDecodeWorkspace,
425};
426
427pub(crate) const JP2_MAGIC: &[u8] = b"\x00\x00\x00\x0C\x6A\x50\x20\x20";
429pub(crate) const CODESTREAM_MAGIC: &[u8] = b"\xFF\x4F\xFF\x51";
431
432mod image;
433pub use image::{DecodeSettings, Image, PreparedRegionDecoder};
434
435#[cfg(test)]
436mod tests;