1use alloc::vec::Vec;
6
7use crate::color::{ComponentPlane, DecodedComponents, DecodedNativeComponents, RawBitmap};
8use crate::error::{bail, DecodingError, Result, ValidationError};
9use crate::j2c::{self, ComponentData, DecoderContext, Reversible53CoefficientImage};
10use crate::jp2::DecodedImage;
11use crate::{
12 checked_decode_byte_len3, checked_decode_byte_len4, checked_decode_sample_count,
13 native_bytes_per_sample, try_reserve_decode_elements, validate_roi, HtCodeBlockDecoder,
14};
15
16use super::native::{try_clone_color_space, NativeOutputBudget};
17use super::Image;
18
19impl<'a> Image<'a> {
20 pub fn decode_native(&self) -> Result<RawBitmap> {
33 let mut decoder_context = DecoderContext::default();
34 self.decode_native_with_context(&mut decoder_context)
35 }
36
37 #[doc(hidden)]
48 pub fn decode_native_with_retained_capacity(
49 &self,
50 retained_capacity: usize,
51 ) -> Result<RawBitmap> {
52 let retained_baseline_bytes = super::allocation::combine_retained_bytes(
53 retained_capacity,
54 self.retained_metadata_bytes()?,
55 )?;
56 let mut decoder_context = DecoderContext::default();
57 self.decode_native_with_context_and_retained_baseline(
58 &mut decoder_context,
59 retained_baseline_bytes,
60 )
61 }
62
63 #[doc(hidden)]
69 pub fn decode_reversible_53_coefficients(&self) -> Result<Reversible53CoefficientImage> {
70 let mut decoder_context = DecoderContext::default();
71 self.decode_reversible_53_coefficients_with_context(&mut decoder_context)
72 }
73
74 #[doc(hidden)]
77 pub fn decode_reversible_53_coefficients_with_context(
78 &self,
79 decoder_context: &mut DecoderContext<'a>,
80 ) -> Result<Reversible53CoefficientImage> {
81 j2c::recode::extract_reversible_53_coefficients(
82 self.codestream,
83 &self.header,
84 self.retained_metadata_bytes()?,
85 decoder_context,
86 )
87 }
88
89 pub fn decode_native_region(&self, roi: (u32, u32, u32, u32)) -> Result<RawBitmap> {
95 self.decode_native_region_with_context(roi, &mut DecoderContext::default())
96 }
97
98 pub fn decode_native_region_components(
105 &self,
106 roi: (u32, u32, u32, u32),
107 ) -> Result<DecodedNativeComponents> {
108 self.decode_native_region_components_with_context(roi, &mut DecoderContext::default())
109 }
110
111 pub fn decode_native_with_context(
118 &self,
119 decoder_context: &mut DecoderContext<'a>,
120 ) -> Result<RawBitmap> {
121 let retained_baseline_bytes = self.retained_metadata_bytes()?;
122 self.decode_native_with_context_and_retained_baseline(
123 decoder_context,
124 retained_baseline_bytes,
125 )
126 }
127
128 pub(crate) fn decode_native_with_context_and_retained_baseline(
129 &self,
130 decoder_context: &mut DecoderContext<'a>,
131 retained_baseline_bytes: usize,
132 ) -> Result<RawBitmap> {
133 let bit_depth = self.uniform_header_bit_depth()?;
134 let mut ht_decoder = None;
135 decoder_context.set_output_region(None);
136 decoder_context.set_round_irreversible_output(true);
137 let decode_result = j2c::decode(
138 self.codestream,
139 &self.header,
140 retained_baseline_bytes,
141 decoder_context,
142 &mut ht_decoder,
143 );
144 decoder_context.set_output_region(None);
145 decoder_context.set_round_irreversible_output(false);
146 decode_result?;
147
148 let components = &decoder_context.tile_decode_context.channel_data;
149 let component_owner_capacity = components.capacity();
150 let num_components =
151 u16::try_from(components.len()).map_err(|_| ValidationError::TooManyChannels)?;
152 let width = self.width();
153 let height = self.height();
154 let pixel_count = checked_decode_sample_count(width, height)?;
155 let bytes_per_sample = native_bytes_per_sample(bit_depth)?;
156 let capacity =
157 checked_decode_byte_len3(pixel_count, usize::from(num_components), bytes_per_sample)?;
158 let mut budget = NativeOutputBudget::for_decoded_channels(
159 retained_baseline_bytes,
160 components,
161 component_owner_capacity,
162 )?;
163 budget.include_bit_capacity(components.len())?;
164 budget.include_elements::<u8>(capacity)?;
165 let component_signed = Self::try_component_signedness(components)?;
166 budget.include_bit_capacity_overage(components.len(), component_signed.capacity())?;
167 let signed = component_signed.iter().all(|signed| *signed);
168 let mut data = Vec::new();
169 try_reserve_decode_elements(&mut data, capacity)?;
170 budget.include_capacity_overage::<u8>(capacity, data.capacity())?;
171 for index in 0..pixel_count {
172 for component in components {
173 Self::push_component_native_sample_bytes(&mut data, component, index, bit_depth);
174 }
175 }
176 if data.len() != capacity {
177 bail!(DecodingError::CodeBlockDecodeFailure);
178 }
179 let bitmap = RawBitmap {
180 data,
181 width,
182 height,
183 bit_depth,
184 signed,
185 component_signed,
186 num_components,
187 bytes_per_sample: u8::try_from(bytes_per_sample)
188 .map_err(|_| ValidationError::ImageTooLarge)?,
189 };
190 NativeOutputBudget::validate_raw_pack(
191 retained_baseline_bytes,
192 components,
193 component_owner_capacity,
194 &bitmap,
195 )?;
196 Ok(bitmap)
197 }
198
199 pub fn decode_native_region_with_context(
206 &self,
207 roi: (u32, u32, u32, u32),
208 decoder_context: &mut DecoderContext<'a>,
209 ) -> Result<RawBitmap> {
210 validate_roi((self.width(), self.height()), roi)?;
211 if self.requires_exact_integer_decode() {
212 return self.decode_native_region_via_full_decode(roi, decoder_context);
213 }
214 let bit_depth = self.uniform_header_bit_depth()?;
215 let retained_image_bytes = self.retained_metadata_bytes()?;
216 let mut ht_decoder = None;
217 decoder_context.set_output_region(Some(roi));
218 decoder_context.set_round_irreversible_output(true);
219 let decode_result = j2c::decode(
220 self.codestream,
221 &self.header,
222 retained_image_bytes,
223 decoder_context,
224 &mut ht_decoder,
225 );
226 decoder_context.set_output_region(None);
227 decoder_context.set_round_irreversible_output(false);
228 decode_result?;
229
230 let components = &decoder_context.tile_decode_context.channel_data;
231 let component_owner_capacity = components.capacity();
232 let num_components =
233 u16::try_from(components.len()).map_err(|_| ValidationError::TooManyChannels)?;
234 let bytes_per_sample = native_bytes_per_sample(bit_depth)?;
235 let (_x, _y, width, height) = roi;
236 let capacity = checked_decode_byte_len4(
237 width as usize,
238 height as usize,
239 usize::from(num_components),
240 bytes_per_sample,
241 )?;
242 let mut budget = NativeOutputBudget::for_decoded_channels(
243 retained_image_bytes,
244 components,
245 component_owner_capacity,
246 )?;
247 budget.include_bit_capacity(components.len())?;
248 budget.include_elements::<u8>(capacity)?;
249 let mut data = Vec::new();
250 let component_signed = Self::try_component_signedness(components)?;
251 budget.include_bit_capacity_overage(components.len(), component_signed.capacity())?;
252 try_reserve_decode_elements(&mut data, capacity)?;
253 budget.include_capacity_overage::<u8>(capacity, data.capacity())?;
254 let signed = component_signed.iter().all(|signed| *signed);
255
256 for row in 0..height as usize {
257 for col in 0..width as usize {
258 let index = row * width as usize + col;
259 for component in components {
260 Self::push_component_native_sample_bytes(
261 &mut data, component, index, bit_depth,
262 );
263 }
264 }
265 }
266 if data.len() != capacity {
267 bail!(DecodingError::CodeBlockDecodeFailure);
268 }
269
270 let bitmap = RawBitmap {
271 data,
272 width,
273 height,
274 bit_depth,
275 signed,
276 component_signed,
277 num_components,
278 bytes_per_sample: u8::try_from(bytes_per_sample)
279 .map_err(|_| ValidationError::ImageTooLarge)?,
280 };
281 NativeOutputBudget::validate_raw_pack(
282 retained_image_bytes,
283 components,
284 component_owner_capacity,
285 &bitmap,
286 )?;
287 Ok(bitmap)
288 }
289
290 fn try_component_signedness(components: &[ComponentData]) -> Result<Vec<bool>> {
291 let mut signedness = Vec::new();
292 try_reserve_decode_elements(&mut signedness, components.len())?;
293 signedness.extend(components.iter().map(|component| component.signed));
294 Ok(signedness)
295 }
296
297 pub(super) fn component_plane_sampling_at(&self, component_idx: usize) -> (u8, u8) {
298 if self.settings.resolve_palette_indices && self.boxes.palette.is_some() {
299 return (1, 1);
300 }
301 self.header
302 .component_infos
303 .get(component_idx)
304 .map_or((1, 1), |component| {
305 (
306 component.size_info.horizontal_resolution,
307 component.size_info.vertical_resolution,
308 )
309 })
310 }
311
312 pub(super) fn try_borrow_component_planes<'ctx>(
313 &self,
314 components: &'ctx [ComponentData],
315 component_owner_capacity: usize,
316 dimensions: (u32, u32),
317 ) -> Result<DecodedComponents<'ctx>> {
318 let retained_image_bytes = self.retained_metadata_bytes()?;
319 self.try_borrow_component_planes_with_retained_baseline(
320 components,
321 component_owner_capacity,
322 dimensions,
323 retained_image_bytes,
324 )
325 }
326
327 pub(super) fn try_borrow_component_planes_with_retained_baseline<'ctx>(
328 &self,
329 components: &'ctx [ComponentData],
330 component_owner_capacity: usize,
331 dimensions: (u32, u32),
332 retained_image_bytes: usize,
333 ) -> Result<DecodedComponents<'ctx>> {
334 let mut budget = NativeOutputBudget::for_decoded_channels(
335 retained_image_bytes,
336 components,
337 component_owner_capacity,
338 )?;
339 budget.include_elements::<ComponentPlane<'_>>(components.len())?;
340 budget.include_color_space_clone(&self.color_space)?;
341 let color_space = try_clone_color_space(&self.color_space)?;
342 budget.include_color_space_clone_overage(&self.color_space, &color_space)?;
343 let mut planes = Vec::new();
344 try_reserve_decode_elements(&mut planes, components.len())?;
345 budget
346 .include_capacity_overage::<ComponentPlane<'_>>(components.len(), planes.capacity())?;
347 for (component_idx, component) in components.iter().enumerate() {
348 planes.push(ComponentPlane {
349 samples: component.container.truncated(),
350 dimensions,
351 bit_depth: component.bit_depth,
352 signed: component.signed,
353 sampling: self.component_plane_sampling_at(component_idx),
354 });
355 }
356
357 let mut packed = DecodedComponents {
358 dimensions,
359 color_space,
360 has_alpha: self.has_alpha,
361 planes,
362 live_bytes: 0,
363 };
364 packed.live_bytes = NativeOutputBudget::validate_borrowed_pack(
365 retained_image_bytes,
366 components,
367 component_owner_capacity,
368 &packed,
369 )?;
370 Ok(packed)
371 }
372
373 fn uniform_header_bit_depth(&self) -> Result<u8> {
374 let Some(first) = self.header.component_infos.first() else {
375 bail!(DecodingError::CodeBlockDecodeFailure);
376 };
377 if self
378 .header
379 .component_infos
380 .iter()
381 .any(|component| component.size_info.precision != first.size_info.precision)
382 {
383 bail!(DecodingError::UnsupportedFeature(
384 "decode_native requires uniform component bit depths; use decode_components for mixed-depth images"
385 ));
386 }
387 if first.size_info.precision > 38 {
388 bail!(DecodingError::UnsupportedFeature(
389 "decode_native supports JPEG 2000 Part 1 component precision up to 38 bits"
390 ));
391 }
392 Ok(first.size_info.precision)
393 }
394
395 pub(super) fn validate_component_plane_precision(&self) -> Result<()> {
396 if self
397 .header
398 .component_infos
399 .iter()
400 .any(|component| component.size_info.precision > 24)
401 {
402 bail!(DecodingError::UnsupportedFeature(
403 "decode_components currently supports component planes up to 24 bits per component"
404 ));
405 }
406 Ok(())
407 }
408}
409
410impl<'a> Image<'a> {
420 #[doc(hidden)]
427 pub fn decode_components_for_integer_output_with_context<'ctx>(
428 &self,
429 decoder_context: &'ctx mut DecoderContext<'a>,
430 ) -> Result<DecodedComponents<'ctx>> {
431 self.decode_borrowed_component_planes(decoder_context, None, None, true)
432 }
433
434 #[doc(hidden)]
441 pub fn decode_region_components_for_integer_output_with_context<'ctx>(
442 &self,
443 roi: (u32, u32, u32, u32),
444 decoder_context: &'ctx mut DecoderContext<'a>,
445 ) -> Result<DecodedComponents<'ctx>> {
446 self.decode_borrowed_component_planes(decoder_context, Some(roi), None, true)
447 }
448
449 #[doc(hidden)]
456 pub fn decode_components_for_integer_output_with_ht_decoder<'ctx>(
457 &self,
458 decoder_context: &'ctx mut DecoderContext<'a>,
459 ht_decoder: &mut dyn HtCodeBlockDecoder,
460 ) -> Result<DecodedComponents<'ctx>> {
461 self.decode_borrowed_component_planes(decoder_context, None, Some(ht_decoder), true)
462 }
463
464 #[doc(hidden)]
471 pub fn decode_region_components_for_integer_output_with_ht_decoder<'ctx>(
472 &self,
473 decoder_context: &'ctx mut DecoderContext<'a>,
474 roi: (u32, u32, u32, u32),
475 ht_decoder: &mut dyn HtCodeBlockDecoder,
476 ) -> Result<DecodedComponents<'ctx>> {
477 self.decode_borrowed_component_planes(decoder_context, Some(roi), Some(ht_decoder), true)
478 }
479
480 pub(super) fn decode_borrowed_component_planes<'ctx>(
481 &self,
482 decoder_context: &'ctx mut DecoderContext<'a>,
483 roi: Option<(u32, u32, u32, u32)>,
484 ht_decoder: Option<&mut dyn HtCodeBlockDecoder>,
485 round_irreversible_output: bool,
486 ) -> Result<DecodedComponents<'ctx>> {
487 let dimensions = match roi {
488 Some(roi) => {
489 validate_roi((self.width(), self.height()), roi)?;
490 (roi.2, roi.3)
491 }
492 None => (self.width(), self.height()),
493 };
494 self.validate_component_plane_precision()?;
495 let decoded_image = self.decode_image(
496 decoder_context,
497 roi,
498 ht_decoder,
499 round_irreversible_output,
500 self.retained_metadata_bytes()?,
501 )?;
502 let DecodedImage {
503 decoded_components,
504 boxes: _,
505 } = decoded_image;
506 self.try_borrow_component_planes(
507 decoded_components.as_slice(),
508 decoded_components.capacity(),
509 dimensions,
510 )
511 }
512}