/src/image/src/imageops/affine.rs
Line | Count | Source |
1 | | //! Functions for performing affine transformations. |
2 | | |
3 | | use crate::error::{ImageError, ParameterError, ParameterErrorKind}; |
4 | | use crate::traits::Pixel; |
5 | | use crate::{GenericImage, GenericImageView, ImageBuffer}; |
6 | | |
7 | | /// Rotate an image 90 degrees clockwise. |
8 | 0 | pub fn rotate90<I: GenericImageView>( |
9 | 0 | image: &I, |
10 | 0 | ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>> |
11 | 0 | where |
12 | 0 | I::Pixel: 'static, |
13 | | { |
14 | 0 | let (width, height) = image.dimensions(); |
15 | 0 | let mut out = image.buffer_with_dimensions(height, width); |
16 | 0 | let _ = rotate90_in(image, &mut out); |
17 | 0 | out |
18 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate90::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
19 | | |
20 | | /// Rotate an image 180 degrees clockwise. |
21 | 0 | pub fn rotate180<I: GenericImageView>( |
22 | 0 | image: &I, |
23 | 0 | ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>> |
24 | 0 | where |
25 | 0 | I::Pixel: 'static, |
26 | | { |
27 | 0 | let (width, height) = image.dimensions(); |
28 | 0 | let mut out = image.buffer_with_dimensions(width, height); |
29 | 0 | let _ = rotate180_in(image, &mut out); |
30 | 0 | out |
31 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
32 | | |
33 | | /// Rotate an image 270 degrees clockwise. |
34 | 0 | pub fn rotate270<I: GenericImageView>( |
35 | 0 | image: &I, |
36 | 0 | ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>> |
37 | 0 | where |
38 | 0 | I::Pixel: 'static, |
39 | | { |
40 | 0 | let (width, height) = image.dimensions(); |
41 | 0 | let mut out = image.buffer_with_dimensions(height, width); |
42 | 0 | let _ = rotate270_in(image, &mut out); |
43 | 0 | out |
44 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate270::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
45 | | |
46 | | /// Rotate an image 90 degrees clockwise and put the result into the destination [`ImageBuffer`]. |
47 | 0 | pub fn rotate90_in<I, Container>( |
48 | 0 | image: &I, |
49 | 0 | destination: &mut ImageBuffer<I::Pixel, Container>, |
50 | 0 | ) -> crate::ImageResult<()> |
51 | 0 | where |
52 | 0 | I: GenericImageView, |
53 | 0 | I::Pixel: 'static, |
54 | 0 | Container: std::ops::DerefMut<Target = [<I::Pixel as Pixel>::Subpixel]>, |
55 | | { |
56 | 0 | let ((w0, h0), (w1, h1)) = (image.dimensions(), destination.dimensions()); |
57 | 0 | if w0 != h1 || h0 != w1 { |
58 | 0 | return Err(ImageError::Parameter(ParameterError::from_kind( |
59 | 0 | ParameterErrorKind::DimensionMismatch, |
60 | 0 | ))); |
61 | 0 | } |
62 | | |
63 | 0 | for y in 0..h0 { |
64 | 0 | for x in 0..w0 { |
65 | 0 | let p = image.get_pixel(x, y); |
66 | 0 | destination.put_pixel(h0 - y - 1, x, p); |
67 | 0 | } |
68 | | } |
69 | 0 | Ok(()) |
70 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate90_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> |
71 | | |
72 | | /// Rotate an image 180 degrees clockwise and put the result into the destination [`ImageBuffer`]. |
73 | 0 | pub fn rotate180_in<I, Container>( |
74 | 0 | image: &I, |
75 | 0 | destination: &mut ImageBuffer<I::Pixel, Container>, |
76 | 0 | ) -> crate::ImageResult<()> |
77 | 0 | where |
78 | 0 | I: GenericImageView, |
79 | 0 | I::Pixel: 'static, |
80 | 0 | Container: std::ops::DerefMut<Target = [<I::Pixel as Pixel>::Subpixel]>, |
81 | | { |
82 | 0 | let ((w0, h0), (w1, h1)) = (image.dimensions(), destination.dimensions()); |
83 | 0 | if w0 != w1 || h0 != h1 { |
84 | 0 | return Err(ImageError::Parameter(ParameterError::from_kind( |
85 | 0 | ParameterErrorKind::DimensionMismatch, |
86 | 0 | ))); |
87 | 0 | } |
88 | | |
89 | 0 | for y in 0..h0 { |
90 | 0 | for x in 0..w0 { |
91 | 0 | let p = image.get_pixel(x, y); |
92 | 0 | destination.put_pixel(w0 - x - 1, h0 - y - 1, p); |
93 | 0 | } |
94 | | } |
95 | 0 | Ok(()) |
96 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate180_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> |
97 | | |
98 | | /// Rotate an image 270 degrees clockwise and put the result into the destination [`ImageBuffer`]. |
99 | 0 | pub fn rotate270_in<I, Container>( |
100 | 0 | image: &I, |
101 | 0 | destination: &mut ImageBuffer<I::Pixel, Container>, |
102 | 0 | ) -> crate::ImageResult<()> |
103 | 0 | where |
104 | 0 | I: GenericImageView, |
105 | 0 | I::Pixel: 'static, |
106 | 0 | Container: std::ops::DerefMut<Target = [<I::Pixel as Pixel>::Subpixel]>, |
107 | | { |
108 | 0 | let ((w0, h0), (w1, h1)) = (image.dimensions(), destination.dimensions()); |
109 | 0 | if w0 != h1 || h0 != w1 { |
110 | 0 | return Err(ImageError::Parameter(ParameterError::from_kind( |
111 | 0 | ParameterErrorKind::DimensionMismatch, |
112 | 0 | ))); |
113 | 0 | } |
114 | | |
115 | 0 | for y in 0..h0 { |
116 | 0 | for x in 0..w0 { |
117 | 0 | let p = image.get_pixel(x, y); |
118 | 0 | destination.put_pixel(y, w0 - x - 1, p); |
119 | 0 | } |
120 | | } |
121 | 0 | Ok(()) |
122 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::rotate270_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> |
123 | | |
124 | | /// Flip an image horizontally |
125 | 0 | pub fn flip_horizontal<I: GenericImageView>( |
126 | 0 | image: &I, |
127 | 0 | ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>> |
128 | 0 | where |
129 | 0 | I::Pixel: 'static, |
130 | | { |
131 | 0 | let mut out = image.buffer_like(); |
132 | 0 | let _ = flip_horizontal_in(image, &mut out); |
133 | 0 | out |
134 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
135 | | |
136 | | /// Flip an image vertically |
137 | 0 | pub fn flip_vertical<I: GenericImageView>( |
138 | 0 | image: &I, |
139 | 0 | ) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>> |
140 | 0 | where |
141 | 0 | I::Pixel: 'static, |
142 | | { |
143 | 0 | let mut out = image.buffer_like(); |
144 | 0 | let _ = flip_vertical_in(image, &mut out); |
145 | 0 | out |
146 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
147 | | |
148 | | /// Flip an image horizontally and put the result into the destination [`ImageBuffer`]. |
149 | 0 | pub fn flip_horizontal_in<I, Container>( |
150 | 0 | image: &I, |
151 | 0 | destination: &mut ImageBuffer<I::Pixel, Container>, |
152 | 0 | ) -> crate::ImageResult<()> |
153 | 0 | where |
154 | 0 | I: GenericImageView, |
155 | 0 | I::Pixel: 'static, |
156 | 0 | Container: std::ops::DerefMut<Target = [<I::Pixel as Pixel>::Subpixel]>, |
157 | | { |
158 | 0 | let ((w0, h0), (w1, h1)) = (image.dimensions(), destination.dimensions()); |
159 | 0 | if w0 != w1 || h0 != h1 { |
160 | 0 | return Err(ImageError::Parameter(ParameterError::from_kind( |
161 | 0 | ParameterErrorKind::DimensionMismatch, |
162 | 0 | ))); |
163 | 0 | } |
164 | | |
165 | 0 | for y in 0..h0 { |
166 | 0 | for x in 0..w0 { |
167 | 0 | let p = image.get_pixel(x, y); |
168 | 0 | destination.put_pixel(w0 - x - 1, y, p); |
169 | 0 | } |
170 | | } |
171 | 0 | Ok(()) |
172 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> |
173 | | |
174 | | /// Flip an image vertically and put the result into the destination [`ImageBuffer`]. |
175 | 0 | pub fn flip_vertical_in<I, Container>( |
176 | 0 | image: &I, |
177 | 0 | destination: &mut ImageBuffer<I::Pixel, Container>, |
178 | 0 | ) -> crate::ImageResult<()> |
179 | 0 | where |
180 | 0 | I: GenericImageView, |
181 | 0 | I::Pixel: 'static, |
182 | 0 | Container: std::ops::DerefMut<Target = [<I::Pixel as Pixel>::Subpixel]>, |
183 | | { |
184 | 0 | let ((w0, h0), (w1, h1)) = (image.dimensions(), destination.dimensions()); |
185 | 0 | if w0 != w1 || h0 != h1 { |
186 | 0 | return Err(ImageError::Parameter(ParameterError::from_kind( |
187 | 0 | ParameterErrorKind::DimensionMismatch, |
188 | 0 | ))); |
189 | 0 | } |
190 | | |
191 | 0 | for y in 0..h0 { |
192 | 0 | for x in 0..w0 { |
193 | 0 | let p = image.get_pixel(x, y); |
194 | 0 | destination.put_pixel(x, h0 - 1 - y, p); |
195 | 0 | } |
196 | | } |
197 | 0 | Ok(()) |
198 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>, alloc::vec::Vec<f32>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>, alloc::vec::Vec<u8>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>, alloc::vec::Vec<u16>> |
199 | | |
200 | | /// Rotate an image 180 degrees clockwise in place. |
201 | 0 | pub fn rotate180_in_place<I: GenericImage>(image: &mut I) { |
202 | 0 | let (width, height) = image.dimensions(); |
203 | | |
204 | 0 | for y in 0..height / 2 { |
205 | 0 | for x in 0..width { |
206 | 0 | let p = image.get_pixel(x, y); |
207 | 0 |
|
208 | 0 | let x2 = width - x - 1; |
209 | 0 | let y2 = height - y - 1; |
210 | 0 |
|
211 | 0 | let p2 = image.get_pixel(x2, y2); |
212 | 0 | image.put_pixel(x, y, p2); |
213 | 0 | image.put_pixel(x2, y2, p); |
214 | 0 | } |
215 | | } |
216 | | |
217 | 0 | if height % 2 != 0 { |
218 | 0 | let middle = height / 2; |
219 | | |
220 | 0 | for x in 0..width / 2 { |
221 | 0 | let p = image.get_pixel(x, middle); |
222 | 0 | let x2 = width - x - 1; |
223 | 0 |
|
224 | 0 | let p2 = image.get_pixel(x2, middle); |
225 | 0 | image.put_pixel(x, middle, p2); |
226 | 0 | image.put_pixel(x2, middle, p); |
227 | 0 | } |
228 | 0 | } |
229 | 0 | } Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::rotate180_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
230 | | |
231 | | /// Flip an image horizontally in place. |
232 | 0 | pub fn flip_horizontal_in_place<I: GenericImage>(image: &mut I) { |
233 | 0 | let (width, height) = image.dimensions(); |
234 | | |
235 | 0 | for y in 0..height { |
236 | 0 | for x in 0..width / 2 { |
237 | 0 | let x2 = width - x - 1; |
238 | 0 | let p2 = image.get_pixel(x2, y); |
239 | 0 | let p = image.get_pixel(x, y); |
240 | 0 | image.put_pixel(x2, y, p); |
241 | 0 | image.put_pixel(x, y, p2); |
242 | 0 | } |
243 | | } |
244 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_horizontal_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
245 | | |
246 | | /// Flip an image vertically in place. |
247 | 0 | pub fn flip_vertical_in_place<I: GenericImage>(image: &mut I) { |
248 | 0 | let (width, height) = image.dimensions(); |
249 | | |
250 | 0 | for y in 0..height / 2 { |
251 | 0 | for x in 0..width { |
252 | 0 | let y2 = height - y - 1; |
253 | 0 | let p2 = image.get_pixel(x, y2); |
254 | 0 | let p = image.get_pixel(x, y); |
255 | 0 | image.put_pixel(x, y2, p); |
256 | 0 | image.put_pixel(x, y, p2); |
257 | 0 | } |
258 | | } |
259 | 0 | } Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgb<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Luma<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<f32>, alloc::vec::Vec<f32>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::Rgba<u16>, alloc::vec::Vec<u16>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u8>, alloc::vec::Vec<u8>>> Unexecuted instantiation: image::imageops::affine::flip_vertical_in_place::<image::images::buffer::ImageBuffer<image::color::LumaA<u16>, alloc::vec::Vec<u16>>> |
260 | | |
261 | | #[cfg(test)] |
262 | | mod test { |
263 | | use super::{ |
264 | | flip_horizontal, flip_horizontal_in_place, flip_vertical, flip_vertical_in_place, |
265 | | rotate180, rotate180_in_place, rotate270, rotate90, |
266 | | }; |
267 | | |
268 | | use crate::traits::Pixel; |
269 | | use crate::{GenericImage, GrayImage, ImageBuffer}; |
270 | | |
271 | | macro_rules! assert_pixels_eq { |
272 | | ($actual:expr, $expected:expr) => {{ |
273 | | let actual_dim = $actual.dimensions(); |
274 | | let expected_dim = $expected.dimensions(); |
275 | | |
276 | | if actual_dim != expected_dim { |
277 | | panic!( |
278 | | "dimensions do not match. \ |
279 | | actual: {:?}, expected: {:?}", |
280 | | actual_dim, expected_dim |
281 | | ) |
282 | | } |
283 | | |
284 | | let diffs = pixel_diffs($actual, $expected); |
285 | | |
286 | | if !diffs.is_empty() { |
287 | | let mut err = "".to_string(); |
288 | | |
289 | | let diff_messages = diffs |
290 | | .iter() |
291 | | .take(5) |
292 | | .map(|d| format!("\nactual: {:?}, expected {:?} ", d.0, d.1)) |
293 | | .collect::<Vec<_>>() |
294 | | .join(""); |
295 | | |
296 | | err.push_str(&diff_messages); |
297 | | panic!("pixels do not match. {:?}", err) |
298 | | } |
299 | | }}; |
300 | | } |
301 | | |
302 | | #[test] |
303 | | fn test_rotate90() { |
304 | | let image: GrayImage = |
305 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
306 | | |
307 | | let expected: GrayImage = |
308 | | ImageBuffer::from_raw(2, 3, vec![10u8, 0u8, 11u8, 1u8, 12u8, 2u8]).unwrap(); |
309 | | |
310 | | assert_pixels_eq!(&rotate90(&image), &expected); |
311 | | } |
312 | | |
313 | | #[test] |
314 | | fn test_rotate180() { |
315 | | let image: GrayImage = |
316 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
317 | | |
318 | | let expected: GrayImage = |
319 | | ImageBuffer::from_raw(3, 2, vec![12u8, 11u8, 10u8, 2u8, 1u8, 0u8]).unwrap(); |
320 | | |
321 | | assert_pixels_eq!(&rotate180(&image), &expected); |
322 | | } |
323 | | |
324 | | #[test] |
325 | | fn test_rotate270() { |
326 | | let image: GrayImage = |
327 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
328 | | |
329 | | let expected: GrayImage = |
330 | | ImageBuffer::from_raw(2, 3, vec![2u8, 12u8, 1u8, 11u8, 0u8, 10u8]).unwrap(); |
331 | | |
332 | | assert_pixels_eq!(&rotate270(&image), &expected); |
333 | | } |
334 | | |
335 | | #[test] |
336 | | fn test_rotate180_in_place() { |
337 | | let mut image: GrayImage = |
338 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
339 | | |
340 | | let expected: GrayImage = |
341 | | ImageBuffer::from_raw(3, 2, vec![12u8, 11u8, 10u8, 2u8, 1u8, 0u8]).unwrap(); |
342 | | |
343 | | rotate180_in_place(&mut image); |
344 | | |
345 | | assert_pixels_eq!(&image, &expected); |
346 | | } |
347 | | |
348 | | #[test] |
349 | | fn test_flip_horizontal() { |
350 | | let image: GrayImage = |
351 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
352 | | |
353 | | let expected: GrayImage = |
354 | | ImageBuffer::from_raw(3, 2, vec![2u8, 1u8, 0u8, 12u8, 11u8, 10u8]).unwrap(); |
355 | | |
356 | | assert_pixels_eq!(&flip_horizontal(&image), &expected); |
357 | | } |
358 | | |
359 | | #[test] |
360 | | fn test_flip_vertical() { |
361 | | let image: GrayImage = |
362 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
363 | | |
364 | | let expected: GrayImage = |
365 | | ImageBuffer::from_raw(3, 2, vec![10u8, 11u8, 12u8, 0u8, 1u8, 2u8]).unwrap(); |
366 | | |
367 | | assert_pixels_eq!(&flip_vertical(&image), &expected); |
368 | | } |
369 | | |
370 | | #[test] |
371 | | fn test_flip_horizontal_in_place() { |
372 | | let mut image: GrayImage = |
373 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
374 | | |
375 | | let expected: GrayImage = |
376 | | ImageBuffer::from_raw(3, 2, vec![2u8, 1u8, 0u8, 12u8, 11u8, 10u8]).unwrap(); |
377 | | |
378 | | flip_horizontal_in_place(&mut image); |
379 | | |
380 | | assert_pixels_eq!(&image, &expected); |
381 | | } |
382 | | |
383 | | #[test] |
384 | | fn test_flip_vertical_in_place() { |
385 | | let mut image: GrayImage = |
386 | | ImageBuffer::from_raw(3, 2, vec![0u8, 1u8, 2u8, 10u8, 11u8, 12u8]).unwrap(); |
387 | | |
388 | | let expected: GrayImage = |
389 | | ImageBuffer::from_raw(3, 2, vec![10u8, 11u8, 12u8, 0u8, 1u8, 2u8]).unwrap(); |
390 | | |
391 | | flip_vertical_in_place(&mut image); |
392 | | |
393 | | assert_pixels_eq!(&image, &expected); |
394 | | } |
395 | | |
396 | | #[allow(clippy::type_complexity)] |
397 | | fn pixel_diffs<I, J, P>(left: &I, right: &J) -> Vec<((u32, u32, P), (u32, u32, P))> |
398 | | where |
399 | | I: GenericImage<Pixel = P>, |
400 | | J: GenericImage<Pixel = P>, |
401 | | P: Pixel + Eq, |
402 | | { |
403 | | left.pixels() |
404 | | .zip(right.pixels()) |
405 | | .filter(|&(p, q)| p != q) |
406 | | .collect::<Vec<_>>() |
407 | | } |
408 | | } |