image_builder/
picture.rs

1use image::imageops::FilterType;
2use image::DynamicImage;
3
4/// External images.
5///
6/// The Picture structure is responsible for defining and adjusting external images that will be
7/// included in the image being built. It allows for cropping, resizing, and positioning to compose
8/// the final image.
9///
10/// **⚠️ It's important to note that if there is both cropping and resizing on the same
11/// image, the library will always perform cropping first, and then resizing.** ⚠️
12/// ## Example
13/// ```
14/// # use image_builder::FilterType;
15/// # let file_bytes:Vec<u8> = Vec::new();
16/// use image_builder::Picture;
17/// use image::DynamicImage;
18///
19/// Picture::new(file_bytes)
20///     .resize(100, 100, FilterType::Triangle) // Resizing is specified here, but the library will first perform the cropping below, and then this resizing.
21///     .crop(50, 50, 200, 200);
22/// ```
23/// In the example above, an image of 300x300 pixels was imported, a square of 200x200 pixels was
24/// cropped, and then this cropped portion was resized by half, resulting in an image of 100x100 pixels.
25#[derive(Clone)]
26pub struct Picture {
27    img: image::DynamicImage,
28    crop: Option<(u32, u32, u32, u32)>,
29    resize: Option<(u32, u32, FilterType)>,
30    position: (u32, u32),
31}
32impl Picture {
33    /// This method instantiates an external image using the file path of the image
34    /// and positions it at the point (0,0) of the image being built.
35    /// ## Example
36    /// ```
37    /// use image::DynamicImage;
38    /// use image_builder::Picture;
39    ///
40    /// Picture::new(image);
41    /// ```
42    pub fn new(img: DynamicImage) -> Picture {
43        Picture {
44            img,
45            resize: None,
46            crop: None,
47            position: (0, 0),
48        }
49    }
50
51    /// This method allows resizing an image by specifying the desired new height, width and [`FilterType`].
52    /// ## Example
53    /// ```rust
54    /// # use image_builder::FilterType;
55    /// use image_builder::Picture;
56    ///
57    /// Picture::new("/home/user/logo.png")
58    ///     .resize(200, 100, FilterType::Triangle);
59    /// ```
60    pub fn resize(&mut self, width: u32, height: u32, filter: FilterType) -> Self {
61        self.resize = Some((width, height, filter));
62        self.clone()
63    }
64
65    /// Use this method to crop an imported image by providing the starting point of the crop (x, y),
66    /// as well as the desired height and width to be cropped.
67    /// ## Example
68    /// ```
69    /// use image_builder::Picture;
70    ///
71    /// Picture::new("/home/user/logo.png")
72    ///     .crop(50, 50, 200, 200);
73    /// ```
74    pub fn crop(&mut self, x: u32, y: u32, width: u32, height: u32) -> Self {
75        self.crop = Some((x, y, width, height));
76        self.clone()
77    }
78
79    /// This method allows you to adjust the position of the imported image within the image being constructed.
80    /// ## Example
81    /// ```
82    /// use image_builder::Picture;
83    ///
84    /// Picture::new("/home/user/logo.png")
85    ///     .position(100, 100);
86    /// ```
87    pub fn position(&mut self, x: u32, y: u32) -> Self {
88        self.position = (x, y);
89        self.clone()
90    }
91}
92
93#[derive(Clone)]
94pub struct CropValues {
95    pub x: u32,
96    pub y: u32,
97    pub width: u32,
98    pub height: u32,
99}
100
101#[derive(Clone)]
102pub struct ResizeValues {
103    pub nwidth: u32,
104    pub nheight: u32,
105    pub filter: FilterType,
106}
107
108#[derive(Clone)]
109pub struct PictureValues<'a> {
110    pub img: &'a DynamicImage,
111    pub x: i64,
112    pub y: i64,
113    pub crop: Option<CropValues>,
114    pub resize: Option<ResizeValues>,
115}
116pub fn extract(picture: &Picture) -> PictureValues {
117    PictureValues {
118        img: &picture.img,
119        x: picture.position.0 as i64,
120        y: picture.position.1 as i64,
121        crop: match picture.crop {
122            None => None,
123            Some(values) => Some(CropValues {
124                x: values.0,
125                y: values.1,
126                width: values.2,
127                height: values.3,
128            }),
129        },
130        resize: match picture.resize {
131            None => None,
132            Some(values) => Some(ResizeValues {
133                nwidth: values.0,
134                nheight: values.1,
135                filter: values.2,
136            }),
137        },
138    }
139}