1use crate::yuv_error::check_rgba_destination;
30use crate::yuv_support::{Rgb30, YuvSourceChannels};
31use crate::{Rgb30ByteOrder, YuvError};
32
33#[inline]
34fn ar30_to_rgb8_impl<
35 const AR30_LAYOUT: usize,
36 const AR30_BYTE_ORDER: usize,
37 const RGBA_LAYOUT: u8,
38>(
39 ar30: &[u8],
40 ar30_stride: u32,
41 rgba: &mut [u8],
42 rgba_stride: u32,
43 width: u32,
44 height: u32,
45) -> Result<(), YuvError> {
46 let rgba_layout: YuvSourceChannels = RGBA_LAYOUT.into();
47 let ar30_layout: Rgb30 = AR30_LAYOUT.into();
48 check_rgba_destination(ar30, ar30_stride, width, height, 4)?;
49 check_rgba_destination(
50 rgba,
51 rgba_stride,
52 width,
53 height,
54 rgba_layout.get_channels_count(),
55 )?;
56
57 for (dst, src) in rgba
58 .chunks_exact_mut(rgba_stride as usize)
59 .zip(ar30.chunks_exact(ar30_stride as usize))
60 {
61 let src = &src[0..width as usize * 4];
62 let dst = &mut dst[0..width as usize * rgba_layout.get_channels_count()];
63 for (dst, src) in dst
64 .chunks_exact_mut(rgba_layout.get_channels_count())
65 .zip(src.chunks_exact(4))
66 {
67 let ar30_v = u32::from_ne_bytes([src[0], src[1], src[2], src[3]]);
68 let unpacked = ar30_layout.unpack::<AR30_BYTE_ORDER>(ar30_v);
69 let r = unpacked.0 >> 2;
70 let g = unpacked.1 >> 2;
71 let b = unpacked.2 >> 2;
72 dst[rgba_layout.get_r_channel_offset()] = r as u8;
73 dst[rgba_layout.get_g_channel_offset()] = g as u8;
74 dst[rgba_layout.get_b_channel_offset()] = b as u8;
75 if rgba_layout.has_alpha() {
76 let expanded_a =
77 (unpacked.3 << 6) | (unpacked.3 << 4) | (unpacked.3 << 2) | unpacked.3;
78 dst[rgba_layout.get_a_channel_offset()] = expanded_a as u8;
79 }
80 }
81 }
82 Ok(())
83}
84
85pub fn ar30_to_rgb8(
98 ar30: &[u8],
99 ar30_stride: u32,
100 byte_order: Rgb30ByteOrder,
101 rgb: &mut [u8],
102 rgb_stride: u32,
103 width: u32,
104 height: u32,
105) -> Result<(), YuvError> {
106 match byte_order {
107 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
108 { Rgb30::Ar30 as usize },
109 { Rgb30ByteOrder::Host as usize },
110 { YuvSourceChannels::Rgb as u8 },
111 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
112 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
113 { Rgb30::Ar30 as usize },
114 { Rgb30ByteOrder::Network as usize },
115 { YuvSourceChannels::Rgb as u8 },
116 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
117 }
118}
119
120pub fn ab30_to_rgb8(
133 ab30: &[u8],
134 ab30_stride: u32,
135 byte_order: Rgb30ByteOrder,
136 rgb: &mut [u8],
137 rgb_stride: u32,
138 width: u32,
139 height: u32,
140) -> Result<(), YuvError> {
141 match byte_order {
142 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
143 { Rgb30::Ab30 as usize },
144 { Rgb30ByteOrder::Host as usize },
145 { YuvSourceChannels::Rgb as u8 },
146 >(ab30, ab30_stride, rgb, rgb_stride, width, height),
147 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
148 { Rgb30::Ab30 as usize },
149 { Rgb30ByteOrder::Network as usize },
150 { YuvSourceChannels::Rgb as u8 },
151 >(ab30, ab30_stride, rgb, rgb_stride, width, height),
152 }
153}
154
155pub fn ra30_to_rgb8(
168 ar30: &[u8],
169 ar30_stride: u32,
170 byte_order: Rgb30ByteOrder,
171 rgb: &mut [u8],
172 rgb_stride: u32,
173 width: u32,
174 height: u32,
175) -> Result<(), YuvError> {
176 match byte_order {
177 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
178 { Rgb30::Ra30 as usize },
179 { Rgb30ByteOrder::Host as usize },
180 { YuvSourceChannels::Rgb as u8 },
181 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
182 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
183 { Rgb30::Ra30 as usize },
184 { Rgb30ByteOrder::Network as usize },
185 { YuvSourceChannels::Rgb as u8 },
186 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
187 }
188}
189
190pub fn ba30_to_rgb8(
203 ar30: &[u8],
204 ar30_stride: u32,
205 byte_order: Rgb30ByteOrder,
206 rgb: &mut [u8],
207 rgb_stride: u32,
208 width: u32,
209 height: u32,
210) -> Result<(), YuvError> {
211 match byte_order {
212 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
213 { Rgb30::Ba30 as usize },
214 { Rgb30ByteOrder::Host as usize },
215 { YuvSourceChannels::Rgb as u8 },
216 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
217 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
218 { Rgb30::Ba30 as usize },
219 { Rgb30ByteOrder::Network as usize },
220 { YuvSourceChannels::Rgb as u8 },
221 >(ar30, ar30_stride, rgb, rgb_stride, width, height),
222 }
223}
224
225pub fn ar30_to_rgba8(
238 ar30: &[u8],
239 ar30_stride: u32,
240 byte_order: Rgb30ByteOrder,
241 rgba: &mut [u8],
242 rgba_stride: u32,
243 width: u32,
244 height: u32,
245) -> Result<(), YuvError> {
246 match byte_order {
247 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
248 { Rgb30::Ar30 as usize },
249 { Rgb30ByteOrder::Host as usize },
250 { YuvSourceChannels::Rgba as u8 },
251 >(ar30, ar30_stride, rgba, rgba_stride, width, height),
252 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
253 { Rgb30::Ar30 as usize },
254 { Rgb30ByteOrder::Network as usize },
255 { YuvSourceChannels::Rgba as u8 },
256 >(ar30, ar30_stride, rgba, rgba_stride, width, height),
257 }
258}
259
260pub fn ra30_to_rgba8(
273 ra30: &[u8],
274 ra30_stride: u32,
275 byte_order: Rgb30ByteOrder,
276 rgba: &mut [u8],
277 rgba_stride: u32,
278 width: u32,
279 height: u32,
280) -> Result<(), YuvError> {
281 match byte_order {
282 Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
283 { Rgb30::Ra30 as usize },
284 { Rgb30ByteOrder::Host as usize },
285 { YuvSourceChannels::Rgba as u8 },
286 >(ra30, ra30_stride, rgba, rgba_stride, width, height),
287 Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
288 { Rgb30::Ra30 as usize },
289 { Rgb30ByteOrder::Network as usize },
290 { YuvSourceChannels::Rgba as u8 },
291 >(ra30, ra30_stride, rgba, rgba_stride, width, height),
292 }
293}