gistools/parsers/image/
decoder.rs

1use super::ImageData;
2use crate::parsers::Buffer;
3#[cfg(feature = "std")]
4use image::ImageReader;
5#[cfg(feature = "std")]
6use std::io::Cursor;
7
8/// Image Decoder Options
9#[derive(Debug, Default, Clone)]
10pub struct DecodeOptions {
11    /// The x position to start at
12    pub x: Option<u32>,
13    /// The y position to start at
14    pub y: Option<u32>,
15    /// The width to read in
16    pub width: Option<u32>,
17    /// The height to read in
18    pub height: Option<u32>,
19    /// The modulo to use. For example you may have a 514x514 image, but you want to use 512x512 [Default=1]
20    pub modulo: Option<u32>,
21}
22
23/// Decode any image
24///
25/// ## Parameters
26/// - `buffer`: the input buffer
27/// - `options`: the decode options
28///
29/// ## Returns
30/// the raw decoded buffer
31#[cfg(feature = "std")]
32pub fn image_decoder(
33    buffer: &Buffer,
34    options: Option<DecodeOptions>,
35) -> Result<ImageData, image::ImageError> {
36    use image::GenericImageView;
37
38    let img = ImageReader::new(Cursor::new(buffer.buf())).with_guessed_format()?.decode()?;
39
40    let (img_width, img_height) = img.dimensions();
41    let opts = options.unwrap_or_default();
42
43    let modulo = opts.modulo.unwrap_or(1);
44    let diff = img_width % modulo;
45
46    let (x, y, width, height) = if diff != 0 {
47        let shift = diff / 2;
48        (shift, shift, img_width - diff, img_width - diff)
49    } else {
50        (
51            opts.x.unwrap_or(0),
52            opts.y.unwrap_or(0),
53            opts.width.unwrap_or(img_width),
54            opts.height.unwrap_or(img_height),
55        )
56    };
57
58    let sub_image = img.view(x, y, width, height).to_image();
59
60    Ok(ImageData {
61        width: width as usize,
62        height: height as usize,
63        data: sub_image.into_raw().into(),
64    })
65}
66
67/// Image decoder
68///
69/// ## Parameters
70/// - `buffer`: the input buffer
71/// - `options`: user defined options
72///
73/// ## Returns
74/// the decoded buffer
75#[cfg(feature = "std")]
76pub fn image_decoder_buffer(buffer: &Buffer, options: Option<DecodeOptions>) -> Buffer {
77    image_decoder(buffer, options).unwrap().data
78}