rust_faces/
imaging.rs

1use image::{flat::SampleLayout, GenericImageView, ImageBuffer, Pixel};
2use ndarray::{Array3, ShapeBuilder};
3
4pub fn make_border<I: GenericImageView>(
5    image: &I,
6    top: u32,
7    bottom: u32,
8    left: u32,
9    right: u32,
10    color: I::Pixel,
11) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
12where
13    I::Pixel: 'static,
14    <I::Pixel as Pixel>::Subpixel: 'static,
15{
16    let (width, height) = image.dimensions();
17
18    let mut new_image = ImageBuffer::new(width + left + right, height + top + bottom);
19
20    for (x, y, pixel) in new_image.enumerate_pixels_mut() {
21        if x < left || x >= width + left || y < top || y >= height + top {
22            *pixel = color;
23        } else {
24            *pixel = image.get_pixel(x - left, y - top);
25        }
26    }
27    new_image
28}
29
30pub trait ToRgb8 {
31    fn to_rgb8(&self) -> ImageBuffer<image::Rgb<u8>, Vec<u8>>;
32}
33
34impl ToRgb8 for Array3<u8> {
35    fn to_rgb8(&self) -> ImageBuffer<image::Rgb<u8>, Vec<u8>> {
36        let (height, width, _) = self.dim();
37        let mut image = ImageBuffer::new(width as u32, height as u32);
38        for (x, y, pixel) in image.enumerate_pixels_mut() {
39            let r = self[[y as usize, x as usize, 0]];
40            let g = self[[y as usize, x as usize, 1]];
41            let b = self[[y as usize, x as usize, 2]];
42            *pixel = image::Rgb([r, g, b]);
43        }
44        image
45    }
46}
47
48/// Uses this trait to convert an image to an ndarray::Array3.
49/// Note that conversion must keep HxWxC order.
50pub trait ToArray3 {
51    type Out;
52
53    fn into_array3(self) -> Self::Out;
54}
55
56impl<P> ToArray3 for ImageBuffer<P, Vec<P::Subpixel>>
57where
58    P: Pixel + 'static,
59{
60    type Out = Array3<P::Subpixel>;
61
62    fn into_array3(self) -> Self::Out {
63        let SampleLayout {
64            channels,
65            channel_stride,
66            height,
67            height_stride,
68            width,
69            width_stride,
70        } = self.sample_layout();
71        let shape = (height as usize, width as usize, channels as usize);
72        let strides = (height_stride, width_stride, channel_stride);
73        Array3::from_shape_vec(shape.strides(strides), self.into_raw()).unwrap()
74    }
75}