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,
50 pub target_resolution: Option<(u32, u32)>,
52}
53
54impl DecodeSettings {
55 #[must_use]
60 pub const fn lenient() -> Self {
61 Self {
62 resolve_palette_indices: true,
63 strict: false,
64 target_resolution: None,
65 }
66 }
67
68 #[must_use]
70 pub const fn strict() -> Self {
71 Self {
72 resolve_palette_indices: true,
73 strict: true,
74 target_resolution: None,
75 }
76 }
77
78 #[must_use]
81 pub const fn lenient_tolerance_enabled(&self) -> bool {
82 !self.strict
83 }
84}
85
86impl Default for DecodeSettings {
87 fn default() -> Self {
88 Self::lenient()
89 }
90}
91
92pub struct Image<'a> {
94 pub(crate) codestream: &'a [u8],
96 pub(crate) header: Header<'a>,
98 pub(crate) boxes: ImageBoxes,
101 pub(crate) settings: DecodeSettings,
103 pub(crate) has_alpha: bool,
105 pub(crate) color_space: ColorSpace,
107}
108
109impl<'a> Image<'a> {
110 pub(crate) fn from_parsed_parts(
111 codestream: &'a [u8],
112 header: Header<'a>,
113 boxes: ImageBoxes,
114 settings: DecodeSettings,
115 color_space: ColorSpace,
116 has_alpha: bool,
117 ) -> Result<Self> {
118 Self::from_parsed_parts_with_retained_baseline(
119 codestream,
120 header,
121 boxes,
122 settings,
123 color_space,
124 has_alpha,
125 0,
126 )
127 }
128
129 pub(crate) fn from_parsed_parts_with_retained_baseline(
130 codestream: &'a [u8],
131 header: Header<'a>,
132 boxes: ImageBoxes,
133 settings: DecodeSettings,
134 color_space: ColorSpace,
135 has_alpha: bool,
136 retained_baseline_bytes: usize,
137 ) -> Result<Self> {
138 let metadata_bytes = retained_metadata_bytes(&header, &boxes, &color_space)?;
139 allocation::combine_retained_bytes(retained_baseline_bytes, metadata_bytes)?;
140 Ok(Self {
141 codestream,
142 header,
143 boxes,
144 settings,
145 has_alpha,
146 color_space,
147 })
148 }
149
150 pub(crate) fn retained_metadata_bytes(&self) -> Result<usize> {
151 retained_metadata_bytes(&self.header, &self.boxes, &self.color_space)
152 }
153
154 #[doc(hidden)]
161 pub fn retained_allocation_bytes(&self) -> Result<usize> {
162 self.retained_metadata_bytes()
163 }
164
165 pub fn new(data: &'a [u8], settings: &DecodeSettings) -> Result<Self> {
171 if data.starts_with(JP2_MAGIC) {
172 jp2::parse(data, *settings)
173 } else if data.starts_with(CODESTREAM_MAGIC) {
174 j2c::parse(data, settings)
175 } else {
176 err!(FormatError::InvalidSignature)
177 }
178 }
179
180 #[doc(hidden)]
190 pub fn new_with_retained_baseline(
191 data: &'a [u8],
192 settings: &DecodeSettings,
193 retained_baseline_bytes: usize,
194 ) -> Result<Self> {
195 if retained_baseline_bytes == 0 {
196 return Self::new(data, settings);
197 }
198 if data.starts_with(JP2_MAGIC) {
199 jp2::parse_with_retained_baseline(data, *settings, retained_baseline_bytes)
200 } else if data.starts_with(CODESTREAM_MAGIC) {
201 j2c::parse_with_retained_baseline(data, settings, retained_baseline_bytes)
202 } else {
203 err!(FormatError::InvalidSignature)
204 }
205 }
206
207 #[must_use]
209 pub fn has_alpha(&self) -> bool {
210 self.has_alpha
211 }
212
213 #[must_use]
215 pub fn color_space(&self) -> &ColorSpace {
216 &self.color_space
217 }
218
219 #[must_use]
221 pub fn width(&self) -> u32 {
222 self.header.size_data.image_width()
223 }
224
225 #[must_use]
227 pub fn height(&self) -> u32 {
228 self.header.size_data.image_height()
229 }
230
231 #[must_use]
234 pub fn original_bit_depth(&self) -> u8 {
235 self.header.component_infos[0].size_info.precision
237 }
238
239 #[doc(hidden)]
241 #[must_use]
242 pub fn supports_direct_device_plane_reuse(&self) -> bool {
243 if self.settings.resolve_palette_indices && self.boxes.palette.is_some() {
244 return false;
245 }
246 if self.boxes.channel_definition.is_some() {
247 return false;
248 }
249 !matches!(
250 self.boxes
251 .primary_color_specification()
252 .map(|spec| &spec.color_space),
253 Some(jp2::colr::ColorSpace::Enumerated(
254 EnumeratedColorspace::Sycc | EnumeratedColorspace::CieLab(_)
255 ))
256 )
257 }
258
259 pub fn decode(&self) -> Result<Vec<u8>> {
266 let bitmap = self.decode_with_context(&mut DecoderContext::default())?;
267 Ok(bitmap.data)
268 }
269
270 pub fn decode_with_context(&self, decoder_context: &mut DecoderContext<'a>) -> Result<Bitmap> {
277 (|| {
278 let retained_image_bytes = self.retained_metadata_bytes()?;
279 let mut decoded_image = self.prepare_decoded_image(decoder_context)?;
280 let component_owner_capacity = decoded_image.decoded_components.capacity();
281 let buffer_size = checked_decode_byte_len3(
282 self.width() as usize,
283 self.height() as usize,
284 decoded_image.decoded_components.len(),
285 )?;
286 let mut budget = NativeOutputBudget::for_component_pack(
287 retained_image_bytes,
288 decoded_image.decoded_components,
289 component_owner_capacity,
290 )?;
291 budget.include_elements::<u8>(buffer_size)?;
292 budget.include_color_space_clone(&self.color_space)?;
293
294 let color_space = try_clone_color_space(&self.color_space)?;
295 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
296 let mut data = Vec::new();
297 try_resize_decode_elements(&mut data, buffer_size, 0_u8)?;
298 budget.include_capacity_overage::<u8>(buffer_size, data.capacity())?;
299 validate_interleaved_output_buffer(&decoded_image, &data)?;
300 interleave_and_convert(&mut decoded_image, &mut data)?;
301 let bitmap = Bitmap {
302 color_space,
303 data,
304 has_alpha: self.has_alpha,
305 width: self.width(),
306 height: self.height(),
307 original_bit_depth: self.original_bit_depth(),
308 };
309 NativeOutputBudget::validate_bitmap_pack(
310 retained_image_bytes,
311 decoded_image.decoded_components,
312 component_owner_capacity,
313 &bitmap,
314 )?;
315 Ok(bitmap)
316 })()
317 }
318
319 pub fn decode_components_with_context<'ctx>(
326 &self,
327 decoder_context: &'ctx mut DecoderContext<'a>,
328 ) -> Result<DecodedComponents<'ctx>> {
329 self.validate_component_plane_precision()?;
330 let decoded_image = self.prepare_decoded_image(decoder_context)?;
331 let DecodedImage {
332 decoded_components,
333 boxes: _,
334 } = decoded_image;
335 self.try_borrow_component_planes(
336 decoded_components.as_slice(),
337 decoded_components.capacity(),
338 (self.width(), self.height()),
339 )
340 }
341
342 pub fn decode_native_components(&self) -> Result<DecodedNativeComponents> {
352 let mut decoder_context = DecoderContext::default();
353 self.decode_native_components_with_context(&mut decoder_context)
354 }
355
356 #[doc(hidden)]
367 pub fn decode_native_components_with_retained_capacity(
368 &self,
369 retained_capacity: usize,
370 ) -> Result<DecodedNativeComponents> {
371 let retained_baseline_bytes =
372 allocation::combine_retained_bytes(retained_capacity, self.retained_metadata_bytes()?)?;
373 let mut decoder_context = DecoderContext::default();
374 self.decode_native_components_with_context_and_retained_baseline(
375 &mut decoder_context,
376 retained_baseline_bytes,
377 )
378 }
379
380 pub fn decode_native_components_with_context(
387 &self,
388 decoder_context: &mut DecoderContext<'a>,
389 ) -> Result<DecodedNativeComponents> {
390 let retained_baseline_bytes = self.retained_metadata_bytes()?;
391 self.decode_native_components_with_context_and_retained_baseline(
392 decoder_context,
393 retained_baseline_bytes,
394 )
395 }
396
397 fn decode_native_components_with_context_and_retained_baseline(
398 &self,
399 decoder_context: &mut DecoderContext<'a>,
400 retained_baseline_bytes: usize,
401 ) -> Result<DecodedNativeComponents> {
402 let decoded_image = self.prepare_decoded_image_with_retained_baseline(
403 decoder_context,
404 retained_baseline_bytes,
405 )?;
406 let DecodedImage {
407 decoded_components,
408 boxes: _,
409 } = decoded_image;
410 let component_owner_capacity = decoded_components.capacity();
411 self.pack_native_component_planes(
412 decoded_components,
413 component_owner_capacity,
414 (self.width(), self.height()),
415 retained_baseline_bytes,
416 )
417 }
418
419 #[doc(hidden)]
421 pub fn decode_components_with_ht_decoder<'ctx>(
422 &self,
423 decoder_context: &'ctx mut DecoderContext<'a>,
424 ht_decoder: &mut dyn HtCodeBlockDecoder,
425 ) -> Result<DecodedComponents<'ctx>> {
426 self.validate_component_plane_precision()?;
427 let decoded_image =
428 self.prepare_decoded_image_with_ht_decoder(decoder_context, ht_decoder)?;
429 let DecodedImage {
430 decoded_components,
431 boxes: _,
432 } = decoded_image;
433 self.try_borrow_component_planes(
434 decoded_components.as_slice(),
435 decoded_components.capacity(),
436 (self.width(), self.height()),
437 )
438 }
439
440 pub fn decode_region_components_with_context<'ctx>(
447 &self,
448 roi: (u32, u32, u32, u32),
449 decoder_context: &'ctx mut DecoderContext<'a>,
450 ) -> Result<DecodedComponents<'ctx>> {
451 validate_roi((self.width(), self.height()), roi)?;
452 self.validate_component_plane_precision()?;
453 let (_x, _y, width, height) = roi;
454 let decoded_image = self.prepare_decoded_image_with_region(decoder_context, Some(roi))?;
455 let DecodedImage {
456 decoded_components,
457 boxes: _,
458 } = decoded_image;
459 self.try_borrow_component_planes(
460 decoded_components.as_slice(),
461 decoded_components.capacity(),
462 (width, height),
463 )
464 }
465
466 pub fn decode_native_region_components_with_context(
473 &self,
474 roi: (u32, u32, u32, u32),
475 decoder_context: &mut DecoderContext<'a>,
476 ) -> Result<DecodedNativeComponents> {
477 validate_roi((self.width(), self.height()), roi)?;
478 if self.requires_exact_integer_decode() {
479 return self.decode_native_region_components_via_full_decode(roi, decoder_context);
480 }
481 let (_x, _y, width, height) = roi;
482 let decoded_image = self.prepare_decoded_image_with_region(decoder_context, Some(roi))?;
483 let DecodedImage {
484 decoded_components,
485 boxes: _,
486 } = decoded_image;
487 let component_owner_capacity = decoded_components.capacity();
488 self.pack_native_component_planes(
489 decoded_components,
490 component_owner_capacity,
491 (width, height),
492 self.retained_metadata_bytes()?,
493 )
494 }
495
496 #[doc(hidden)]
499 pub fn decode_region_components_with_ht_decoder<'ctx>(
500 &self,
501 decoder_context: &'ctx mut DecoderContext<'a>,
502 roi: (u32, u32, u32, u32),
503 ht_decoder: &mut dyn HtCodeBlockDecoder,
504 ) -> Result<DecodedComponents<'ctx>> {
505 validate_roi((self.width(), self.height()), roi)?;
506 self.validate_component_plane_precision()?;
507 let (_x, _y, width, height) = roi;
508 let decoded_image = self.prepare_decoded_image_with_region_and_ht_decoder(
509 decoder_context,
510 Some(roi),
511 Some(ht_decoder),
512 )?;
513 let DecodedImage {
514 decoded_components,
515 boxes: _,
516 } = decoded_image;
517 self.try_borrow_component_planes(
518 decoded_components.as_slice(),
519 decoded_components.capacity(),
520 (width, height),
521 )
522 }
523
524 pub fn decode_region(&self, roi: (u32, u32, u32, u32)) -> Result<Bitmap> {
530 self.decode_region_with_context(roi, &mut DecoderContext::default())
531 }
532
533 pub fn decode_region_with_context(
540 &self,
541 roi: (u32, u32, u32, u32),
542 decoder_context: &mut DecoderContext<'a>,
543 ) -> Result<Bitmap> {
544 validate_roi((self.width(), self.height()), roi)?;
545 (|| {
546 let retained_image_bytes = self.retained_metadata_bytes()?;
547 let mut decoded_image =
548 self.prepare_decoded_image_with_region(decoder_context, Some(roi))?;
549 let component_owner_capacity = decoded_image.decoded_components.capacity();
550 let (_x, _y, width, height) = roi;
551 let data_len = checked_decode_byte_len3(
552 width as usize,
553 height as usize,
554 decoded_image.decoded_components.len(),
555 )?;
556 let mut budget = NativeOutputBudget::for_component_pack(
557 retained_image_bytes,
558 decoded_image.decoded_components,
559 component_owner_capacity,
560 )?;
561 budget.include_elements::<u8>(data_len)?;
562 budget.include_color_space_clone(&self.color_space)?;
563
564 let color_space = try_clone_color_space(&self.color_space)?;
565 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
566 let mut data = Vec::new();
567 try_resize_decode_elements(&mut data, data_len, 0_u8)?;
568 budget.include_capacity_overage::<u8>(data_len, data.capacity())?;
569 interleave_and_convert_region(
570 &mut decoded_image,
571 width as usize,
572 (0, 0, width, height),
573 &mut data,
574 );
575 let bitmap = Bitmap {
576 color_space,
577 data,
578 has_alpha: self.has_alpha,
579 width,
580 height,
581 original_bit_depth: self.original_bit_depth(),
582 };
583 NativeOutputBudget::validate_bitmap_pack(
584 retained_image_bytes,
585 decoded_image.decoded_components,
586 component_owner_capacity,
587 &bitmap,
588 )?;
589 Ok(bitmap)
590 })()
591 }
592
593 pub fn decode_into(
607 &self,
608 buf: &mut [u8],
609 decoder_context: &mut DecoderContext<'a>,
610 ) -> Result<()> {
611 let mut decoded_image = self.prepare_decoded_image(decoder_context)?;
612 validate_interleaved_output_buffer(&decoded_image, buf)?;
613 interleave_and_convert(&mut decoded_image, buf)?;
614
615 Ok(())
616 }
617
618 fn prepare_decoded_image<'ctx>(
619 &self,
620 decoder_context: &'ctx mut DecoderContext<'a>,
621 ) -> Result<DecodedImage<'ctx, '_>> {
622 self.prepare_decoded_image_with_region(decoder_context, None)
623 }
624
625 fn prepare_decoded_image_with_retained_baseline<'ctx>(
626 &self,
627 decoder_context: &'ctx mut DecoderContext<'a>,
628 retained_baseline_bytes: usize,
629 ) -> Result<DecodedImage<'ctx, '_>> {
630 self.prepare_decoded_image_with_region_and_ht_decoder_with_retained_baseline(
631 decoder_context,
632 None,
633 None,
634 retained_baseline_bytes,
635 )
636 }
637
638 fn prepare_decoded_image_with_ht_decoder<'ctx>(
639 &self,
640 decoder_context: &'ctx mut DecoderContext<'a>,
641 ht_decoder: &mut dyn HtCodeBlockDecoder,
642 ) -> Result<DecodedImage<'ctx, '_>> {
643 self.prepare_decoded_image_with_region_and_ht_decoder(
644 decoder_context,
645 None,
646 Some(ht_decoder),
647 )
648 }
649
650 fn prepare_decoded_image_with_region<'ctx>(
651 &self,
652 decoder_context: &'ctx mut DecoderContext<'a>,
653 output_region: Option<(u32, u32, u32, u32)>,
654 ) -> Result<DecodedImage<'ctx, '_>> {
655 self.prepare_decoded_image_with_region_and_ht_decoder(decoder_context, output_region, None)
656 }
657
658 fn prepare_decoded_image_with_region_and_ht_decoder<'ctx>(
659 &self,
660 decoder_context: &'ctx mut DecoderContext<'a>,
661 output_region: Option<(u32, u32, u32, u32)>,
662 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
663 ) -> Result<DecodedImage<'ctx, '_>> {
664 let retained_baseline_bytes = self.retained_metadata_bytes()?;
665 self.prepare_decoded_image_with_region_and_ht_decoder_with_retained_baseline(
666 decoder_context,
667 output_region,
668 ht_decoder,
669 retained_baseline_bytes,
670 )
671 }
672
673 fn prepare_decoded_image_with_region_and_ht_decoder_with_retained_baseline<'ctx>(
674 &self,
675 decoder_context: &'ctx mut DecoderContext<'a>,
676 output_region: Option<(u32, u32, u32, u32)>,
677 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
678 retained_baseline_bytes: usize,
679 ) -> Result<DecodedImage<'ctx, '_>> {
680 let settings = &self.settings;
681 self.decode_with_output_region_and_ht_decoder_with_retained_baseline(
682 decoder_context,
683 output_region,
684 ht_decoder,
685 retained_baseline_bytes,
686 )?;
687 let mut decoded_image = DecodedImage {
688 decoded_components: &mut decoder_context.tile_decode_context.channel_data,
689 boxes: &self.boxes,
690 };
691
692 if settings.resolve_palette_indices {
693 let components = core::mem::take(decoded_image.decoded_components);
694 *decoded_image.decoded_components =
695 resolve_palette_indices(components, decoded_image.boxes, retained_baseline_bytes)?;
696 }
697
698 if let Some(cdef) = &decoded_image.boxes.channel_definition {
699 validate_and_reorder_channels(
700 cdef,
701 decoded_image.decoded_components,
702 retained_baseline_bytes,
703 )?;
704 }
705
706 let bit_depth = decoded_image
707 .decoded_components
708 .first()
709 .ok_or(DecodingError::CodeBlockDecodeFailure)?
710 .bit_depth;
711 convert_color_space(&mut decoded_image, bit_depth)?;
712 Ok(decoded_image)
713 }
714
715 fn decode_with_output_region(
716 &self,
717 decoder_context: &mut DecoderContext<'a>,
718 output_region: Option<(u32, u32, u32, u32)>,
719 ) -> Result<()> {
720 self.decode_with_output_region_and_ht_decoder(decoder_context, output_region, None)
721 }
722
723 fn decode_with_output_region_and_ht_decoder(
724 &self,
725 decoder_context: &mut DecoderContext<'a>,
726 output_region: Option<(u32, u32, u32, u32)>,
727 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
728 ) -> Result<()> {
729 let retained_metadata_bytes = self.retained_metadata_bytes()?;
730 self.decode_with_output_region_and_ht_decoder_with_retained_baseline(
731 decoder_context,
732 output_region,
733 ht_decoder,
734 retained_metadata_bytes,
735 )
736 }
737
738 fn decode_with_output_region_and_ht_decoder_with_retained_baseline(
739 &self,
740 decoder_context: &mut DecoderContext<'a>,
741 output_region: Option<(u32, u32, u32, u32)>,
742 mut ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
743 retained_baseline_bytes: usize,
744 ) -> Result<()> {
745 decoder_context.set_output_region(output_region);
746 let decode_result = j2c::decode(
747 self.codestream,
748 &self.header,
749 retained_baseline_bytes,
750 decoder_context,
751 &mut ht_decoder,
752 );
753 decoder_context.set_output_region(None);
754 decode_result
755 }
756}