1pub fn bgr_stride(width: usize) -> usize {
4 (width * 3).next_multiple_of(4)
5}
6
7pub 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
25pub 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#[inline]
36pub fn rgb_to_bgr(data: &mut [(u8, u8, u8)]) {
37 bgr_to_rgb(data);
38}
39
40pub 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#[inline]
55pub fn rgb_to_bgr_bytes(data: &mut [u8]) {
56 bgr_to_rgb_bytes(data);
57}
58
59pub 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#[inline]
70pub fn bgra_to_rgba(data: &mut [(u8, u8, u8, u8)]) {
71 rgba_to_bgra(data);
72}
73
74pub 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#[inline]
89pub fn bgra_to_rgba_bytes(data: &mut [u8]) {
90 rgba_to_bgra_bytes(data);
91}
92
93#[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, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, ];
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}