1use alloc::vec::Vec;
6
7use crate::color::{
8 ComponentPlane, ComponentRowSink, DecodedComponents, DecodedNativeComponents, RawBitmap,
9};
10use crate::error::{bail, DecodingError, Result, ValidationError};
11use crate::j2c::{self, ComponentData, DecoderContext, Reversible53CoefficientImage};
12use crate::jp2::DecodedImage;
13use crate::CpuDecodeParallelism;
14use crate::{
15 checked_decode_byte_len3, checked_decode_byte_len4, checked_decode_sample_count,
16 native_bytes_per_sample, try_reserve_decode_elements, validate_roi, HtCodeBlockDecoder,
17};
18
19use super::native::{try_clone_color_space, NativeOutputBudget};
20use super::Image;
21
22impl<'a> Image<'a> {
23 pub fn decode_wavelets_with_context(
30 &self,
31 context: &mut DecoderContext<'a>,
32 selection: &crate::WaveletSelection,
33 ) -> Result<crate::WaveletImage> {
34 self.with_packet_cache_retry(|| {
35 j2c::wavelets::extract(
36 self.codestream,
37 &self.header,
38 self.retained_metadata_bytes()?,
39 context,
40 selection,
41 )
42 })
43 }
44
45 pub fn decode_native(&self) -> Result<RawBitmap> {
58 let mut decoder_context = DecoderContext::default();
59 self.decode_native_with_context(&mut decoder_context)
60 }
61
62 #[doc(hidden)]
73 pub fn decode_native_with_retained_capacity(
74 &self,
75 retained_capacity: usize,
76 ) -> Result<RawBitmap> {
77 let retained_baseline_bytes = super::allocation::combine_retained_bytes(
78 retained_capacity,
79 self.retained_header_metadata_bytes()?,
80 )?;
81 let mut decoder_context = DecoderContext::default();
82 self.decode_native_with_context_and_retained_baseline(
83 &mut decoder_context,
84 retained_baseline_bytes,
85 )
86 }
87
88 #[doc(hidden)]
94 pub fn decode_reversible_53_coefficients(&self) -> Result<Reversible53CoefficientImage> {
95 let mut decoder_context = DecoderContext::default();
96 self.decode_reversible_53_coefficients_with_context(&mut decoder_context)
97 }
98
99 #[doc(hidden)]
102 pub fn decode_reversible_53_coefficients_with_context(
103 &self,
104 decoder_context: &mut DecoderContext<'a>,
105 ) -> Result<Reversible53CoefficientImage> {
106 self.with_packet_cache_retry(|| {
107 j2c::recode::extract_reversible_53_coefficients(
108 self.codestream,
109 &self.header,
110 self.retained_metadata_bytes()?,
111 decoder_context,
112 )
113 })
114 }
115
116 pub fn decode_native_region(&self, roi: (u32, u32, u32, u32)) -> Result<RawBitmap> {
122 self.decode_native_region_with_context(roi, &mut DecoderContext::default())
123 }
124
125 pub fn decode_native_region_components(
132 &self,
133 roi: (u32, u32, u32, u32),
134 ) -> Result<DecodedNativeComponents> {
135 self.decode_native_region_components_with_context(roi, &mut DecoderContext::default())
136 }
137
138 pub fn decode_native_with_context(
145 &self,
146 decoder_context: &mut DecoderContext<'a>,
147 ) -> Result<RawBitmap> {
148 let retained_baseline_bytes = self.retained_header_metadata_bytes()?;
149 self.decode_native_with_context_and_retained_baseline(
150 decoder_context,
151 retained_baseline_bytes,
152 )
153 }
154
155 pub(crate) fn decode_native_with_context_and_retained_baseline(
156 &self,
157 decoder_context: &mut DecoderContext<'a>,
158 retained_baseline_bytes: usize,
159 ) -> Result<RawBitmap> {
160 self.with_packet_cache_retry(|| {
161 let bit_depth = self.uniform_header_bit_depth()?;
162 let parallel = decoder_context.cpu_decode_parallelism() == CpuDecodeParallelism::Auto;
163 let retained_baseline_bytes =
164 self.run_decode(decoder_context, None, None, true, retained_baseline_bytes)?;
165
166 let components = &decoder_context.tile_decode_context.channel_data;
167 let component_owner_capacity = components.capacity();
168 let num_components =
169 u16::try_from(components.len()).map_err(|_| ValidationError::TooManyChannels)?;
170 let width = self.width();
171 let height = self.height();
172 let pixel_count = checked_decode_sample_count(width, height)?;
173 let bytes_per_sample = native_bytes_per_sample(bit_depth)?;
174 let capacity = checked_decode_byte_len3(
175 pixel_count,
176 usize::from(num_components),
177 bytes_per_sample,
178 )?;
179 let mut budget = NativeOutputBudget::for_decoded_channels(
180 retained_baseline_bytes,
181 components,
182 component_owner_capacity,
183 )?;
184 budget.include_bit_capacity(components.len())?;
185 budget.include_elements::<u8>(capacity)?;
186 let component_signed = Self::try_component_signedness(components)?;
187 budget.include_bit_capacity_overage(components.len(), component_signed.capacity())?;
188 let signed = component_signed.iter().all(|signed| *signed);
189 let mut data = Vec::new();
190 try_reserve_decode_elements(&mut data, capacity)?;
191 budget.include_capacity_overage::<u8>(capacity, data.capacity())?;
192 if let [component] = components.as_slice() {
193 Self::extend_component_native_sample_bytes(
194 &mut data,
195 component,
196 0..pixel_count,
197 bit_depth,
198 parallel,
199 );
200 } else {
201 for index in 0..pixel_count {
202 for component in components {
203 Self::push_component_native_sample_bytes(
204 &mut data, component, index, bit_depth,
205 );
206 }
207 }
208 }
209 if data.len() != capacity {
210 bail!(DecodingError::CodeBlockDecodeFailure);
211 }
212 let bitmap = RawBitmap {
213 data,
214 width,
215 height,
216 bit_depth,
217 signed,
218 component_signed,
219 num_components,
220 bytes_per_sample: u8::try_from(bytes_per_sample)
221 .map_err(|_| ValidationError::ImageTooLarge)?,
222 };
223 NativeOutputBudget::validate_raw_pack(
224 retained_baseline_bytes,
225 components,
226 component_owner_capacity,
227 &bitmap,
228 )?;
229 Ok(bitmap)
230 })
231 }
232
233 pub fn decode_native_region_with_context(
240 &self,
241 roi: (u32, u32, u32, u32),
242 decoder_context: &mut DecoderContext<'a>,
243 ) -> Result<RawBitmap> {
244 self.with_packet_cache_retry(|| {
245 validate_roi((self.width(), self.height()), roi)?;
246 if self.requires_exact_integer_decode() {
247 return self.decode_native_region_via_full_decode(roi, decoder_context);
248 }
249 let bit_depth = self.uniform_header_bit_depth()?;
250 let retained_image_bytes = self.retained_header_metadata_bytes()?;
251 let parallel = decoder_context.cpu_decode_parallelism() == CpuDecodeParallelism::Auto;
252 let retained_image_bytes =
253 self.run_decode(decoder_context, Some(roi), None, true, retained_image_bytes)?;
254
255 let components = &decoder_context.tile_decode_context.channel_data;
256 let component_owner_capacity = components.capacity();
257 let num_components =
258 u16::try_from(components.len()).map_err(|_| ValidationError::TooManyChannels)?;
259 let bytes_per_sample = native_bytes_per_sample(bit_depth)?;
260 let (_x, _y, width, height) = roi;
261 let capacity = checked_decode_byte_len4(
262 width as usize,
263 height as usize,
264 usize::from(num_components),
265 bytes_per_sample,
266 )?;
267 let mut budget = NativeOutputBudget::for_decoded_channels(
268 retained_image_bytes,
269 components,
270 component_owner_capacity,
271 )?;
272 budget.include_bit_capacity(components.len())?;
273 budget.include_elements::<u8>(capacity)?;
274 let mut data = Vec::new();
275 let component_signed = Self::try_component_signedness(components)?;
276 budget.include_bit_capacity_overage(components.len(), component_signed.capacity())?;
277 try_reserve_decode_elements(&mut data, capacity)?;
278 budget.include_capacity_overage::<u8>(capacity, data.capacity())?;
279 let signed = component_signed.iter().all(|signed| *signed);
280
281 let pixel_count = width as usize * height as usize;
282 if let [component] = components.as_slice() {
283 Self::extend_component_native_sample_bytes(
284 &mut data,
285 component,
286 0..pixel_count,
287 bit_depth,
288 parallel,
289 );
290 } else {
291 for index in 0..pixel_count {
292 for component in components {
293 Self::push_component_native_sample_bytes(
294 &mut data, component, index, bit_depth,
295 );
296 }
297 }
298 }
299 if data.len() != capacity {
300 bail!(DecodingError::CodeBlockDecodeFailure);
301 }
302
303 let bitmap = RawBitmap {
304 data,
305 width,
306 height,
307 bit_depth,
308 signed,
309 component_signed,
310 num_components,
311 bytes_per_sample: u8::try_from(bytes_per_sample)
312 .map_err(|_| ValidationError::ImageTooLarge)?,
313 };
314 NativeOutputBudget::validate_raw_pack(
315 retained_image_bytes,
316 components,
317 component_owner_capacity,
318 &bitmap,
319 )?;
320 Ok(bitmap)
321 })
322 }
323
324 fn try_component_signedness(components: &[ComponentData]) -> Result<Vec<bool>> {
325 let mut signedness = Vec::new();
326 try_reserve_decode_elements(&mut signedness, components.len())?;
327 signedness.extend(components.iter().map(|component| component.signed));
328 Ok(signedness)
329 }
330
331 pub(super) fn component_plane_sampling_at(&self, component_idx: usize) -> (u8, u8) {
332 if self.settings.resolve_palette_indices && self.boxes.palette.is_some() {
333 return (1, 1);
334 }
335 self.header
336 .component_infos
337 .get(component_idx)
338 .map_or((1, 1), |component| {
339 (
340 component.size_info.horizontal_resolution,
341 component.size_info.vertical_resolution,
342 )
343 })
344 }
345
346 pub(super) fn try_borrow_component_planes_with_retained_baseline<'ctx>(
347 &self,
348 components: &'ctx [ComponentData],
349 component_owner_capacity: usize,
350 dimensions: (u32, u32),
351 retained_image_bytes: usize,
352 ) -> Result<DecodedComponents<'ctx>> {
353 self.with_packet_cache_retry(|| {
354 #[cfg(feature = "std")]
355 let retained_image_bytes = super::allocation::combine_retained_bytes(
356 retained_image_bytes,
357 self.packet_cache.retained_bytes(),
358 )?;
359 let mut budget = NativeOutputBudget::for_decoded_channels(
360 retained_image_bytes,
361 components,
362 component_owner_capacity,
363 )?;
364 budget.include_elements::<ComponentPlane<'_>>(components.len())?;
365 budget.include_color_space_clone(&self.color_space)?;
366 let color_space = try_clone_color_space(&self.color_space)?;
367 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
368 let mut planes = Vec::new();
369 try_reserve_decode_elements(&mut planes, components.len())?;
370 budget.include_capacity_overage::<ComponentPlane<'_>>(
371 components.len(),
372 planes.capacity(),
373 )?;
374 for (component_idx, component) in components.iter().enumerate() {
375 planes.push(ComponentPlane {
376 samples: component.container.truncated(),
377 dimensions,
378 bit_depth: component.bit_depth,
379 signed: component.signed,
380 sampling: self.component_plane_sampling_at(component_idx),
381 });
382 }
383
384 let mut packed = DecodedComponents {
385 dimensions,
386 color_space,
387 has_alpha: self.has_alpha,
388 planes,
389 live_bytes: 0,
390 };
391 packed.live_bytes = NativeOutputBudget::validate_borrowed_pack(
392 retained_image_bytes,
393 components,
394 component_owner_capacity,
395 &packed,
396 )?;
397 Ok(packed)
398 })
399 }
400
401 fn uniform_header_bit_depth(&self) -> Result<u8> {
402 let Some(first) = self.header.component_infos.first() else {
403 bail!(DecodingError::CodeBlockDecodeFailure);
404 };
405 if self
406 .header
407 .component_infos
408 .iter()
409 .any(|component| component.size_info.precision != first.size_info.precision)
410 {
411 bail!(DecodingError::UnsupportedFeature(
412 "decode_native requires uniform component bit depths; use decode_components for mixed-depth images"
413 ));
414 }
415 if first.size_info.precision > 38 {
416 bail!(DecodingError::UnsupportedFeature(
417 "decode_native supports JPEG 2000 Part 1 component precision up to 38 bits"
418 ));
419 }
420 Ok(first.size_info.precision)
421 }
422
423 pub(super) fn validate_component_plane_precision(&self) -> Result<()> {
424 if self
425 .header
426 .component_infos
427 .iter()
428 .any(|component| component.size_info.precision > 24)
429 {
430 bail!(DecodingError::UnsupportedFeature(
431 "decode_components currently supports component planes up to 24 bits per component"
432 ));
433 }
434 Ok(())
435 }
436}
437
438impl<'a> Image<'a> {
448 #[doc(hidden)]
455 pub fn decode_components_for_integer_output_with_context<'ctx>(
456 &self,
457 decoder_context: &'ctx mut DecoderContext<'a>,
458 ) -> Result<DecodedComponents<'ctx>> {
459 self.decode_borrowed_component_planes(decoder_context, None, None, true)
460 }
461
462 #[doc(hidden)]
469 pub fn decode_region_components_for_integer_output_with_context<'ctx>(
470 &self,
471 roi: (u32, u32, u32, u32),
472 decoder_context: &'ctx mut DecoderContext<'a>,
473 ) -> Result<DecodedComponents<'ctx>> {
474 self.decode_borrowed_component_planes(decoder_context, Some(roi), None, true)
475 }
476
477 #[doc(hidden)]
489 pub fn decode_region_rows_for_integer_output_with_context(
490 &self,
491 roi: (u32, u32, u32, u32),
492 decoder_context: &mut DecoderContext<'a>,
493 sink: &mut dyn ComponentRowSink,
494 ) -> Result<()> {
495 validate_roi((self.width(), self.height()), roi)?;
496 self.validate_component_plane_precision()?;
497 let charged_image_bytes = self.run_decode_rows(
498 decoder_context,
499 Some(roi),
500 None,
501 true,
502 self.retained_header_metadata_bytes()?,
503 Some(&mut *sink),
504 )?;
505 if decoder_context.tile_decode_context.stream_rows {
506 return Ok(());
507 }
508 let DecodedImage {
509 decoded_components,
510 boxes: _,
511 } = self.finish_decoded_image(
512 &mut decoder_context.tile_decode_context.channel_data,
513 charged_image_bytes,
514 )?;
515 let components = self.try_borrow_component_planes_with_retained_baseline(
516 decoded_components.as_slice(),
517 decoded_components.capacity(),
518 (roi.2, roi.3),
519 self.retained_header_metadata_bytes()?,
520 )?;
521 sink.write_rows(0, 0, &components.planes);
522 Ok(())
523 }
524
525 #[doc(hidden)]
532 pub fn decode_components_for_integer_output_with_ht_decoder<'ctx>(
533 &self,
534 decoder_context: &'ctx mut DecoderContext<'a>,
535 ht_decoder: &mut dyn HtCodeBlockDecoder,
536 ) -> Result<DecodedComponents<'ctx>> {
537 self.decode_borrowed_component_planes(decoder_context, None, Some(ht_decoder), true)
538 }
539
540 #[doc(hidden)]
547 pub fn decode_region_components_for_integer_output_with_ht_decoder<'ctx>(
548 &self,
549 decoder_context: &'ctx mut DecoderContext<'a>,
550 roi: (u32, u32, u32, u32),
551 ht_decoder: &mut dyn HtCodeBlockDecoder,
552 ) -> Result<DecodedComponents<'ctx>> {
553 self.decode_borrowed_component_planes(decoder_context, Some(roi), Some(ht_decoder), true)
554 }
555
556 pub(super) fn decode_borrowed_component_planes<'ctx>(
557 &self,
558 decoder_context: &'ctx mut DecoderContext<'a>,
559 roi: Option<(u32, u32, u32, u32)>,
560 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
561 round_irreversible_output: bool,
562 ) -> Result<DecodedComponents<'ctx>> {
563 let dimensions = match roi {
564 Some(roi) => {
565 validate_roi((self.width(), self.height()), roi)?;
566 (roi.2, roi.3)
567 }
568 None => (self.width(), self.height()),
569 };
570 self.validate_component_plane_precision()?;
571 let (decoded_image, _charged_image_bytes) = self.decode_image(
572 decoder_context,
573 roi,
574 ht_decoder,
575 round_irreversible_output,
576 self.retained_header_metadata_bytes()?,
577 )?;
578 let DecodedImage {
579 decoded_components,
580 boxes: _,
581 } = decoded_image;
582 self.try_borrow_component_planes_with_retained_baseline(
583 decoded_components.as_slice(),
584 decoded_components.capacity(),
585 dimensions,
586 self.retained_header_metadata_bytes()?,
587 )
588 }
589}