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
48pub 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}