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