1#[cfg(not(feature = "wasi-decoder"))]
2mod sandbox;
3#[cfg(not(feature = "wasi-decoder"))]
4pub use sandbox::*;
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
9pub struct DecodeArea {
10 pub start_x: u32,
11 pub start_y: u32,
12 pub end_x: u32,
13 pub end_y: u32,
14}
15
16impl std::str::FromStr for DecodeArea {
17 type Err = anyhow::Error;
18 fn from_str(s: &str) -> Result<Self, Self::Err> {
19 let dim = s
20 .splitn(4, ":")
21 .map(|v| v.parse::<u32>())
22 .collect::<Result<Vec<u32>, _>>()?;
23 Ok(Self {
24 start_x: dim.get(0).copied().unwrap_or(0),
25 start_y: dim.get(1).copied().unwrap_or(0),
26 end_x: dim.get(2).copied().unwrap_or(0),
27 end_y: dim.get(3).copied().unwrap_or(0),
28 })
29 }
30}
31
32#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
34pub struct DecodeParameters {
35 pub reduce: u32,
36 pub strict: bool,
37 pub layers: u32,
38 pub area: Option<DecodeArea>,
39}
40
41#[cfg(feature = "jpeg2k")]
42impl From<DecodeArea> for jpeg2k::DecodeArea {
43 fn from(p: DecodeArea) -> Self {
44 Self::new(p.start_x, p.start_y, p.end_x, p.end_y)
45 }
46}
47
48#[cfg(feature = "jpeg2k")]
49impl From<DecodeParameters> for jpeg2k::DecodeParameters {
50 fn from(p: DecodeParameters) -> Self {
51 Self::new()
52 .reduce(p.reduce)
53 .strict(p.strict)
54 .layers(p.layers)
55 .decode_area(p.area.map(|a| a.into()))
56 }
57}
58
59#[derive(Debug, Default, Clone, Serialize, Deserialize)]
61pub struct DecodeImageRequest {
62 pub params: Option<DecodeParameters>,
63 pub only_header: bool,
64 pub data: Vec<u8>,
66}
67
68impl DecodeImageRequest {
69 pub fn new(data: Vec<u8>) -> Self {
70 Self {
71 data,
72 only_header: false,
73 params: None,
74 }
75 }
76
77 pub fn new_with(data: Vec<u8>, params: DecodeParameters) -> Self {
78 Self {
79 data,
80 only_header: false,
81 params: Some(params),
82 }
83 }
84
85 pub fn only_header(&self) -> Self {
86 let mut header_request = self.clone();
87 header_request.only_header = true;
88 header_request
89 }
90
91 #[cfg(feature = "jpeg2k")]
92 pub fn params(&self) -> jpeg2k::DecodeParameters {
93 match self.params {
94 Some(params) => params.into(),
95 None => jpeg2k::DecodeParameters::new(),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
102pub enum ImageFormat {
103 L8,
104 La8,
105 Rgb8,
106 Rgba8,
107 L16,
108 La16,
109 Rgb16,
110 Rgba16,
111}
112
113#[cfg(feature = "jpeg2k")]
114impl From<jpeg2k::ImageFormat> for ImageFormat {
115 fn from(format: jpeg2k::ImageFormat) -> Self {
116 use jpeg2k::ImageFormat::*;
117 match format {
118 L8 => Self::L8,
119 La8 => Self::La8,
120 Rgb8 => Self::Rgb8,
121 Rgba8 => Self::Rgba8,
122 L16 => Self::L16,
123 La16 => Self::La16,
124 Rgb16 => Self::Rgb16,
125 Rgba16 => Self::Rgba16,
126 }
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub enum ImagePixelData {
133 L8(Vec<u8>),
134 La8(Vec<u8>),
135 Rgb8(Vec<u8>),
136 Rgba8(Vec<u8>),
137 L16(Vec<u16>),
138 La16(Vec<u16>),
139 Rgb16(Vec<u16>),
140 Rgba16(Vec<u16>),
141}
142
143#[cfg(feature = "jpeg2k")]
144impl From<jpeg2k::ImagePixelData> for ImagePixelData {
145 fn from(format: jpeg2k::ImagePixelData) -> Self {
146 use jpeg2k::ImagePixelData::*;
147 match format {
148 L8(d) => Self::L8(d),
149 La8(d) => Self::La8(d),
150 Rgb8(d) => Self::Rgb8(d),
151 Rgba8(d) => Self::Rgba8(d),
152 L16(d) => Self::L16(d),
153 La16(d) => Self::La16(d),
154 Rgb16(d) => Self::Rgb16(d),
155 Rgba16(d) => Self::Rgba16(d),
156 }
157 }
158}
159
160#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
162pub struct ComponentInfo {
163 pub width: u32,
164 pub height: u32,
165 pub precision: u32,
166 pub is_alpha: bool,
167 pub is_signed: bool,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct J2KImage {
173 pub width: u32,
174 pub height: u32,
175 pub format: ImageFormat,
176 pub data: ImagePixelData,
177 pub orig_width: u32,
178 pub orig_height: u32,
179 pub x_offset: u32,
180 pub y_offset: u32,
181 pub num_components: u32,
182 pub components: Vec<ComponentInfo>,
183}
184
185#[cfg(feature = "jpeg2k")]
187impl TryFrom<jpeg2k::Image> for J2KImage {
188 type Error = jpeg2k::error::Error;
189
190 fn try_from(img: jpeg2k::Image) -> Result<Self, Self::Error> {
191 let comps = img.components();
192 let num_components = img.num_components();
193 let mut has_alpha = false;
194 let components = comps
195 .iter()
196 .map(|c| {
197 let is_alpha = c.is_alpha();
198 if is_alpha {
199 has_alpha = true;
200 }
201 ComponentInfo {
202 width: c.width(),
203 height: c.height(),
204 precision: c.precision(),
205 is_alpha: c.is_alpha(),
206 is_signed: c.is_signed(),
207 }
208 })
209 .collect::<Vec<_>>();
210 let (format, data) = match img.get_pixels(None) {
211 Ok(d) => (d.format.into(), d.data.into()),
212 Err(_) => {
213 let format = match (num_components, has_alpha) {
214 (1, _) => ImageFormat::L8,
215 (2, true) => ImageFormat::La8,
216 (3, false) => ImageFormat::Rgb8,
217 (4, _) => ImageFormat::Rgba8,
218 _ => {
219 return Err(jpeg2k::error::Error::UnsupportedComponentsError(
220 num_components,
221 ));
222 }
223 };
224 (format, ImagePixelData::L8(vec![]))
225 }
226 };
227 Ok(J2KImage {
228 width: img.width(),
229 height: img.height(),
230 format,
231 data,
232 orig_width: img.orig_width(),
233 orig_height: img.orig_height(),
234 x_offset: img.x_offset(),
235 y_offset: img.y_offset(),
236 num_components,
237 components,
238 })
239 }
240}
241
242#[cfg(feature = "image")]
244impl TryFrom<J2KImage> for ::image::DynamicImage {
245 type Error = ();
246
247 fn try_from(img: J2KImage) -> Result<::image::DynamicImage, Self::Error> {
248 use image::*;
249 let J2KImage {
250 width,
251 height,
252 data,
253 ..
254 } = img;
255 match data {
256 crate::ImagePixelData::L8(data) => {
257 let gray = GrayImage::from_vec(width, height, data)
258 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
259
260 Ok(DynamicImage::ImageLuma8(gray))
261 }
262 crate::ImagePixelData::La8(data) => {
263 let gray = GrayAlphaImage::from_vec(width, height, data)
264 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
265
266 Ok(DynamicImage::ImageLumaA8(gray))
267 }
268 crate::ImagePixelData::Rgb8(data) => {
269 let rgb = RgbImage::from_vec(width, height, data)
270 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
271
272 Ok(DynamicImage::ImageRgb8(rgb))
273 }
274 crate::ImagePixelData::Rgba8(data) => {
275 let rgba = RgbaImage::from_vec(width, height, data)
276 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
277
278 Ok(DynamicImage::ImageRgba8(rgba))
279 }
280 crate::ImagePixelData::L16(data) => {
281 let gray = ImageBuffer::from_vec(width, height, data)
282 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
283
284 Ok(DynamicImage::ImageLuma16(gray))
285 }
286 crate::ImagePixelData::La16(data) => {
287 let gray = ImageBuffer::from_vec(width, height, data)
288 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
289
290 Ok(DynamicImage::ImageLumaA16(gray))
291 }
292 crate::ImagePixelData::Rgb16(data) => {
293 let rgb = ImageBuffer::from_vec(width, height, data)
294 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
295
296 Ok(DynamicImage::ImageRgb16(rgb))
297 }
298 crate::ImagePixelData::Rgba16(data) => {
299 let rgba = ImageBuffer::from_vec(width, height, data)
300 .expect("Shouldn't happen. Report to jpeg2k if you see this.");
301
302 Ok(DynamicImage::ImageRgba16(rgba))
303 }
304 }
305 }
306}