jpeg2k_sandboxed/
lib.rs

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/// DecodeParameters
33#[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/// DecodeImageRequest
60#[derive(Debug, Default, Clone, Serialize, Deserialize)]
61pub struct DecodeImageRequest {
62  pub params: Option<DecodeParameters>,
63  pub only_header: bool,
64  /// JP2/J2K compressed image data.
65  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/// Image pixel format.
101#[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/// Image pixel data.
131#[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/// Component info.
161#[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/// J2KImage
171#[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/// Try to convert a loaded Jpeg 2000 image into a `J2KImage`.
186#[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/// Try to convert a loaded Jpeg 2000 image into a `image::DynamicImage`.
243#[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}