yuvutils_rs/
ar30_rgb.rs

1/*
2 * Copyright (c) Radzivon Bartoshyk, 11/2024. 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::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
85/// Converts RGBA2101010 to RGB 8 bit depth
86///
87/// # Arguments
88///
89/// * `ar30`: Source AR30 data
90/// * `ar30_stride`: Source AR30 stride
91/// * `byte_order`: See [Rgb30ByteOrder] for more info
92/// * `rgb`: Destination RGB data
93/// * `rgb_stride`: Destination RGB stride
94/// * `width`: Image width
95/// * `height`: Image height
96///
97pub 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
120/// Converts BGBA2101010 to RGB 8 bit depth
121///
122/// # Arguments
123///
124/// * `ab30`: Source AR30 data
125/// * `ab30_stride`: Source AR30 stride
126/// * `byte_order`: See [Rgb30ByteOrder] for more info
127/// * `rgb`: Destination RGB data
128/// * `rgb_stride`: Destination RGB stride
129/// * `width`: Image width
130/// * `height`: Image height
131///
132pub 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
155/// Converts RGBA1010102 to RGB 8 bit depth
156///
157/// # Arguments
158///
159/// * `ar30`: Source RA30 data
160/// * `ar30_stride`: Source RA30 stride
161/// * `byte_order`: See [Rgb30ByteOrder] for more info
162/// * `rgb`: Destination RGB data
163/// * `rgb_stride`: Destination RGB stride
164/// * `width`: Image width
165/// * `height`: Image height
166///
167pub 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
190/// Converts BGRA1010102 to RGB 8 bit depth
191///
192/// # Arguments
193///
194/// * `ar30`: Source RA30 data
195/// * `ar30_stride`: Source RA30 stride
196/// * `byte_order`: See [Rgb30ByteOrder] for more info
197/// * `rgb`: Destination RGB data
198/// * `rgb_stride`: Destination RGB stride
199/// * `width`: Image width
200/// * `height`: Image height
201///
202pub 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
225/// Converts RGBA2101010 to RGB 8 bit depth
226///
227/// # Arguments
228///
229/// * `ar30`: Source AR30 data
230/// * `ar30_stride`: Source AR30 stride
231/// * `byte_order`: See [Rgb30ByteOrder] for more info
232/// * `rgba`: Destination RGBA data
233/// * `rgba_stride`: Destination RGBA stride
234/// * `width`: Image width
235/// * `height`: Image height
236///
237pub 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
260/// Converts RGBA1010102 to RGB 8 bit depth
261///
262/// # Arguments
263///
264/// * `ar30`: Source RA30 data
265/// * `ar30_stride`: Source RA30 stride
266/// * `byte_order`: See [Rgb30ByteOrder] for more info
267/// * `rgba`: Destination RGBA data
268/// * `rgba_stride`: Destination RGBA stride
269/// * `width`: Image width
270/// * `height`: Image height
271///
272pub 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}