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, 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, 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 J2kIdwtRequiredInputWindows, J2kRequiredBandRegion,
207};
208pub use inspect::{
209 inspect_htj2k_capabilities, inspect_j2k_codestream_header, looks_like_j2k_codestream,
210 J2kCodestreamComponentHeader, J2kCodestreamHeaderError, J2kCodestreamHeaderMetadata,
211};
212#[doc(hidden)]
213pub use j2c::capabilities::required_magnitude_bound as htj2k_required_magnitude_bound;
214pub use j2c::capabilities::{Htj2kCapabilities, Htj2kCapabilityMode, J2kCorrespondingProfile};
215#[doc(hidden)]
216pub use jp2::{
217 extract_jp2_codestream_payload, inspect_jp2_container, Jp2ChannelAssociation,
218 Jp2ChannelDefinition, Jp2ChannelType, Jp2ColorSpec, Jp2ComponentMapping,
219 Jp2ComponentMappingType, Jp2ComponentMetadata, Jp2Container, Jp2FileKind, Jp2FileMetadata,
220 Jp2ImageHeaderMetadata, Jp2PaletteColumn, Jp2PaletteMetadata,
221};
222#[doc(hidden)]
223pub use roi::idwt_band_index;
224pub(crate) use roi::{
225 add_roi_shift_to_bitplanes, apply_roi_maxshift_inverse_f32, apply_roi_maxshift_inverse_i32,
226 apply_roi_maxshift_inverse_i64, validate_roi,
227};
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_step_for_subband, EncodeComponentPlane, EncodeOptions,
260 EncodeProgressionOrder, EncodeRoiRegion, EncodeTypedComponentPlane, ResidentHtj2kEncodeError,
261};
262pub use j2c::{
263 CpuDecodeParallelism, DecoderContext, DecoderWorkspace, DecoderWorkspaceStats,
264 Reversible53CoefficientImage,
265};
266#[doc(hidden)]
267pub use j2k_types::{
268 sort_packet_descriptors_for_progression, CpuOnlyJ2kEncodeStageAccelerator,
269 EncodedHtJ2kCodeBlock, EncodedHtJ2kCodeBlockSet, EncodedJ2kCodeBlock,
270 IrreversibleQuantizationStep, IrreversibleQuantizationSubbandScales, J2kCodeBlockSegment,
271 J2kCodeBlockStyle, J2kDeinterleaveMctToF32Job, J2kDeinterleaveToF32Job, J2kEncodeContext,
272 J2kEncodeDispatchReport, J2kEncodeStageAccelerator, J2kEncodeStageError,
273 J2kEncodeStageErrorKind, J2kEncodeStageResult, J2kForwardDwt53Job, J2kForwardDwt53Level,
274 J2kForwardDwt53Output, J2kForwardDwt97Job, J2kForwardDwt97Level, J2kForwardDwt97Output,
275 J2kForwardIctJob, J2kForwardRctJob, J2kHtCodeBlockEncodeJob, J2kHtCodeBlockSetEncodeJob,
276 J2kHtSubbandEncodeJob, J2kHtj2kTileEncodeJob, J2kPacketizationBlockCodingMode,
277 J2kPacketizationCodeBlock, J2kPacketizationEncodeJob, J2kPacketizationPacketDescriptor,
278 J2kPacketizationProgressionOrder, J2kPacketizationResolution, J2kPacketizationSubband,
279 J2kQuantizeSubbandJob, J2kResidentEncodeInput, J2kResidentEncodeInputError,
280 J2kResidentHtj2kTileEncodeJob, J2kSubBandType, J2kTier1CodeBlockEncodeJob,
281 PrecomputedHtj2k53Component, PrecomputedHtj2k53Image, PrecomputedHtj2k97Component,
282 PrecomputedHtj2k97Image, PreencodedHtj2k97CodeBlock, PreencodedHtj2k97CompactCodeBlock,
283 PreencodedHtj2k97CompactComponent, PreencodedHtj2k97CompactImage,
284 PreencodedHtj2k97CompactResolution, PreencodedHtj2k97CompactSubband,
285 PreencodedHtj2k97Component, PreencodedHtj2k97Image, PreencodedHtj2k97Resolution,
286 PreencodedHtj2k97Subband, PrequantizedHtj2k97CodeBlock, PrequantizedHtj2k97Component,
287 PrequantizedHtj2k97Image, PrequantizedHtj2k97Resolution, PrequantizedHtj2k97Subband,
288};
289
290mod j2c;
291mod jp2;
292pub(crate) mod reader;
293#[doc(hidden)]
294pub use j2c::ht_encode_tables::HtUvlcTableEntry;
295
296const MAX_CLASSIC_DECODE_BITPLANES: u8 = j2c::MAX_BITPLANE_COUNT;
297const MAX_DEINTERLEAVE_REFERENCE_BIT_DEPTH: u8 = j2k_types::MAX_JPEG2000_PART1_SAMPLE_BIT_DEPTH;
298pub(crate) use j2k_types::MAX_JPEG2000_PART1_COMPONENTS as MAX_J2K_SPEC_COMPONENTS;
299pub(crate) const MAX_J2K_IMAGE_DIMENSION: u32 = 60_000;
300pub(crate) const MAX_J2K_TILE_COUNT: u64 = u16::MAX as u64 + 1;
301#[doc(hidden)]
302pub use j2k_types::{DEFAULT_MAX_CODEC_BYTES, DEFAULT_MAX_DECODE_BYTES};
303
304#[inline]
305pub(crate) fn checked_decode_usize_product2(left: usize, right: usize) -> Result<usize> {
306 left.checked_mul(right)
307 .ok_or(ValidationError::ImageTooLarge.into())
308}
309
310#[inline]
311fn checked_decode_byte_cap(len: usize) -> Result<usize> {
312 if len > DEFAULT_MAX_DECODE_BYTES {
313 bail!(ValidationError::ImageTooLarge);
314 }
315 Ok(len)
316}
317
318#[inline]
319pub(crate) fn checked_decode_byte_len2(left: usize, right: usize) -> Result<usize> {
320 checked_decode_byte_cap(checked_decode_usize_product2(left, right)?)
321}
322
323#[inline]
324pub(crate) fn checked_decode_byte_len3(first: usize, second: usize, third: usize) -> Result<usize> {
325 let partial = checked_decode_usize_product2(first, second)?;
326 checked_decode_byte_cap(checked_decode_usize_product2(partial, third)?)
327}
328
329#[inline]
330pub(crate) fn checked_decode_byte_len4(
331 first: usize,
332 second: usize,
333 third: usize,
334 fourth: usize,
335) -> Result<usize> {
336 let partial = checked_decode_usize_product2(first, second)?;
337 let partial = checked_decode_usize_product2(partial, third)?;
338 checked_decode_byte_cap(checked_decode_usize_product2(partial, fourth)?)
339}
340
341#[inline]
342pub(crate) fn try_reserve_decode_elements<T>(values: &mut Vec<T>, target_len: usize) -> Result<()> {
343 checked_decode_byte_len2(target_len, core::mem::size_of::<T>())?;
344 if target_len > values.capacity() {
345 values
346 .try_reserve_exact(target_len - values.len())
347 .map_err(|_| DecodingError::HostAllocationFailed)?;
348 }
349 Ok(())
350}
351
352#[inline]
353pub(crate) fn try_resize_decode_elements<T: Clone>(
354 values: &mut Vec<T>,
355 target_len: usize,
356 value: T,
357) -> Result<()> {
358 try_reserve_decode_elements(values, target_len)?;
359 values.resize(target_len, value);
360 Ok(())
361}
362
363#[inline]
364pub(crate) fn checked_decode_sample_count(width: u32, height: u32) -> Result<usize> {
365 #[cfg(target_pointer_width = "64")]
366 {
367 usize::try_from(u64::from(width) * u64::from(height))
368 .map_err(|_| ValidationError::ImageTooLarge.into())
369 }
370
371 #[cfg(not(target_pointer_width = "64"))]
372 {
373 checked_decode_usize_product2(width as usize, height as usize)
374 }
375}
376
377#[inline]
378fn native_bytes_per_sample(bit_depth: u8) -> Result<usize> {
379 if bit_depth == 0 || bit_depth > 63 {
380 bail!(ValidationError::ImageTooLarge);
381 }
382 Ok(usize::from(bit_depth).div_ceil(8).max(1))
383}
384
385#[doc(hidden)]
386pub use backend::{
387 HtCleanupEncodeDistribution, HtCodeBlockBatchJob, HtCodeBlockDecodeJob,
388 HtCodeBlockDecodePhaseLimit, HtCodeBlockDecoder, HtSubBandDecodeJob, J2kCodeBlockBatchJob,
389 J2kCodeBlockDecodeJob, J2kIdwtBand, J2kIdwtNormalization, J2kInverseMctJob, J2kRect,
390 J2kSingleDecompositionIdwtJob, J2kStoreComponentJob, J2kSubBandDecodeJob, J2kTier1TokenSegment,
391 J2kWaveletTransform,
392};
393#[doc(hidden)]
394pub use ht_adapter::{
395 decode_ht_sigprop_benchmark_state, ht_uvlc_encode_table, ht_uvlc_encode_table_bytes,
396 ht_uvlc_table0, ht_uvlc_table1, ht_vlc_encode_table0, ht_vlc_encode_table1, ht_vlc_table0,
397 ht_vlc_table1, prepare_ht_sigprop_benchmark_state, HtSigPropBenchmarkState,
398};
399
400mod scalar;
401#[doc(hidden)]
402pub use scalar::{
403 collect_ht_cleanup_encode_distribution, decode_ht_code_block_scalar,
404 decode_ht_code_block_scalar_until_phase, decode_ht_code_block_scalar_with_workspace,
405 decode_ht_code_block_scalar_with_workspace_midpoint,
406 decode_ht_code_block_scalar_with_workspace_midpoint_profiled,
407 decode_ht_code_block_scalar_with_workspace_profiled, decode_j2k_code_block_scalar,
408 decode_j2k_code_block_scalar_profiled, decode_j2k_code_block_scalar_with_workspace,
409 decode_j2k_code_block_scalar_with_workspace_midpoint,
410 decode_j2k_code_block_scalar_with_workspace_midpoint_profiled,
411 decode_j2k_code_block_scalar_with_workspace_profiled, decode_j2k_sub_band_scalar,
412 encode_ht_code_block_scalar, encode_ht_code_block_scalar_with_passes,
413 encode_ht_code_block_scalar_with_passes_and_workspace, encode_j2k_code_block_scalar_with_style,
414 encode_j2k_packetization_scalar, forward_dwt53_reference, forward_dwt97_reference,
415 forward_ict_reference, forward_rct_reference, pack_j2k_code_block_scalar_from_tier1_tokens,
416 quantize_reversible_reference, quantize_subband_reference, try_deinterleave_reference,
417 HtCodeBlockDecodeProfile, HtCodeBlockDecodeWorkspace, HtCodeBlockEncodeWorkspace,
418 J2kCodeBlockDecodeProfile, J2kCodeBlockDecodeWorkspace,
419};
420
421pub(crate) const JP2_MAGIC: &[u8] = b"\x00\x00\x00\x0C\x6A\x50\x20\x20";
423pub(crate) const CODESTREAM_MAGIC: &[u8] = b"\xFF\x4F\xFF\x51";
425
426mod image;
427pub use image::{DecodeSettings, Image, PreparedRegionDecoder};
428
429#[cfg(test)]
430mod tests;