yuvutils_rs/
mirroring.rs

1/*
2 * Copyright (c) Radzivon Bartoshyk, 1/2025. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1.  Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * 2.  Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * 3.  Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29use crate::geometry::map_ft_result;
30use crate::YuvError;
31use fast_transpose::{
32    flip_plane, flip_plane16, flip_plane16_with_alpha, flip_plane_with_alpha, flip_rgb, flip_rgb16,
33    flip_rgba, flip_rgba16, flop_plane, flop_plane16, flop_plane16_with_alpha,
34    flop_plane_with_alpha, flop_rgb, flop_rgb16, flop_rgba, flop_rgba16,
35};
36
37/// Declares mirroring mode: vertical or horizontal
38#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
39pub enum MirrorMode {
40    Vertical,
41    Horizontal,
42}
43
44/// Mirrors RGBA 8 bit image.
45///
46/// This mirrors any 4 channels image, channel order does not matter.
47///
48/// # Arguments
49///
50/// * `src`: Source image
51/// * `src_stride`: Source image stride
52/// * `dst`: Destination image
53/// * `dst_stride`: Destination image stride
54/// * `width`: Image width
55/// * `height`: Image Height
56/// * `mode`: Refer to [MirrorMode] for mode info
57///
58/// returns: Result<(), [YuvError]>
59///
60pub fn mirror_rgba(
61    src: &[u8],
62    src_stride: usize,
63    dst: &mut [u8],
64    dst_stride: usize,
65    width: usize,
66    height: usize,
67    mode: MirrorMode,
68) -> Result<(), YuvError> {
69    let rs = match mode {
70        MirrorMode::Vertical => flop_rgba(src, src_stride, dst, dst_stride, width, height),
71        MirrorMode::Horizontal => flip_rgba(src, src_stride, dst, dst_stride, width, height),
72    };
73    map_ft_result(rs)
74}
75
76/// Mirrors RGB 8 bit image.
77///
78/// This mirrors any 3 channels image, channel order does not matter.
79///
80/// # Arguments
81///
82/// * `src`: Source image
83/// * `src_stride`: Source image stride
84/// * `dst`: Destination image
85/// * `dst_stride`: Destination image stride
86/// * `width`: Image width
87/// * `height`: Image Height
88/// * `mode`: Refer to [MirrorMode] for mode info
89///
90/// returns: Result<(), [YuvError]>
91///
92pub fn mirror_rgb(
93    src: &[u8],
94    src_stride: usize,
95    dst: &mut [u8],
96    dst_stride: usize,
97    width: usize,
98    height: usize,
99    mode: MirrorMode,
100) -> Result<(), YuvError> {
101    let rs = match mode {
102        MirrorMode::Vertical => flop_rgb(src, src_stride, dst, dst_stride, width, height),
103        MirrorMode::Horizontal => flip_rgb(src, src_stride, dst, dst_stride, width, height),
104    };
105    map_ft_result(rs)
106}
107
108/// Mirrors CbCr 8 bit image.
109///
110/// This mirrors any 2 channels image, channel order does not matter.
111///
112/// # Arguments
113///
114/// * `src`: Source image
115/// * `src_stride`: Source image stride
116/// * `dst`: Destination image
117/// * `dst_stride`: Destination image stride
118/// * `width`: Image width
119/// * `height`: Image Height
120/// * `mode`: Refer to [MirrorMode] for mode info
121///
122/// returns: Result<(), [YuvError]>
123///
124pub fn mirror_cbcr(
125    src: &[u8],
126    src_stride: usize,
127    dst: &mut [u8],
128    dst_stride: usize,
129    width: usize,
130    height: usize,
131    mode: MirrorMode,
132) -> Result<(), YuvError> {
133    let rs = match mode {
134        MirrorMode::Vertical => {
135            flop_plane_with_alpha(src, src_stride, dst, dst_stride, width, height)
136        }
137        MirrorMode::Horizontal => {
138            flip_plane_with_alpha(src, src_stride, dst, dst_stride, width, height)
139        }
140    };
141    map_ft_result(rs)
142}
143
144/// Mirrors Plane 8 bit image.
145///
146/// This mirrors any planar channels image.
147///
148/// # Arguments
149///
150/// * `src`: Source image
151/// * `src_stride`: Source image stride
152/// * `dst`: Destination image
153/// * `dst_stride`: Destination image stride
154/// * `width`: Image width
155/// * `height`: Image Height
156/// * `mode`: Refer to [MirrorMode] for mode info
157///
158/// returns: Result<(), [YuvError]>
159///
160pub fn mirror_plane(
161    src: &[u8],
162    src_stride: usize,
163    dst: &mut [u8],
164    dst_stride: usize,
165    width: usize,
166    height: usize,
167    mode: MirrorMode,
168) -> Result<(), YuvError> {
169    let rs = match mode {
170        MirrorMode::Vertical => flop_plane(src, src_stride, dst, dst_stride, width, height),
171        MirrorMode::Horizontal => flip_plane(src, src_stride, dst, dst_stride, width, height),
172    };
173    map_ft_result(rs)
174}
175
176/// Mirrors RGBA 8+ bit image.
177///
178/// This mirrors any 4 channels image, channel order does not matter.
179///
180/// # Arguments
181///
182/// * `src`: Source image
183/// * `src_stride`: Source image stride
184/// * `dst`: Destination image
185/// * `dst_stride`: Destination image stride
186/// * `width`: Image width
187/// * `height`: Image Height
188/// * `mode`: Refer to [MirrorMode] for mode info
189///
190/// returns: Result<(), [YuvError]>
191///
192pub fn mirror_rgba16(
193    src: &[u16],
194    src_stride: usize,
195    dst: &mut [u16],
196    dst_stride: usize,
197    width: usize,
198    height: usize,
199    mode: MirrorMode,
200) -> Result<(), YuvError> {
201    let rs = match mode {
202        MirrorMode::Vertical => flop_rgba16(src, src_stride, dst, dst_stride, width, height),
203        MirrorMode::Horizontal => flip_rgba16(src, src_stride, dst, dst_stride, width, height),
204    };
205    map_ft_result(rs)
206}
207
208/// Mirrors RGB 8+ bit image.
209///
210/// This mirrors any 3 channels image, channel order does not matter.
211///
212/// # Arguments
213///
214/// * `src`: Source image
215/// * `src_stride`: Source image stride
216/// * `dst`: Destination image
217/// * `dst_stride`: Destination image stride
218/// * `width`: Image width
219/// * `height`: Image Height
220/// * `mode`: Refer to [MirrorMode] for mode info
221///
222/// returns: Result<(), [YuvError]>
223///
224pub fn mirror_rgb16(
225    src: &[u16],
226    src_stride: usize,
227    dst: &mut [u16],
228    dst_stride: usize,
229    width: usize,
230    height: usize,
231    mode: MirrorMode,
232) -> Result<(), YuvError> {
233    let rs = match mode {
234        MirrorMode::Vertical => flop_rgb16(src, src_stride, dst, dst_stride, width, height),
235        MirrorMode::Horizontal => flip_rgb16(src, src_stride, dst, dst_stride, width, height),
236    };
237    map_ft_result(rs)
238}
239
240/// Mirrors CbCr 8+ bit image.
241///
242/// This mirrors any 2 channels image, channel order does not matter.
243///
244/// # Arguments
245///
246/// * `src`: Source image
247/// * `src_stride`: Source image stride
248/// * `dst`: Destination image
249/// * `dst_stride`: Destination image stride
250/// * `width`: Image width
251/// * `height`: Image Height
252/// * `mode`: Refer to [MirrorMode] for mode info
253///
254/// returns: Result<(), [YuvError]>
255///
256pub fn mirror_cbcr16(
257    src: &[u16],
258    src_stride: usize,
259    dst: &mut [u16],
260    dst_stride: usize,
261    width: usize,
262    height: usize,
263    mode: MirrorMode,
264) -> Result<(), YuvError> {
265    let rs = match mode {
266        MirrorMode::Vertical => {
267            flop_plane16_with_alpha(src, src_stride, dst, dst_stride, width, height)
268        }
269        MirrorMode::Horizontal => {
270            flip_plane16_with_alpha(src, src_stride, dst, dst_stride, width, height)
271        }
272    };
273    map_ft_result(rs)
274}
275
276/// Mirrors Plane 8+ bit image.
277///
278/// This mirrors any planar channels image.
279///
280/// # Arguments
281///
282/// * `src`: Source image
283/// * `src_stride`: Source image stride
284/// * `dst`: Destination image
285/// * `dst_stride`: Destination image stride
286/// * `width`: Image width
287/// * `height`: Image Height
288/// * `mode`: Refer to [MirrorMode] for mode info
289///
290/// returns: Result<(), [YuvError]>
291///
292pub fn mirror_plane16(
293    src: &[u16],
294    src_stride: usize,
295    dst: &mut [u16],
296    dst_stride: usize,
297    width: usize,
298    height: usize,
299    mode: MirrorMode,
300) -> Result<(), YuvError> {
301    let rs = match mode {
302        MirrorMode::Vertical => flop_plane16(src, src_stride, dst, dst_stride, width, height),
303        MirrorMode::Horizontal => flip_plane16(src, src_stride, dst, dst_stride, width, height),
304    };
305    map_ft_result(rs)
306}