j2k_jpeg/decoder/routing/
owned_output.rs1use alloc::vec::Vec;
6
7use crate::allocation::checked_add_allocation_bytes;
8
9use super::super::{
10 additional_decode_scratch_bytes, allocate_output_buffer_with_live_budget,
11 checked_output_geometry, output_format_from_parts, scaled_dimensions, scaled_rect_covering,
12 DecodeOutcome, DecodeRequest, Decoder, JpegError, Rect, ScratchPool, DEFAULT_SCRATCH,
13};
14
15impl Decoder<'_> {
16 pub fn decode_request(
23 &self,
24 request: DecodeRequest,
25 ) -> Result<(Vec<u8>, DecodeOutcome), JpegError> {
26 self.decode_request_with_external_live(request, 0)
27 }
28
29 #[doc(hidden)]
39 pub fn decode_request_with_external_live(
40 &self,
41 request: DecodeRequest,
42 external_live_bytes: usize,
43 ) -> Result<(Vec<u8>, DecodeOutcome), JpegError> {
44 DEFAULT_SCRATCH.with(|pool| {
45 self.decode_request_with_scratch_and_external_live(
46 &mut pool.borrow_mut(),
47 request,
48 external_live_bytes,
49 )
50 })
51 }
52
53 #[doc(hidden)]
59 pub fn decode_request_with_scratch_and_external_live(
60 &self,
61 pool: &mut ScratchPool,
62 request: DecodeRequest,
63 external_live_bytes: usize,
64 ) -> Result<(Vec<u8>, DecodeOutcome), JpegError> {
65 let legacy = output_format_from_parts(self.info.sof_kind, request.fmt, request.scale)?;
66 let source_roi = request
67 .region
68 .unwrap_or_else(|| Rect::full(self.info.dimensions));
69 if !source_roi.is_within(self.info.dimensions) {
70 return Err(JpegError::RectOutOfBounds {
71 rect: source_roi,
72 width: self.info.dimensions.0,
73 height: self.info.dimensions.1,
74 });
75 }
76 let output_rect = if request.region.is_some() {
77 scaled_rect_covering(source_roi, legacy.downscale())?
78 } else {
79 let (width, height) = scaled_dimensions(self.info.dimensions, legacy.downscale());
80 Rect::full((width, height))
81 };
82 let (stride, len) =
83 checked_output_geometry(output_rect.w, output_rect.h, legacy.bytes_per_pixel())?;
84 let additional_scratch = additional_decode_scratch_bytes(
85 self.info.sof_kind,
86 self.info.dimensions,
87 legacy,
88 source_roi,
89 output_rect,
90 legacy.downscale(),
91 )?;
92 let planned_output_live = checked_add_allocation_bytes(external_live_bytes, len)?;
93 self.prepare_decode_workspace_with_additional(
94 pool,
95 planned_output_live,
96 additional_scratch,
97 )?;
98 let workspace_cap = self.decode_workspace_cap()?;
99 let mut allocation_live =
100 checked_add_allocation_bytes(external_live_bytes, pool.retained_bytes())?;
101 let mut out =
102 allocate_output_buffer_with_live_budget(len, &mut allocation_live, workspace_cap)?;
103 let decode_external_live =
104 checked_add_allocation_bytes(external_live_bytes, out.capacity())?;
105 let outcome = if let Some(roi) = request.region {
106 self.decode_region_into_output_format_with_scratch_and_external(
107 pool,
108 &mut out,
109 stride,
110 legacy,
111 roi,
112 decode_external_live,
113 )?
114 } else {
115 self.decode_into_output_format_with_scratch_and_external(
116 pool,
117 &mut out,
118 stride,
119 legacy,
120 decode_external_live,
121 )?
122 };
123 Ok((out, outcome))
124 }
125}