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) encoded_input: &'a [u8],
97 pub(crate) codestream: &'a [u8],
99 pub(crate) header: Header<'a>,
101 pub(crate) boxes: ImageBoxes,
104 pub(crate) settings: DecodeSettings,
106 pub(crate) has_alpha: bool,
108 pub(crate) color_space: ColorSpace,
110}
111
112#[derive(Clone, Copy)]
113pub(crate) struct ImageSource<'a> {
114 encoded_input: &'a [u8],
115 codestream: &'a [u8],
116}
117
118impl<'a> ImageSource<'a> {
119 pub(crate) const fn new(encoded_input: &'a [u8], codestream: &'a [u8]) -> Self {
120 Self {
121 encoded_input,
122 codestream,
123 }
124 }
125}
126
127impl<'a> Image<'a> {
128 pub(crate) fn from_parsed_parts(
129 source: ImageSource<'a>,
130 header: Header<'a>,
131 boxes: ImageBoxes,
132 settings: DecodeSettings,
133 color_space: ColorSpace,
134 has_alpha: bool,
135 ) -> Result<Self> {
136 Self::from_parsed_parts_with_retained_baseline(
137 source,
138 header,
139 boxes,
140 settings,
141 color_space,
142 has_alpha,
143 0,
144 )
145 }
146
147 pub(crate) fn from_parsed_parts_with_retained_baseline(
148 source: ImageSource<'a>,
149 header: Header<'a>,
150 boxes: ImageBoxes,
151 settings: DecodeSettings,
152 color_space: ColorSpace,
153 has_alpha: bool,
154 retained_baseline_bytes: usize,
155 ) -> Result<Self> {
156 let metadata_bytes = retained_metadata_bytes(&header, &boxes, &color_space)?;
157 allocation::combine_retained_bytes(retained_baseline_bytes, metadata_bytes)?;
158 Ok(Self {
159 encoded_input: source.encoded_input,
160 codestream: source.codestream,
161 header,
162 boxes,
163 settings,
164 has_alpha,
165 color_space,
166 })
167 }
168
169 pub(crate) fn retained_metadata_bytes(&self) -> Result<usize> {
170 retained_metadata_bytes(&self.header, &self.boxes, &self.color_space)
171 }
172
173 #[doc(hidden)]
180 pub fn retained_allocation_bytes(&self) -> Result<usize> {
181 self.retained_metadata_bytes()
182 }
183
184 pub fn new(data: &'a [u8], settings: &DecodeSettings) -> Result<Self> {
190 if data.starts_with(JP2_MAGIC) {
191 jp2::parse(data, *settings)
192 } else if data.starts_with(CODESTREAM_MAGIC) {
193 j2c::parse(data, settings)
194 } else {
195 err!(FormatError::InvalidSignature)
196 }
197 }
198
199 #[doc(hidden)]
209 pub fn new_with_retained_baseline(
210 data: &'a [u8],
211 settings: &DecodeSettings,
212 retained_baseline_bytes: usize,
213 ) -> Result<Self> {
214 if retained_baseline_bytes == 0 {
215 return Self::new(data, settings);
216 }
217 if data.starts_with(JP2_MAGIC) {
218 jp2::parse_with_retained_baseline(data, *settings, retained_baseline_bytes)
219 } else if data.starts_with(CODESTREAM_MAGIC) {
220 j2c::parse_with_retained_baseline(data, settings, retained_baseline_bytes)
221 } else {
222 err!(FormatError::InvalidSignature)
223 }
224 }
225
226 #[must_use]
228 pub fn has_alpha(&self) -> bool {
229 self.has_alpha
230 }
231
232 #[must_use]
234 pub fn color_space(&self) -> &ColorSpace {
235 &self.color_space
236 }
237
238 #[must_use]
240 pub fn width(&self) -> u32 {
241 self.header.size_data.image_width()
242 }
243
244 #[must_use]
246 pub fn height(&self) -> u32 {
247 self.header.size_data.image_height()
248 }
249
250 #[must_use]
253 pub fn original_bit_depth(&self) -> u8 {
254 self.header.component_infos[0].size_info.precision
256 }
257
258 #[doc(hidden)]
260 #[must_use]
261 pub fn supports_direct_device_plane_reuse(&self) -> bool {
262 if self.settings.resolve_palette_indices && self.boxes.palette.is_some() {
263 return false;
264 }
265 if self.boxes.channel_definition.is_some() {
266 return false;
267 }
268 !matches!(
269 self.boxes
270 .primary_color_specification()
271 .map(|spec| &spec.color_space),
272 Some(jp2::colr::ColorSpace::Enumerated(
273 EnumeratedColorspace::Sycc | EnumeratedColorspace::CieLab(_)
274 ))
275 )
276 }
277
278 pub fn decode(&self) -> Result<Vec<u8>> {
285 let bitmap = self.decode_with_context(&mut DecoderContext::default())?;
286 Ok(bitmap.data)
287 }
288
289 pub fn decode_with_context(&self, decoder_context: &mut DecoderContext<'a>) -> Result<Bitmap> {
296 (|| {
297 let retained_image_bytes = self.retained_metadata_bytes()?;
298 let mut decoded_image =
299 self.decode_image(decoder_context, None, None, retained_image_bytes)?;
300 let component_owner_capacity = decoded_image.decoded_components.capacity();
301 let buffer_size = checked_decode_byte_len3(
302 self.width() as usize,
303 self.height() as usize,
304 decoded_image.decoded_components.len(),
305 )?;
306 let mut budget = NativeOutputBudget::for_decoded_channels(
307 retained_image_bytes,
308 decoded_image.decoded_components,
309 component_owner_capacity,
310 )?;
311 budget.include_elements::<u8>(buffer_size)?;
312 budget.include_color_space_clone(&self.color_space)?;
313
314 let color_space = try_clone_color_space(&self.color_space)?;
315 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
316 let mut data = Vec::new();
317 try_resize_decode_elements(&mut data, buffer_size, 0_u8)?;
318 budget.include_capacity_overage::<u8>(buffer_size, data.capacity())?;
319 validate_interleaved_output_buffer(&decoded_image, &data)?;
320 interleave_and_convert(&mut decoded_image, &mut data)?;
321 let bitmap = Bitmap {
322 color_space,
323 data,
324 has_alpha: self.has_alpha,
325 width: self.width(),
326 height: self.height(),
327 original_bit_depth: self.original_bit_depth(),
328 };
329 NativeOutputBudget::validate_bitmap_pack(
330 retained_image_bytes,
331 decoded_image.decoded_components,
332 component_owner_capacity,
333 &bitmap,
334 )?;
335 Ok(bitmap)
336 })()
337 }
338
339 pub fn decode_components_with_context<'ctx>(
346 &self,
347 decoder_context: &'ctx mut DecoderContext<'a>,
348 ) -> Result<DecodedComponents<'ctx>> {
349 self.validate_component_plane_precision()?;
350 let decoded_image =
351 self.decode_image(decoder_context, None, None, self.retained_metadata_bytes()?)?;
352 let DecodedImage {
353 decoded_components,
354 boxes: _,
355 } = decoded_image;
356 self.try_borrow_component_planes(
357 decoded_components.as_slice(),
358 decoded_components.capacity(),
359 (self.width(), self.height()),
360 )
361 }
362
363 pub fn decode_native_components(&self) -> Result<DecodedNativeComponents> {
373 let mut decoder_context = DecoderContext::default();
374 self.decode_native_components_with_context(&mut decoder_context)
375 }
376
377 #[doc(hidden)]
388 pub fn decode_native_components_with_retained_capacity(
389 &self,
390 retained_capacity: usize,
391 ) -> Result<DecodedNativeComponents> {
392 let retained_baseline_bytes =
393 allocation::combine_retained_bytes(retained_capacity, self.retained_metadata_bytes()?)?;
394 let mut decoder_context = DecoderContext::default();
395 self.decode_native_components_with_context_and_retained_baseline(
396 &mut decoder_context,
397 retained_baseline_bytes,
398 )
399 }
400
401 pub fn decode_native_components_with_context(
408 &self,
409 decoder_context: &mut DecoderContext<'a>,
410 ) -> Result<DecodedNativeComponents> {
411 let retained_baseline_bytes = self.retained_metadata_bytes()?;
412 self.decode_native_components_with_context_and_retained_baseline(
413 decoder_context,
414 retained_baseline_bytes,
415 )
416 }
417
418 fn decode_native_components_with_context_and_retained_baseline(
419 &self,
420 decoder_context: &mut DecoderContext<'a>,
421 retained_baseline_bytes: usize,
422 ) -> Result<DecodedNativeComponents> {
423 let decoded_image =
424 self.decode_image(decoder_context, None, None, retained_baseline_bytes)?;
425 let DecodedImage {
426 decoded_components,
427 boxes: _,
428 } = decoded_image;
429 let component_owner_capacity = decoded_components.capacity();
430 self.pack_native_component_planes(
431 decoded_components,
432 component_owner_capacity,
433 (self.width(), self.height()),
434 retained_baseline_bytes,
435 )
436 }
437
438 #[doc(hidden)]
440 pub fn decode_components_with_ht_decoder<'ctx>(
441 &self,
442 decoder_context: &'ctx mut DecoderContext<'a>,
443 ht_decoder: &mut dyn HtCodeBlockDecoder,
444 ) -> Result<DecodedComponents<'ctx>> {
445 self.validate_component_plane_precision()?;
446 let decoded_image = self.decode_image(
447 decoder_context,
448 None,
449 Some(ht_decoder),
450 self.retained_metadata_bytes()?,
451 )?;
452 let DecodedImage {
453 decoded_components,
454 boxes: _,
455 } = decoded_image;
456 self.try_borrow_component_planes(
457 decoded_components.as_slice(),
458 decoded_components.capacity(),
459 (self.width(), self.height()),
460 )
461 }
462
463 pub fn decode_region_components_with_context<'ctx>(
470 &self,
471 roi: (u32, u32, u32, u32),
472 decoder_context: &'ctx mut DecoderContext<'a>,
473 ) -> Result<DecodedComponents<'ctx>> {
474 validate_roi((self.width(), self.height()), roi)?;
475 self.validate_component_plane_precision()?;
476 let (_x, _y, width, height) = roi;
477 let decoded_image = self.decode_image(
478 decoder_context,
479 Some(roi),
480 None,
481 self.retained_metadata_bytes()?,
482 )?;
483 let DecodedImage {
484 decoded_components,
485 boxes: _,
486 } = decoded_image;
487 self.try_borrow_component_planes(
488 decoded_components.as_slice(),
489 decoded_components.capacity(),
490 (width, height),
491 )
492 }
493
494 pub fn decode_native_region_components_with_context(
501 &self,
502 roi: (u32, u32, u32, u32),
503 decoder_context: &mut DecoderContext<'a>,
504 ) -> Result<DecodedNativeComponents> {
505 validate_roi((self.width(), self.height()), roi)?;
506 if self.requires_exact_integer_decode() {
507 return self.decode_native_region_components_via_full_decode(roi, decoder_context);
508 }
509 let (_x, _y, width, height) = roi;
510 let retained_image_bytes = self.retained_metadata_bytes()?;
511 let decoded_image =
512 self.decode_image(decoder_context, Some(roi), None, retained_image_bytes)?;
513 let DecodedImage {
514 decoded_components,
515 boxes: _,
516 } = decoded_image;
517 let component_owner_capacity = decoded_components.capacity();
518 self.pack_native_component_planes(
519 decoded_components,
520 component_owner_capacity,
521 (width, height),
522 retained_image_bytes,
523 )
524 }
525
526 #[doc(hidden)]
529 pub fn decode_region_components_with_ht_decoder<'ctx>(
530 &self,
531 decoder_context: &'ctx mut DecoderContext<'a>,
532 roi: (u32, u32, u32, u32),
533 ht_decoder: &mut dyn HtCodeBlockDecoder,
534 ) -> Result<DecodedComponents<'ctx>> {
535 validate_roi((self.width(), self.height()), roi)?;
536 self.validate_component_plane_precision()?;
537 let (_x, _y, width, height) = roi;
538 let decoded_image = self.decode_image(
539 decoder_context,
540 Some(roi),
541 Some(ht_decoder),
542 self.retained_metadata_bytes()?,
543 )?;
544 let DecodedImage {
545 decoded_components,
546 boxes: _,
547 } = decoded_image;
548 self.try_borrow_component_planes(
549 decoded_components.as_slice(),
550 decoded_components.capacity(),
551 (width, height),
552 )
553 }
554
555 pub fn decode_region(&self, roi: (u32, u32, u32, u32)) -> Result<Bitmap> {
561 self.decode_region_with_context(roi, &mut DecoderContext::default())
562 }
563
564 pub fn decode_region_with_context(
571 &self,
572 roi: (u32, u32, u32, u32),
573 decoder_context: &mut DecoderContext<'a>,
574 ) -> Result<Bitmap> {
575 validate_roi((self.width(), self.height()), roi)?;
576 (|| {
577 let retained_image_bytes = self.retained_metadata_bytes()?;
578 let mut decoded_image =
579 self.decode_image(decoder_context, Some(roi), None, retained_image_bytes)?;
580 let component_owner_capacity = decoded_image.decoded_components.capacity();
581 let (_x, _y, width, height) = roi;
582 let data_len = checked_decode_byte_len3(
583 width as usize,
584 height as usize,
585 decoded_image.decoded_components.len(),
586 )?;
587 let mut budget = NativeOutputBudget::for_decoded_channels(
588 retained_image_bytes,
589 decoded_image.decoded_components,
590 component_owner_capacity,
591 )?;
592 budget.include_elements::<u8>(data_len)?;
593 budget.include_color_space_clone(&self.color_space)?;
594
595 let color_space = try_clone_color_space(&self.color_space)?;
596 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
597 let mut data = Vec::new();
598 try_resize_decode_elements(&mut data, data_len, 0_u8)?;
599 budget.include_capacity_overage::<u8>(data_len, data.capacity())?;
600 interleave_and_convert_region(
601 &mut decoded_image,
602 width as usize,
603 (0, 0, width, height),
604 &mut data,
605 );
606 let bitmap = Bitmap {
607 color_space,
608 data,
609 has_alpha: self.has_alpha,
610 width,
611 height,
612 original_bit_depth: self.original_bit_depth(),
613 };
614 NativeOutputBudget::validate_bitmap_pack(
615 retained_image_bytes,
616 decoded_image.decoded_components,
617 component_owner_capacity,
618 &bitmap,
619 )?;
620 Ok(bitmap)
621 })()
622 }
623
624 pub fn decode_into(
638 &self,
639 buf: &mut [u8],
640 decoder_context: &mut DecoderContext<'a>,
641 ) -> Result<()> {
642 let mut decoded_image =
643 self.decode_image(decoder_context, None, None, self.retained_metadata_bytes()?)?;
644 validate_interleaved_output_buffer(&decoded_image, buf)?;
645 interleave_and_convert(&mut decoded_image, buf)?;
646
647 Ok(())
648 }
649
650 fn decode_image<'ctx>(
651 &self,
652 decoder_context: &'ctx mut DecoderContext<'a>,
653 output_region: Option<(u32, u32, u32, u32)>,
654 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
655 retained_baseline_bytes: usize,
656 ) -> Result<DecodedImage<'ctx, '_>> {
657 let settings = &self.settings;
658 let mut ht_decoder = ht_decoder;
659 decoder_context.set_output_region(output_region);
660 let decode_result = j2c::decode(
661 self.codestream,
662 &self.header,
663 retained_baseline_bytes,
664 decoder_context,
665 &mut ht_decoder,
666 );
667 decoder_context.set_output_region(None);
668 decode_result?;
669 let mut decoded_image = DecodedImage {
670 decoded_components: &mut decoder_context.tile_decode_context.channel_data,
671 boxes: &self.boxes,
672 };
673
674 if settings.resolve_palette_indices {
675 let components = core::mem::take(decoded_image.decoded_components);
676 *decoded_image.decoded_components =
677 resolve_palette_indices(components, decoded_image.boxes, retained_baseline_bytes)?;
678 }
679
680 if let Some(cdef) = &decoded_image.boxes.channel_definition {
681 validate_and_reorder_channels(
682 cdef,
683 decoded_image.decoded_components,
684 retained_baseline_bytes,
685 )?;
686 }
687
688 let bit_depth = decoded_image
689 .decoded_components
690 .first()
691 .ok_or(DecodingError::CodeBlockDecodeFailure)?
692 .bit_depth;
693 convert_color_space(&mut decoded_image, bit_depth)?;
694 Ok(decoded_image)
695 }
696}