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