1use image::{ImageBuffer, Rgb, DynamicImage, Rgba, Frame};
2
3use crate::utils::{image::{RgbImageRepr, RgbPixelRepr, get_dimensions_of_matrix, RgbaImageRepr, RgbaPixelRepr}, numops::map_to_2d};
4
5pub trait Effect<T> {
10 fn affect(&self, item: T) -> T;
12}
13
14pub trait Affectable<T, F: Effect<T>> {
22
23 fn apply(self, effect: &F) -> Self;
25}
26
27impl<T, F> Affectable<T, F> for T where F: Effect<T> {
28 fn apply(self, effect: &F) -> Self {
29 effect.affect(self)
30 }
31}
32
33impl<F> Effect<RgbaPixelRepr> for F where F: Effect<RgbPixelRepr> {
34 fn affect(&self, item: RgbaPixelRepr) -> RgbaPixelRepr {
35 let [r, g, b, a] = item;
36 let [r, g, b] = self.affect([r, g, b]);
37 [r, g, b, a]
38 }
39}
40
41impl<F> Effect<RgbImageRepr> for F where F: Effect<RgbPixelRepr> {
42 fn affect(&self, mut item: RgbImageRepr) -> RgbImageRepr {
43 for row in item.iter_mut() {
44 for pixel in row.iter_mut() {
45 *pixel = self.affect(*pixel);
46 }
47 }
48 item
49 }
50}
51
52impl<F> Effect<RgbaImageRepr> for F where F: Effect<RgbImageRepr> {
53 fn affect(&self, item: RgbaImageRepr) -> RgbaImageRepr {
54 let (xs, ys) = get_dimensions_of_matrix(&item);
55
56 let mut rgb_repr = vec![vec![[0_u8; 3]; xs]; ys];
57 let mut output = vec![vec![[0_u8; 4]; xs]; ys];
58
59 for y in 0..ys {
60 for x in 0..xs {
61 let [r, g, b, _] = item[y][x];
62 rgb_repr[y][x] = [r, g, b];
63 }
64 }
65
66 let rgb_repr = self.affect(rgb_repr);
67
68 for y in 0..ys {
69 for x in 0..xs {
70 let [r, g, b] = rgb_repr[y][x];
71 output[y][x] = [r, g, b, item[y][x][3]];
72 }
73 }
74
75 output
76 }
77}
78
79impl<F> Effect<ImageBuffer<Rgb<u8>, Vec<u8>>> for F where F: Effect<RgbImageRepr> {
80 fn affect(&self, item: ImageBuffer<Rgb<u8>, Vec<u8>>) -> ImageBuffer<Rgb<u8>, Vec<u8>> {
81 let (xs, ys) = item.dimensions();
82 let (xs, ys) = (xs as usize, ys as usize);
83
84 let mut img_matrix = vec![vec![[0_u8; 3]; xs]; ys];
85
86 for (i, pixel) in item.pixels().into_iter().enumerate() {
87 let (x, y) = map_to_2d(i, xs);
88 img_matrix[y][x] = pixel.0;
89 }
90
91 img_matrix = self.affect(img_matrix);
92
93 let (xdim, ydim) = get_dimensions_of_matrix(&img_matrix);
94
95 ImageBuffer::from_fn(xdim as u32, ydim as u32, |x, y| {
96 image::Rgb(img_matrix[y as usize][x as usize])
97 })
98 }
99}
100
101impl<F> Effect<ImageBuffer<Rgba<u8>, Vec<u8>>> for F where F: Effect<RgbaImageRepr> {
102 fn affect(&self, item: ImageBuffer<Rgba<u8>, Vec<u8>>) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
103 let (xs, ys) = item.dimensions();
104 let (xs, ys) = (xs as usize, ys as usize);
105
106 let mut img_matrix = vec![vec![[0_u8; 4]; xs]; ys];
107
108 for (i, pixel) in item.pixels().into_iter().enumerate() {
109 let (x, y) = map_to_2d(i, xs);
110 img_matrix[y][x] = pixel.0;
111 }
112
113 img_matrix = self.affect(img_matrix);
114
115 let (xdim, ydim) = get_dimensions_of_matrix(&img_matrix);
116
117 ImageBuffer::from_fn(xdim as u32, ydim as u32, |x, y| {
118 image::Rgba(img_matrix[y as usize][x as usize])
119 })
120 }
121}
122
123impl<F> Effect<DynamicImage> for F where F:
124 Effect<ImageBuffer<Rgb<u8>, Vec<u8>>>
125 + Effect<ImageBuffer<Rgba<u8>, Vec<u8>>>
126{
127 fn affect(&self, item: DynamicImage) -> DynamicImage {
128 match item {
129 DynamicImage::ImageRgb8(img) => {
130 DynamicImage::from(self.affect(img))
131 },
132 DynamicImage::ImageRgba8(img) => {
133 DynamicImage::from(self.affect(img))
134 },
135 _ => {
136 DynamicImage::ImageRgb8(self.affect(item.into_rgb8()))
137 }
138 }
139 }
140}
141
142impl<F> Effect<Frame> for F where F: Effect<ImageBuffer<Rgba<u8>, Vec<u8>>> {
143 fn affect(&self, item: Frame) -> Frame {
144 let left = item.left();
145 let top = item.top();
146 let delay = item.delay();
147
148 let new_buf = self.affect(item.into_buffer());
149 Frame::from_parts(new_buf, left, top, delay)
150 }
151}