1use alloc::vec::Vec;
4
5use crate::error::err;
6use crate::j2c::{self, Header};
7use crate::jp2::colr::EnumeratedColorspace;
8use crate::jp2::{self, DecodedImage, ImageBoxes};
9use crate::{
10 checked_decode_byte_len3, convert_color_space, interleave_and_convert,
11 interleave_and_convert_region, resolve_palette_indices, try_resize_decode_elements,
12 validate_and_reorder_channels, validate_interleaved_output_buffer, validate_roi, Bitmap,
13 ColorSpace, DecodedComponents, DecodedNativeComponents, DecoderContext, DecodingError,
14 FormatError, HtCodeBlockDecoder, Result, CODESTREAM_MAGIC, JP2_MAGIC,
15};
16
17mod allocation;
18mod compare;
19#[cfg(test)]
20mod contract_tests;
21mod direct_api;
22mod native;
23mod output_api;
24use self::allocation::retained_metadata_bytes;
25pub(crate) use self::allocation::{retained_container_metadata_bytes, DecodeOwnerBudget};
26use self::native::{try_clone_color_space, NativeOutputBudget};
27
28#[derive(Debug, Copy, Clone)]
30pub struct DecodeSettings {
31 pub resolve_palette_indices: bool,
43 pub strict: bool,
49 pub target_resolution: Option<(u32, u32)>,
51}
52
53impl DecodeSettings {
54 #[must_use]
71 pub const fn lenient() -> Self {
72 Self {
73 resolve_palette_indices: true,
74 strict: false,
75 target_resolution: None,
76 }
77 }
78
79 #[must_use]
81 pub const fn strict() -> Self {
82 Self {
83 resolve_palette_indices: true,
84 strict: true,
85 target_resolution: None,
86 }
87 }
88
89 #[must_use]
92 pub const fn lenient_tolerance_enabled(&self) -> bool {
93 !self.strict
94 }
95}
96
97impl Default for DecodeSettings {
98 fn default() -> Self {
99 Self::strict()
100 }
101}
102
103pub struct Image<'a> {
105 pub(crate) encoded_input: &'a [u8],
108 pub(crate) codestream: &'a [u8],
110 pub(crate) header: Header<'a>,
112 pub(crate) boxes: ImageBoxes,
115 pub(crate) settings: DecodeSettings,
117 pub(crate) used_lenient_metadata_recovery: bool,
120 pub(crate) has_alpha: bool,
122 pub(crate) color_space: ColorSpace,
124}
125
126#[derive(Clone, Copy)]
127pub(crate) struct ImageSource<'a> {
128 encoded_input: &'a [u8],
129 codestream: &'a [u8],
130}
131
132impl<'a> ImageSource<'a> {
133 pub(crate) const fn new(encoded_input: &'a [u8], codestream: &'a [u8]) -> Self {
134 Self {
135 encoded_input,
136 codestream,
137 }
138 }
139}
140
141pub(crate) struct ImageProperties {
142 boxes: ImageBoxes,
143 settings: DecodeSettings,
144 color_space: ColorSpace,
145 has_alpha: bool,
146 used_lenient_metadata_recovery: bool,
147}
148
149impl ImageProperties {
150 pub(crate) const fn new(
151 boxes: ImageBoxes,
152 settings: DecodeSettings,
153 color_space: ColorSpace,
154 has_alpha: bool,
155 used_lenient_metadata_recovery: bool,
156 ) -> Self {
157 Self {
158 boxes,
159 settings,
160 color_space,
161 has_alpha,
162 used_lenient_metadata_recovery,
163 }
164 }
165}
166
167impl<'a> Image<'a> {
168 pub(crate) fn from_parsed_parts(
169 source: ImageSource<'a>,
170 header: Header<'a>,
171 properties: ImageProperties,
172 ) -> Result<Self> {
173 Self::from_parsed_parts_with_retained_baseline(source, header, properties, 0)
174 }
175
176 pub(crate) fn from_parsed_parts_with_retained_baseline(
177 source: ImageSource<'a>,
178 header: Header<'a>,
179 properties: ImageProperties,
180 retained_baseline_bytes: usize,
181 ) -> Result<Self> {
182 let ImageProperties {
183 boxes,
184 settings,
185 color_space,
186 has_alpha,
187 used_lenient_metadata_recovery,
188 } = properties;
189 let metadata_bytes = retained_metadata_bytes(&header, &boxes, &color_space)?;
190 allocation::combine_retained_bytes(retained_baseline_bytes, metadata_bytes)?;
191 Ok(Self {
192 encoded_input: source.encoded_input,
193 codestream: source.codestream,
194 header,
195 boxes,
196 settings,
197 used_lenient_metadata_recovery,
198 has_alpha,
199 color_space,
200 })
201 }
202
203 pub(crate) fn retained_metadata_bytes(&self) -> Result<usize> {
204 retained_metadata_bytes(&self.header, &self.boxes, &self.color_space)
205 }
206
207 #[doc(hidden)]
214 pub fn retained_allocation_bytes(&self) -> Result<usize> {
215 self.retained_metadata_bytes()
216 }
217
218 #[doc(hidden)]
220 #[must_use]
221 pub const fn used_lenient_metadata_recovery(&self) -> bool {
222 self.used_lenient_metadata_recovery
223 }
224
225 pub fn new(data: &'a [u8], settings: &DecodeSettings) -> Result<Self> {
231 if data.starts_with(JP2_MAGIC) {
232 jp2::parse(data, *settings)
233 } else if data.starts_with(CODESTREAM_MAGIC) {
234 j2c::parse(data, settings)
235 } else {
236 err!(FormatError::InvalidSignature)
237 }
238 }
239
240 #[doc(hidden)]
250 pub fn new_with_retained_baseline(
251 data: &'a [u8],
252 settings: &DecodeSettings,
253 retained_baseline_bytes: usize,
254 ) -> Result<Self> {
255 if retained_baseline_bytes == 0 {
256 return Self::new(data, settings);
257 }
258 if data.starts_with(JP2_MAGIC) {
259 jp2::parse_with_retained_baseline(data, *settings, retained_baseline_bytes)
260 } else if data.starts_with(CODESTREAM_MAGIC) {
261 j2c::parse_with_retained_baseline(data, settings, retained_baseline_bytes)
262 } else {
263 err!(FormatError::InvalidSignature)
264 }
265 }
266
267 #[must_use]
269 pub fn has_alpha(&self) -> bool {
270 self.has_alpha
271 }
272
273 #[must_use]
275 pub fn color_space(&self) -> &ColorSpace {
276 &self.color_space
277 }
278
279 #[must_use]
281 pub fn width(&self) -> u32 {
282 self.header.size_data.image_width()
283 }
284
285 #[must_use]
287 pub fn height(&self) -> u32 {
288 self.header.size_data.image_height()
289 }
290
291 #[must_use]
294 pub fn original_bit_depth(&self) -> u8 {
295 self.header.component_infos[0].size_info.precision
297 }
298
299 #[doc(hidden)]
301 #[must_use]
302 pub fn supports_direct_device_plane_reuse(&self) -> bool {
303 if self.settings.resolve_palette_indices && self.boxes.palette.is_some() {
304 return false;
305 }
306 if self.boxes.channel_definition.is_some() {
307 return false;
308 }
309 !matches!(
310 self.boxes
311 .primary_color_specification()
312 .map(|spec| &spec.color_space),
313 Some(jp2::colr::ColorSpace::Enumerated(
314 EnumeratedColorspace::Sycc | EnumeratedColorspace::CieLab(_)
315 ))
316 )
317 }
318
319 pub fn decode(&self) -> Result<Vec<u8>> {
326 let bitmap = self.decode_with_context(&mut DecoderContext::default())?;
327 Ok(bitmap.data)
328 }
329
330 pub fn decode_with_context(&self, decoder_context: &mut DecoderContext<'a>) -> Result<Bitmap> {
337 (|| {
338 let retained_image_bytes = self.retained_metadata_bytes()?;
339 let mut decoded_image =
340 self.decode_image(decoder_context, None, None, retained_image_bytes)?;
341 let component_owner_capacity = decoded_image.decoded_components.capacity();
342 let buffer_size = checked_decode_byte_len3(
343 self.width() as usize,
344 self.height() as usize,
345 decoded_image.decoded_components.len(),
346 )?;
347 let mut budget = NativeOutputBudget::for_decoded_channels(
348 retained_image_bytes,
349 decoded_image.decoded_components,
350 component_owner_capacity,
351 )?;
352 budget.include_elements::<u8>(buffer_size)?;
353 budget.include_color_space_clone(&self.color_space)?;
354
355 let color_space = try_clone_color_space(&self.color_space)?;
356 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
357 let mut data = Vec::new();
358 try_resize_decode_elements(&mut data, buffer_size, 0_u8)?;
359 budget.include_capacity_overage::<u8>(buffer_size, data.capacity())?;
360 validate_interleaved_output_buffer(&decoded_image, &data)?;
361 interleave_and_convert(&mut decoded_image, &mut data)?;
362 let bitmap = Bitmap {
363 color_space,
364 data,
365 has_alpha: self.has_alpha,
366 width: self.width(),
367 height: self.height(),
368 original_bit_depth: self.original_bit_depth(),
369 };
370 NativeOutputBudget::validate_bitmap_pack(
371 retained_image_bytes,
372 decoded_image.decoded_components,
373 component_owner_capacity,
374 &bitmap,
375 )?;
376 Ok(bitmap)
377 })()
378 }
379
380 pub fn decode_components_with_context<'ctx>(
387 &self,
388 decoder_context: &'ctx mut DecoderContext<'a>,
389 ) -> Result<DecodedComponents<'ctx>> {
390 self.validate_component_plane_precision()?;
391 let decoded_image =
392 self.decode_image(decoder_context, None, None, self.retained_metadata_bytes()?)?;
393 let DecodedImage {
394 decoded_components,
395 boxes: _,
396 } = decoded_image;
397 self.try_borrow_component_planes(
398 decoded_components.as_slice(),
399 decoded_components.capacity(),
400 (self.width(), self.height()),
401 )
402 }
403
404 pub fn decode_native_components(&self) -> Result<DecodedNativeComponents> {
414 let mut decoder_context = DecoderContext::default();
415 self.decode_native_components_with_context(&mut decoder_context)
416 }
417
418 #[doc(hidden)]
429 pub fn decode_native_components_with_retained_capacity(
430 &self,
431 retained_capacity: usize,
432 ) -> Result<DecodedNativeComponents> {
433 let retained_baseline_bytes =
434 allocation::combine_retained_bytes(retained_capacity, self.retained_metadata_bytes()?)?;
435 let mut decoder_context = DecoderContext::default();
436 self.decode_native_components_with_context_and_retained_baseline(
437 &mut decoder_context,
438 retained_baseline_bytes,
439 )
440 }
441
442 pub fn decode_native_components_with_context(
449 &self,
450 decoder_context: &mut DecoderContext<'a>,
451 ) -> Result<DecodedNativeComponents> {
452 let retained_baseline_bytes = self.retained_metadata_bytes()?;
453 self.decode_native_components_with_context_and_retained_baseline(
454 decoder_context,
455 retained_baseline_bytes,
456 )
457 }
458
459 fn decode_native_components_with_context_and_retained_baseline(
460 &self,
461 decoder_context: &mut DecoderContext<'a>,
462 retained_baseline_bytes: usize,
463 ) -> Result<DecodedNativeComponents> {
464 let decoded_image =
465 self.decode_image(decoder_context, None, None, retained_baseline_bytes)?;
466 let DecodedImage {
467 decoded_components,
468 boxes: _,
469 } = decoded_image;
470 let component_owner_capacity = decoded_components.capacity();
471 self.pack_native_component_planes(
472 decoded_components,
473 component_owner_capacity,
474 (self.width(), self.height()),
475 retained_baseline_bytes,
476 )
477 }
478
479 #[doc(hidden)]
481 pub fn decode_components_with_ht_decoder<'ctx>(
482 &self,
483 decoder_context: &'ctx mut DecoderContext<'a>,
484 ht_decoder: &mut dyn HtCodeBlockDecoder,
485 ) -> Result<DecodedComponents<'ctx>> {
486 self.validate_component_plane_precision()?;
487 let decoded_image = self.decode_image(
488 decoder_context,
489 None,
490 Some(ht_decoder),
491 self.retained_metadata_bytes()?,
492 )?;
493 let DecodedImage {
494 decoded_components,
495 boxes: _,
496 } = decoded_image;
497 self.try_borrow_component_planes(
498 decoded_components.as_slice(),
499 decoded_components.capacity(),
500 (self.width(), self.height()),
501 )
502 }
503
504 pub fn decode_region_components_with_context<'ctx>(
511 &self,
512 roi: (u32, u32, u32, u32),
513 decoder_context: &'ctx mut DecoderContext<'a>,
514 ) -> Result<DecodedComponents<'ctx>> {
515 validate_roi((self.width(), self.height()), roi)?;
516 self.validate_component_plane_precision()?;
517 let (_x, _y, width, height) = roi;
518 let decoded_image = self.decode_image(
519 decoder_context,
520 Some(roi),
521 None,
522 self.retained_metadata_bytes()?,
523 )?;
524 let DecodedImage {
525 decoded_components,
526 boxes: _,
527 } = decoded_image;
528 self.try_borrow_component_planes(
529 decoded_components.as_slice(),
530 decoded_components.capacity(),
531 (width, height),
532 )
533 }
534
535 pub fn decode_native_region_components_with_context(
542 &self,
543 roi: (u32, u32, u32, u32),
544 decoder_context: &mut DecoderContext<'a>,
545 ) -> Result<DecodedNativeComponents> {
546 validate_roi((self.width(), self.height()), roi)?;
547 if self.requires_exact_integer_decode() {
548 return self.decode_native_region_components_via_full_decode(roi, decoder_context);
549 }
550 let (_x, _y, width, height) = roi;
551 let retained_image_bytes = self.retained_metadata_bytes()?;
552 let decoded_image =
553 self.decode_image(decoder_context, Some(roi), None, retained_image_bytes)?;
554 let DecodedImage {
555 decoded_components,
556 boxes: _,
557 } = decoded_image;
558 let component_owner_capacity = decoded_components.capacity();
559 self.pack_native_component_planes(
560 decoded_components,
561 component_owner_capacity,
562 (width, height),
563 retained_image_bytes,
564 )
565 }
566
567 #[doc(hidden)]
570 pub fn decode_region_components_with_ht_decoder<'ctx>(
571 &self,
572 decoder_context: &'ctx mut DecoderContext<'a>,
573 roi: (u32, u32, u32, u32),
574 ht_decoder: &mut dyn HtCodeBlockDecoder,
575 ) -> Result<DecodedComponents<'ctx>> {
576 validate_roi((self.width(), self.height()), roi)?;
577 self.validate_component_plane_precision()?;
578 let (_x, _y, width, height) = roi;
579 let decoded_image = self.decode_image(
580 decoder_context,
581 Some(roi),
582 Some(ht_decoder),
583 self.retained_metadata_bytes()?,
584 )?;
585 let DecodedImage {
586 decoded_components,
587 boxes: _,
588 } = decoded_image;
589 self.try_borrow_component_planes(
590 decoded_components.as_slice(),
591 decoded_components.capacity(),
592 (width, height),
593 )
594 }
595
596 pub fn decode_region(&self, roi: (u32, u32, u32, u32)) -> Result<Bitmap> {
602 self.decode_region_with_context(roi, &mut DecoderContext::default())
603 }
604
605 pub fn decode_region_with_context(
612 &self,
613 roi: (u32, u32, u32, u32),
614 decoder_context: &mut DecoderContext<'a>,
615 ) -> Result<Bitmap> {
616 validate_roi((self.width(), self.height()), roi)?;
617 (|| {
618 let retained_image_bytes = self.retained_metadata_bytes()?;
619 let mut decoded_image =
620 self.decode_image(decoder_context, Some(roi), None, retained_image_bytes)?;
621 let component_owner_capacity = decoded_image.decoded_components.capacity();
622 let (_x, _y, width, height) = roi;
623 let data_len = checked_decode_byte_len3(
624 width as usize,
625 height as usize,
626 decoded_image.decoded_components.len(),
627 )?;
628 let mut budget = NativeOutputBudget::for_decoded_channels(
629 retained_image_bytes,
630 decoded_image.decoded_components,
631 component_owner_capacity,
632 )?;
633 budget.include_elements::<u8>(data_len)?;
634 budget.include_color_space_clone(&self.color_space)?;
635
636 let color_space = try_clone_color_space(&self.color_space)?;
637 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
638 let mut data = Vec::new();
639 try_resize_decode_elements(&mut data, data_len, 0_u8)?;
640 budget.include_capacity_overage::<u8>(data_len, data.capacity())?;
641 interleave_and_convert_region(
642 &mut decoded_image,
643 width as usize,
644 (0, 0, width, height),
645 &mut data,
646 );
647 let bitmap = Bitmap {
648 color_space,
649 data,
650 has_alpha: self.has_alpha,
651 width,
652 height,
653 original_bit_depth: self.original_bit_depth(),
654 };
655 NativeOutputBudget::validate_bitmap_pack(
656 retained_image_bytes,
657 decoded_image.decoded_components,
658 component_owner_capacity,
659 &bitmap,
660 )?;
661 Ok(bitmap)
662 })()
663 }
664
665 pub fn decode_into(
679 &self,
680 buf: &mut [u8],
681 decoder_context: &mut DecoderContext<'a>,
682 ) -> Result<()> {
683 let mut decoded_image =
684 self.decode_image(decoder_context, None, None, self.retained_metadata_bytes()?)?;
685 validate_interleaved_output_buffer(&decoded_image, buf)?;
686 interleave_and_convert(&mut decoded_image, buf)?;
687
688 Ok(())
689 }
690
691 fn decode_image<'ctx>(
692 &self,
693 decoder_context: &'ctx mut DecoderContext<'a>,
694 output_region: Option<(u32, u32, u32, u32)>,
695 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
696 retained_baseline_bytes: usize,
697 ) -> Result<DecodedImage<'ctx, '_>> {
698 let settings = &self.settings;
699 let mut ht_decoder = ht_decoder;
700 decoder_context.set_output_region(output_region);
701 let decode_result = j2c::decode(
702 self.codestream,
703 &self.header,
704 retained_baseline_bytes,
705 decoder_context,
706 &mut ht_decoder,
707 );
708 decoder_context.set_output_region(None);
709 decode_result?;
710 let mut decoded_image = DecodedImage {
711 decoded_components: &mut decoder_context.tile_decode_context.channel_data,
712 boxes: &self.boxes,
713 };
714
715 if settings.resolve_palette_indices {
716 let components = core::mem::take(decoded_image.decoded_components);
717 *decoded_image.decoded_components =
718 resolve_palette_indices(components, decoded_image.boxes, retained_baseline_bytes)?;
719 }
720
721 if let Some(cdef) = &decoded_image.boxes.channel_definition {
722 validate_and_reorder_channels(
723 cdef,
724 decoded_image.decoded_components,
725 retained_baseline_bytes,
726 )?;
727 }
728
729 let bit_depth = decoded_image
730 .decoded_components
731 .first()
732 .ok_or(DecodingError::CodeBlockDecodeFailure)?
733 .bit_depth;
734 convert_color_space(&mut decoded_image, bit_depth)?;
735 Ok(decoded_image)
736 }
737}