Coverage Report

Created: 2026-01-17 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}