aviutl2/
utils.rs

1/// `Vec<T>`を2次元配列として捉え、上下に反転させる関数。
2///
3/// # Panics
4///
5/// `data.len()` が `width * height` でない場合にパニックします。
6pub fn flip_vertical<T>(data: &mut [T], width: usize, height: usize) {
7    assert!(data.len() == width * height);
8    let data_ptr = data.as_mut_ptr();
9    let row_size = width;
10    unsafe {
11        for y in 0..(height / 2) {
12            let top_row_start = data_ptr.add(y * row_size);
13            let bottom_row_start = data_ptr.add((height - 1 - y) * row_size);
14            std::ptr::swap_nonoverlapping(top_row_start, bottom_row_start, row_size);
15        }
16    }
17}
18
19/// Vec<(u8, u8, u8)>をBGRの配列として捉え、RGBの配列に変換する関数。
20/// エイリアスとして [`rgb_to_bgr`] も提供されます。
21pub fn bgr_to_rgb(data: &mut [(u8, u8, u8)]) {
22    for pixel in data.iter_mut() {
23        let (b, g, r) = *pixel;
24        *pixel = (r, g, b);
25    }
26}
27
28/// [`bgr_to_rgb`]のエイリアス。
29#[inline]
30pub fn rgb_to_bgr(data: &mut [(u8, u8, u8)]) {
31    bgr_to_rgb(data);
32}
33
34/// `Vec<u8>`をBGRの配列として捉え、RGBの配列に変換する関数。
35/// エイリアスとして [`rgb_to_bgr_bytes`] も提供されます。
36///
37/// # Panics
38///
39/// `data.len()` が3の倍数でない場合にパニックします。
40pub fn bgr_to_rgb_bytes(data: &mut [u8]) {
41    assert!(data.len().is_multiple_of(3));
42    for chunk in data.chunks_exact_mut(3) {
43        chunk.swap(0, 2);
44    }
45}
46
47/// [`bgr_to_rgb_bytes`]のエイリアス。
48#[inline]
49pub fn rgb_to_bgr_bytes(data: &mut [u8]) {
50    bgr_to_rgb_bytes(data);
51}
52
53/// `Vec<(u8, u8, u8, u8)>`をRGBAの配列として捉え、BGRAの配列に変換する関数。
54/// エイリアスとして [`bgra_to_rgba`] も提供されます。
55pub fn rgba_to_bgra(data: &mut [(u8, u8, u8, u8)]) {
56    for pixel in data.iter_mut() {
57        let (b, g, r, a) = *pixel;
58        *pixel = (r, g, b, a);
59    }
60}
61
62/// [`rgba_to_bgra`]のエイリアス。
63#[inline]
64pub fn bgra_to_rgba(data: &mut [(u8, u8, u8, u8)]) {
65    rgba_to_bgra(data);
66}
67
68/// `Vec<u8>`をRGBAの配列として捉え、BGRAの配列に変換する関数。
69/// エイリアスとして [`bgra_to_rgba_bytes`] も提供されます。
70///
71/// # Panics
72///
73/// `data.len()` が4の倍数でない場合にパニックします。
74pub fn rgba_to_bgra_bytes(data: &mut [u8]) {
75    assert!(data.len().is_multiple_of(4));
76    for chunk in data.chunks_exact_mut(4) {
77        chunk.swap(0, 2);
78    }
79}
80
81/// [`rgba_to_bgra_bytes`]のエイリアス。
82#[inline]
83pub fn bgra_to_rgba_bytes(data: &mut [u8]) {
84    rgba_to_bgra_bytes(data);
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90    #[test]
91    fn test_flip_vertical() {
92        let mut data = vec![
93            1, 2, 3, 4, 5, 6, // Row 0
94            7, 8, 9, 10, 11, 12, // Row 1
95            13, 14, 15, 16, 17, 18, // Row 2
96        ];
97        flip_vertical(&mut data, 6, 3);
98        assert_eq!(
99            data,
100            vec![
101                13, 14, 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6
102            ]
103        );
104    }
105
106    #[test]
107    fn test_bgr_to_rgb() {
108        let mut data = vec![(0, 0, 255), (0, 255, 0), (255, 0, 0)];
109        bgr_to_rgb(&mut data);
110        assert_eq!(data, vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)]);
111    }
112
113    #[test]
114    fn test_rgb_to_bgr() {
115        let mut data = vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)];
116        rgb_to_bgr(&mut data);
117        assert_eq!(data, vec![(0, 0, 255), (0, 255, 0), (255, 0, 0)]);
118    }
119
120    #[test]
121    fn test_bgr_to_rgb_bytes() {
122        let mut data = vec![0, 0, 255, 0, 255, 0, 255, 0, 0];
123        bgr_to_rgb_bytes(&mut data);
124        assert_eq!(data, vec![255, 0, 0, 0, 255, 0, 0, 0, 255]);
125    }
126
127    #[test]
128    fn test_rgb_to_bgr_bytes() {
129        let mut data = vec![255, 0, 0, 0, 255, 0, 0, 0, 255];
130        rgb_to_bgr_bytes(&mut data);
131        assert_eq!(data, vec![0, 0, 255, 0, 255, 0, 255, 0, 0]);
132    }
133
134    #[test]
135    fn test_rgba_to_bgra() {
136        let mut data = vec![(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)];
137        rgba_to_bgra(&mut data);
138        assert_eq!(
139            data,
140            vec![(0, 0, 255, 255), (0, 255, 0, 255), (255, 0, 0, 255)]
141        );
142    }
143
144    #[test]
145    fn test_bgra_to_rgba() {
146        let mut data = vec![(0, 0, 255, 255), (0, 255, 0, 255), (255, 0, 0, 255)];
147        bgra_to_rgba(&mut data);
148        assert_eq!(
149            data,
150            vec![(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)]
151        );
152    }
153
154    #[test]
155    fn test_rgba_to_bgra_bytes() {
156        let mut data = vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255];
157        rgba_to_bgra_bytes(&mut data);
158        assert_eq!(data, vec![0, 0, 255, 255, 0, 255, 0, 255, 255, 0, 0, 255]);
159    }
160
161    #[test]
162    fn test_bgra_to_rgba_bytes() {
163        let mut data = vec![0, 0, 255, 255, 0, 255, 0, 255, 255, 0, 0, 255];
164        bgra_to_rgba_bytes(&mut data);
165        assert_eq!(data, vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]);
166    }
167}