Skip to main content

aviutl2/
utils.rs

1/// BGR24形式のDIBの1行のバイト数を返します。
2/// 行末のパディングを含め、4バイト境界に揃えます。
3pub fn bgr_stride(width: usize) -> usize {
4    (width * 3).next_multiple_of(4)
5}
6
7/// `Vec<T>`を2次元配列として捉え、上下に反転させる関数。
8///
9/// # Panics
10///
11/// `data.len()` が `width * height` でない場合にパニックします。
12pub fn flip_vertical<T>(data: &mut [T], width: usize, height: usize) {
13    assert!(data.len() == width * height);
14    let data_ptr = data.as_mut_ptr();
15    let row_size = width;
16    unsafe {
17        for y in 0..(height / 2) {
18            let top_row_start = data_ptr.add(y * row_size);
19            let bottom_row_start = data_ptr.add((height - 1 - y) * row_size);
20            std::ptr::swap_nonoverlapping(top_row_start, bottom_row_start, row_size);
21        }
22    }
23}
24
25/// Vec<(u8, u8, u8)>をBGRの配列として捉え、RGBの配列に変換する関数。
26/// エイリアスとして [`rgb_to_bgr`] も提供されます。
27pub fn bgr_to_rgb(data: &mut [(u8, u8, u8)]) {
28    for pixel in data.iter_mut() {
29        let (b, g, r) = *pixel;
30        *pixel = (r, g, b);
31    }
32}
33
34/// [`bgr_to_rgb`]のエイリアス。
35#[inline]
36pub fn rgb_to_bgr(data: &mut [(u8, u8, u8)]) {
37    bgr_to_rgb(data);
38}
39
40/// `Vec<u8>`をBGRの配列として捉え、RGBの配列に変換する関数。
41/// エイリアスとして [`rgb_to_bgr_bytes`] も提供されます。
42///
43/// # Panics
44///
45/// `data.len()` が3の倍数でない場合にパニックします。
46pub fn bgr_to_rgb_bytes(data: &mut [u8]) {
47    assert!(data.len().is_multiple_of(3));
48    for chunk in data.as_chunks_mut::<3>().0 {
49        chunk.swap(0, 2);
50    }
51}
52
53/// [`bgr_to_rgb_bytes`]のエイリアス。
54#[inline]
55pub fn rgb_to_bgr_bytes(data: &mut [u8]) {
56    bgr_to_rgb_bytes(data);
57}
58
59/// `Vec<(u8, u8, u8, u8)>`をRGBAの配列として捉え、BGRAの配列に変換する関数。
60/// エイリアスとして [`bgra_to_rgba`] も提供されます。
61pub fn rgba_to_bgra(data: &mut [(u8, u8, u8, u8)]) {
62    for pixel in data.iter_mut() {
63        let (b, g, r, a) = *pixel;
64        *pixel = (r, g, b, a);
65    }
66}
67
68/// [`rgba_to_bgra`]のエイリアス。
69#[inline]
70pub fn bgra_to_rgba(data: &mut [(u8, u8, u8, u8)]) {
71    rgba_to_bgra(data);
72}
73
74/// `Vec<u8>`をRGBAの配列として捉え、BGRAの配列に変換する関数。
75/// エイリアスとして [`bgra_to_rgba_bytes`] も提供されます。
76///
77/// # Panics
78///
79/// `data.len()` が4の倍数でない場合にパニックします。
80pub fn rgba_to_bgra_bytes(data: &mut [u8]) {
81    assert!(data.len().is_multiple_of(4));
82    for chunk in data.as_chunks_mut::<4>().0 {
83        chunk.swap(0, 2);
84    }
85}
86
87/// [`rgba_to_bgra_bytes`]のエイリアス。
88#[inline]
89pub fn bgra_to_rgba_bytes(data: &mut [u8]) {
90    rgba_to_bgra_bytes(data);
91}
92
93/// bitflagを簡単に初期化するためのマクロ。
94///
95/// # Example
96///
97/// ```rust
98/// # use aviutl2::bitflag;
99///
100/// let flag = bitflag!(
101///     aviutl2::filter::FilterPluginFlags {
102///         video: true,
103///     }
104/// );
105///
106/// assert!(flag.video);
107/// assert_eq!(flag.to_bits(), aviutl2_sys::filter2::FILTER_PLUGIN_TABLE::FLAG_VIDEO);
108/// ```
109#[macro_export]
110macro_rules! bitflag {
111    ($ty:ty { $($name:ident : $bit:expr),* $(,)? }) => {
112        {
113            let mut value: $ty = ::std::default::Default::default();
114            $(
115                value.$name = $bit;
116            )*
117            value
118        }
119    }
120}
121
122pub(crate) fn catch_unwind_with_panic_info<F, R>(f: F) -> Result<R, String>
123where
124    F: FnOnce() -> R + std::panic::UnwindSafe,
125{
126    match std::panic::catch_unwind(f) {
127        Ok(result) => Ok(result),
128        Err(err) => {
129            if let Some(s) = err.downcast_ref::<&str>() {
130                Err(s.to_string())
131            } else if let Some(s) = err.downcast_ref::<String>() {
132                Err(s.clone())
133            } else {
134                Err("<unknown panic>".to_string())
135            }
136        }
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143    #[test]
144    fn test_flip_vertical() {
145        let mut data = vec![
146            1, 2, 3, 4, 5, 6, // Row 0
147            7, 8, 9, 10, 11, 12, // Row 1
148            13, 14, 15, 16, 17, 18, // Row 2
149        ];
150        flip_vertical(&mut data, 6, 3);
151        assert_eq!(
152            data,
153            vec![
154                13, 14, 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6
155            ]
156        );
157    }
158
159    #[test]
160    fn test_bgr_to_rgb() {
161        let mut data = vec![(0, 0, 255), (0, 255, 0), (255, 0, 0)];
162        bgr_to_rgb(&mut data);
163        assert_eq!(data, vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)]);
164    }
165
166    #[test]
167    fn test_rgb_to_bgr() {
168        let mut data = vec![(255, 0, 0), (0, 255, 0), (0, 0, 255)];
169        rgb_to_bgr(&mut data);
170        assert_eq!(data, vec![(0, 0, 255), (0, 255, 0), (255, 0, 0)]);
171    }
172
173    #[test]
174    fn test_bgr_to_rgb_bytes() {
175        let mut data = vec![0, 0, 255, 0, 255, 0, 255, 0, 0];
176        bgr_to_rgb_bytes(&mut data);
177        assert_eq!(data, vec![255, 0, 0, 0, 255, 0, 0, 0, 255]);
178    }
179
180    #[test]
181    fn test_rgb_to_bgr_bytes() {
182        let mut data = vec![255, 0, 0, 0, 255, 0, 0, 0, 255];
183        rgb_to_bgr_bytes(&mut data);
184        assert_eq!(data, vec![0, 0, 255, 0, 255, 0, 255, 0, 0]);
185    }
186
187    #[test]
188    fn test_rgba_to_bgra() {
189        let mut data = vec![(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)];
190        rgba_to_bgra(&mut data);
191        assert_eq!(
192            data,
193            vec![(0, 0, 255, 255), (0, 255, 0, 255), (255, 0, 0, 255)]
194        );
195    }
196
197    #[test]
198    fn test_bgra_to_rgba() {
199        let mut data = vec![(0, 0, 255, 255), (0, 255, 0, 255), (255, 0, 0, 255)];
200        bgra_to_rgba(&mut data);
201        assert_eq!(
202            data,
203            vec![(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)]
204        );
205    }
206
207    #[test]
208    fn test_rgba_to_bgra_bytes() {
209        let mut data = vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255];
210        rgba_to_bgra_bytes(&mut data);
211        assert_eq!(data, vec![0, 0, 255, 255, 0, 255, 0, 255, 255, 0, 0, 255]);
212    }
213
214    #[test]
215    fn test_bgra_to_rgba_bytes() {
216        let mut data = vec![0, 0, 255, 255, 0, 255, 0, 255, 255, 0, 0, 255];
217        bgra_to_rgba_bytes(&mut data);
218        assert_eq!(data, vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]);
219    }
220}