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}