yuvutils_rs/
yuy2_to_rgb.rs

1/*
2 * Copyright (c) Radzivon Bartoshyk, 10/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 */
29#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
30use crate::neon::yuy2_to_rgb_neon;
31use crate::numerics::qrshr;
32use crate::yuv_error::check_rgba_destination;
33use crate::yuv_support::{
34    get_inverse_transform, get_yuv_range, YuvSourceChannels, Yuy2Description,
35};
36#[allow(unused_imports)]
37use crate::yuv_to_yuy2::YuvToYuy2Navigation;
38use crate::{YuvError, YuvPackedImage, YuvRange, YuvStandardMatrix};
39#[cfg(feature = "rayon")]
40use rayon::iter::{IndexedParallelIterator, ParallelIterator};
41#[cfg(feature = "rayon")]
42use rayon::prelude::{ParallelSlice, ParallelSliceMut};
43
44fn yuy2_to_rgb_impl<const DESTINATION_CHANNELS: u8, const YUY2_SOURCE: usize>(
45    packed_image: &YuvPackedImage<u8>,
46    rgb_store: &mut [u8],
47    rgb_stride: u32,
48    range: YuvRange,
49    matrix: YuvStandardMatrix,
50) -> Result<(), YuvError> {
51    let yuy2_source: Yuy2Description = YUY2_SOURCE.into();
52
53    let dst_chans: YuvSourceChannels = DESTINATION_CHANNELS.into();
54    let channels = dst_chans.get_channels_count();
55
56    packed_image.check_constraints()?;
57    check_rgba_destination(
58        rgb_store,
59        rgb_stride,
60        packed_image.width,
61        packed_image.height,
62        channels,
63    )?;
64
65    let range = get_yuv_range(8, range);
66    let kr_kb = matrix.get_kr_kb();
67    let transform = get_inverse_transform(255, range.range_y, range.range_uv, kr_kb.kr, kr_kb.kb);
68    const PRECISION: i32 = 6;
69    let inverse_transform = transform.to_integers(PRECISION as u32);
70    let i16_transform = inverse_transform.cast::<i16>();
71    let cr_coef = i16_transform.cr_coef;
72    let cb_coef = i16_transform.cb_coef;
73    let y_coef = i16_transform.y_coef;
74    let g_coef_1 = i16_transform.g_coeff_1;
75    let g_coef_2 = i16_transform.g_coeff_2;
76    let bias_y = range.bias_y as i16;
77    let bias_uv = range.bias_uv as i16;
78
79    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
80    let _use_sse = std::arch::is_x86_feature_detected!("sse4.1");
81    #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "avx"))]
82    let _use_avx = std::arch::is_x86_feature_detected!("avx2");
83
84    let rgb_iter;
85    let yuy2_iter;
86    #[cfg(feature = "rayon")]
87    {
88        rgb_iter = rgb_store.par_chunks_exact_mut(rgb_stride as usize);
89        yuy2_iter = packed_image
90            .yuy
91            .par_chunks_exact(packed_image.yuy_stride as usize);
92    }
93    #[cfg(not(feature = "rayon"))]
94    {
95        rgb_iter = rgb_store.chunks_exact_mut(rgb_stride as usize);
96        yuy2_iter = packed_image
97            .yuy
98            .chunks_exact(packed_image.yuy_stride as usize);
99    }
100
101    let yuy2_width = if packed_image.width % 2 == 0 {
102        2 * packed_image.width as usize
103    } else {
104        2 * (packed_image.width as usize + 1)
105    };
106
107    rgb_iter.zip(yuy2_iter).for_each(|(rgb_store, yuy2_store)| {
108        let yuy2_store = &yuy2_store[0..yuy2_width];
109        let rgb_store = &mut rgb_store[0..(packed_image.width as usize * channels)];
110
111        let mut _cx = 0usize;
112        let mut _yuy2_x = 0usize;
113
114        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
115        {
116            #[cfg(feature = "avx")]
117            if _use_avx {
118                use crate::avx2::yuy2_to_rgb_avx;
119                let processed = yuy2_to_rgb_avx::<DESTINATION_CHANNELS, YUY2_SOURCE>(
120                    &range,
121                    &inverse_transform,
122                    yuy2_store,
123                    rgb_store,
124                    packed_image.width,
125                    YuvToYuy2Navigation::new(_cx, 0, _yuy2_x),
126                );
127                _cx = processed.cx;
128                _yuy2_x = processed.x;
129            }
130            #[cfg(feature = "sse")]
131            if _use_sse {
132                use crate::sse::yuy2_to_rgb_sse;
133                let processed = yuy2_to_rgb_sse::<DESTINATION_CHANNELS, YUY2_SOURCE>(
134                    &range,
135                    &inverse_transform,
136                    yuy2_store,
137                    rgb_store,
138                    packed_image.width,
139                    YuvToYuy2Navigation::new(_cx, 0, _yuy2_x),
140                );
141                _cx = processed.cx;
142                _yuy2_x = processed.x;
143            }
144        }
145
146        #[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
147        {
148            let processed = yuy2_to_rgb_neon::<DESTINATION_CHANNELS, YUY2_SOURCE, PRECISION>(
149                &range,
150                &inverse_transform,
151                yuy2_store,
152                rgb_store,
153                packed_image.width,
154                YuvToYuy2Navigation::new(_cx, 0, _yuy2_x),
155            );
156            _cx = processed.cx;
157            _yuy2_x = processed.x;
158        }
159
160        for (rgb, yuy2) in rgb_store
161            .chunks_exact_mut(2 * channels)
162            .zip(yuy2_store.chunks_exact(4))
163            .skip(_cx / 2)
164        {
165            let first_y = yuy2[yuy2_source.get_first_y_position()];
166            let second_y = yuy2[yuy2_source.get_second_y_position()];
167            let u_value = yuy2[yuy2_source.get_u_position()];
168            let v_value = yuy2[yuy2_source.get_v_position()];
169
170            let cb = u_value as i16 - bias_uv;
171            let cr = v_value as i16 - bias_uv;
172            let f_y = (first_y as i16 - bias_y) as i32 * y_coef as i32;
173            let s_y = (second_y as i16 - bias_y) as i32 * y_coef as i32;
174
175            let r0 = qrshr::<PRECISION, 8>(f_y + cr_coef as i32 * cr as i32);
176            let b0 = qrshr::<PRECISION, 8>(f_y + cb_coef as i32 * cb as i32);
177            let g0 = qrshr::<PRECISION, 8>(
178                f_y - g_coef_1 as i32 * cr as i32 - g_coef_2 as i32 * cb as i32,
179            );
180
181            rgb[dst_chans.get_r_channel_offset()] = r0 as u8;
182            rgb[dst_chans.get_g_channel_offset()] = g0 as u8;
183            rgb[dst_chans.get_b_channel_offset()] = b0 as u8;
184
185            if dst_chans.has_alpha() {
186                rgb[dst_chans.get_a_channel_offset()] = 255;
187            }
188
189            let r1 = qrshr::<PRECISION, 8>(s_y + cr_coef as i32 * cr as i32);
190            let b1 = qrshr::<PRECISION, 8>(s_y + cb_coef as i32 * cb as i32);
191            let g1 = qrshr::<PRECISION, 8>(
192                s_y - g_coef_1 as i32 * cr as i32 - g_coef_2 as i32 * cb as i32,
193            );
194
195            let rgb = &mut rgb[channels..channels * 2];
196
197            rgb[dst_chans.get_r_channel_offset()] = r1 as u8;
198            rgb[dst_chans.get_g_channel_offset()] = g1 as u8;
199            rgb[dst_chans.get_b_channel_offset()] = b1 as u8;
200
201            if dst_chans.has_alpha() {
202                rgb[dst_chans.get_a_channel_offset()] = 255;
203            }
204        }
205
206        if packed_image.width & 1 == 1 {
207            let last_rgb = rgb_store.chunks_exact_mut(2 * channels).into_remainder();
208            let rgb = &mut last_rgb[0..channels];
209            let yuy2 = yuy2_store.chunks_exact(4).last().unwrap();
210
211            let first_y = yuy2[yuy2_source.get_first_y_position()];
212            let u_value = yuy2[yuy2_source.get_u_position()];
213            let v_value = yuy2[yuy2_source.get_v_position()];
214
215            let cb = u_value as i16 - bias_uv;
216            let cr = v_value as i16 - bias_uv;
217            let f_y = (first_y as i16 - bias_y) as i32 * y_coef as i32;
218
219            let r0 = qrshr::<PRECISION, 8>(f_y + cr_coef as i32 * cr as i32);
220            let b0 = qrshr::<PRECISION, 8>(f_y + cb_coef as i32 * cb as i32);
221            let g0 = qrshr::<PRECISION, 8>(
222                f_y - g_coef_1 as i32 * cr as i32 - g_coef_2 as i32 * cb as i32,
223            );
224            rgb[dst_chans.get_r_channel_offset()] = r0 as u8;
225            rgb[dst_chans.get_g_channel_offset()] = g0 as u8;
226            rgb[dst_chans.get_b_channel_offset()] = b0 as u8;
227
228            if dst_chans.has_alpha() {
229                rgb[dst_chans.get_a_channel_offset()] = 255;
230            }
231        }
232    });
233    Ok(())
234}
235
236/// Convert YUYV (YUV Packed) format to RGB image.
237///
238/// This function takes YUYV (4:2:2 Packed) format data with 8-bit precision,
239/// and converts it to RGB with 8-bit per channel precision.
240///
241/// # Arguments
242///
243/// * `packed_image` - Source packed image.
244/// * `rgb` - A mutable slice to store the converted RGB data.
245/// * `rgb_stride` - The stride (components per row) for the RGB image data.
246/// * `range` - The YUV range (limited or full).
247/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
248///
249/// # Panics
250///
251/// This function panics if the lengths of the planes or the input YUYV data are not valid based
252/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
253///
254pub fn yuyv422_to_rgb(
255    packed_image: &YuvPackedImage<u8>,
256    rgb: &mut [u8],
257    rgb_stride: u32,
258    range: YuvRange,
259    matrix: YuvStandardMatrix,
260) -> Result<(), YuvError> {
261    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgb as u8 }, { Yuy2Description::YUYV as usize }>(
262        packed_image,
263        rgb,
264        rgb_stride,
265        range,
266        matrix,
267    )
268}
269
270/// Convert YUYV (YUV Packed) format to RGBA image.
271///
272/// This function takes YUYV (4:2:2 Packed) format data with 8-bit precision,
273/// and converts it to RGBA with 8-bit per channel precision.
274///
275/// # Arguments
276///
277/// * `packed_image` - Source packed image.
278/// * `rgba` - A mutable slice to store the converted RGBA data.
279/// * `rgba_stride` - The stride (components per row) for the RGBA image data.
280/// * `range` - The YUV range (limited or full).
281/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
282///
283/// # Panics
284///
285/// This function panics if the lengths of the planes or the input YUYV data are not valid based
286/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
287///
288pub fn yuyv422_to_rgba(
289    packed_image: &YuvPackedImage<u8>,
290    rgba: &mut [u8],
291    rgba_stride: u32,
292    range: YuvRange,
293    matrix: YuvStandardMatrix,
294) -> Result<(), YuvError> {
295    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgba as u8 }, { Yuy2Description::YUYV as usize }>(
296        packed_image,
297        rgba,
298        rgba_stride,
299        range,
300        matrix,
301    )
302}
303
304/// Convert YUYV (YUV Packed) format to BGR image.
305///
306/// This function takes YUYV (4:2:2 Packed) format data with 8-bit precision,
307/// and converts it to BGR with 8-bit per channel precision.
308///
309/// # Arguments
310///
311/// * `packed_image` - Source packed image.
312/// * `bgr` - A mutable slice to store the converted BGR data.
313/// * `bgr_stride` - The stride (components per row) for the BGR image data.
314/// * `range` - The YUV range (limited or full).
315/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
316///
317/// # Panics
318///
319/// This function panics if the lengths of the planes or the input YUYV data are not valid based
320/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
321///
322pub fn yuyv422_to_bgr(
323    packed_image: &YuvPackedImage<u8>,
324    bgr: &mut [u8],
325    bgr_stride: u32,
326    range: YuvRange,
327    matrix: YuvStandardMatrix,
328) -> Result<(), YuvError> {
329    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgr as u8 }, { Yuy2Description::YUYV as usize }>(
330        packed_image,
331        bgr,
332        bgr_stride,
333        range,
334        matrix,
335    )
336}
337
338/// Convert YUYV (YUV Packed) format to BGR image.
339///
340/// This function takes YUYV (4:2:2 Packed) format data with 8-bit precision,
341/// and converts it to BGRA with 8-bit per channel precision.
342///
343/// # Arguments
344///
345/// * `packed_image` - Source packed image.
346/// * `bgra` - A mutable slice to store the converted BGRA data.
347/// * `bgra_stride` - The stride (components per row) for the BGRA image data.
348/// * `range` - The YUV range (limited or full).
349/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
350///
351/// # Panics
352///
353/// This function panics if the lengths of the planes or the input YUYV data are not valid based
354/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
355///
356pub fn yuyv422_to_bgra(
357    packed_image: &YuvPackedImage<u8>,
358    bgra: &mut [u8],
359    bgra_stride: u32,
360    range: YuvRange,
361    matrix: YuvStandardMatrix,
362) -> Result<(), YuvError> {
363    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgra as u8 }, { Yuy2Description::YUYV as usize }>(
364        packed_image,
365        bgra,
366        bgra_stride,
367        range,
368        matrix,
369    )
370}
371
372/// Convert UYVY (YUV Packed) format to RGB image.
373///
374/// This function takes UYVY (4:2:2 Packed) format data with 8-bit precision,
375/// and converts it to RGB with 8-bit per channel precision.
376///
377/// # Arguments
378///
379/// * `packed_image` - Source packed image.
380/// * `rgb` - A mutable slice to store the converted RGB data.
381/// * `rgb_stride` - The stride (components per row) for the RGB image data.
382/// * `range` - The YUV range (limited or full).
383/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
384///
385/// # Panics
386///
387/// This function panics if the lengths of the planes or the input UYVY data are not valid based
388/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
389///
390pub fn uyvy422_to_rgb(
391    packed_image: &YuvPackedImage<u8>,
392    rgb: &mut [u8],
393    rgb_stride: u32,
394    range: YuvRange,
395    matrix: YuvStandardMatrix,
396) -> Result<(), YuvError> {
397    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgb as u8 }, { Yuy2Description::UYVY as usize }>(
398        packed_image,
399        rgb,
400        rgb_stride,
401        range,
402        matrix,
403    )
404}
405
406/// Convert UYVY (YUV Packed) format to RGBA image.
407///
408/// This function takes UYVY (4:2:2 Packed) format data with 8-bit precision,
409/// and converts it to RGBA with 8-bit per channel precision.
410///
411/// # Arguments
412///
413/// * `packed_image` - Source packed image.
414/// * `rgba` - A mutable slice to store the converted RGBA data.
415/// * `rgba_stride` - The stride (components per row) for the RGBA image data.
416/// * `range` - The YUV range (limited or full).
417/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
418///
419/// # Panics
420///
421/// This function panics if the lengths of the planes or the input UYVY data are not valid based
422/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
423///
424pub fn uyvy422_to_rgba(
425    packed_image: &YuvPackedImage<u8>,
426    rgba: &mut [u8],
427    rgba_stride: u32,
428    range: YuvRange,
429    matrix: YuvStandardMatrix,
430) -> Result<(), YuvError> {
431    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgba as u8 }, { Yuy2Description::UYVY as usize }>(
432        packed_image,
433        rgba,
434        rgba_stride,
435        range,
436        matrix,
437    )
438}
439
440/// Convert UYVY (YUV Packed) format to BGR image.
441///
442/// This function takes UYVY (4:2:2 Packed) format data with 8-bit precision,
443/// and converts it to BGR with 8-bit per channel precision.
444///
445/// # Arguments
446///
447/// * `packed_image` - Source packed image.
448/// * `bgr` - A mutable slice to store the converted BGR data.
449/// * `bgr_stride` - The stride (components per row) for the BGR image data.
450/// * `range` - The YUV range (limited or full).
451/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
452///
453/// # Panics
454///
455/// This function panics if the lengths of the planes or the input UYVY data are not valid based
456/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
457///
458pub fn uyvy422_to_bgr(
459    packed_image: &YuvPackedImage<u8>,
460    bgr: &mut [u8],
461    bgr_stride: u32,
462    range: YuvRange,
463    matrix: YuvStandardMatrix,
464) -> Result<(), YuvError> {
465    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgr as u8 }, { Yuy2Description::UYVY as usize }>(
466        packed_image,
467        bgr,
468        bgr_stride,
469        range,
470        matrix,
471    )
472}
473
474/// Convert UYVY (YUV Packed) format to BGRA image.
475///
476/// This function takes UYVY (4:2:2 Packed) format data with 8-bit precision,
477/// and converts it to BGRA with 8-bit per channel precision.
478///
479/// # Arguments
480///
481/// * `packed_image` - Source packed image.
482/// * `bgra` - A mutable slice to store the converted BGRA data.
483/// * `bgra_stride` - The stride (components per row) for the BGRA image data.
484/// * `range` - The YUV range (limited or full).
485/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
486///
487/// # Panics
488///
489/// This function panics if the lengths of the planes or the input UYVY data are not valid based
490/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
491///
492pub fn uyvy422_to_bgra(
493    packed_image: &YuvPackedImage<u8>,
494    bgra: &mut [u8],
495    bgra_stride: u32,
496    range: YuvRange,
497    matrix: YuvStandardMatrix,
498) -> Result<(), YuvError> {
499    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgra as u8 }, { Yuy2Description::UYVY as usize }>(
500        packed_image,
501        bgra,
502        bgra_stride,
503        range,
504        matrix,
505    )
506}
507
508/// Convert YVYU ( YUV Packed ) format to RGB image.
509///
510/// This function takes YVYU (4:2:2 Packed) format data with 8-bit precision,
511/// and converts it to RGB with 8-bit per channel precision.
512///
513/// # Arguments
514///
515/// * `packed_image` - Source packed image.
516/// * `rgb` - A mutable slice to store the converted RGB data.
517/// * `rgb_stride` - The stride (components per row) for the RGB image data.
518/// * `range` - The YUV range (limited or full).
519/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
520///
521/// # Panics
522///
523/// This function panics if the lengths of the planes or the input YVYU data are not valid based
524/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
525///
526pub fn yvyu422_to_rgb(
527    packed_image: &YuvPackedImage<u8>,
528    rgb: &mut [u8],
529    rgb_stride: u32,
530    range: YuvRange,
531    matrix: YuvStandardMatrix,
532) -> Result<(), YuvError> {
533    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgb as u8 }, { Yuy2Description::YVYU as usize }>(
534        packed_image,
535        rgb,
536        rgb_stride,
537        range,
538        matrix,
539    )
540}
541
542/// Convert YVYU (YUV Packed) format to RGBA image.
543///
544/// This function takes YVYU (4:2:2 Packed) format data with 8-bit precision,
545/// and converts it to RGBA with 8-bit per channel precision.
546///
547/// # Arguments
548///
549/// * `packed_image` - Source packed image.
550/// * `rgba` - A mutable slice to store the converted RGBA data.
551/// * `rgba_stride` - The stride (components per row) for the RGBA image data.
552/// * `range` - The YUV range (limited or full).
553/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
554///
555/// # Panics
556///
557/// This function panics if the lengths of the planes or the input YVYU data are not valid based
558/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
559///
560pub fn yvyu422_to_rgba(
561    packed_image: &YuvPackedImage<u8>,
562    rgba: &mut [u8],
563    rgba_stride: u32,
564    range: YuvRange,
565    matrix: YuvStandardMatrix,
566) -> Result<(), YuvError> {
567    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgba as u8 }, { Yuy2Description::YVYU as usize }>(
568        packed_image,
569        rgba,
570        rgba_stride,
571        range,
572        matrix,
573    )
574}
575
576/// Convert YVYU (YUV Packed) format to BGR image.
577///
578/// This function takes YVYU (4:2:2 Packed) format data with 8-bit precision,
579/// and converts it to BGR with 8-bit per channel precision.
580///
581/// # Arguments
582///
583/// * `packed_image` - Source packed image.
584/// * `bgr` - A mutable slice to store the converted BGR data.
585/// * `bgr_stride` - The stride (components per row) for the BGR image data.
586/// * `range` - The YUV range (limited or full).
587/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
588///
589/// # Panics
590///
591/// This function panics if the lengths of the planes or the input YVYU data are not valid based
592/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
593///
594pub fn yvyu422_to_bgr(
595    packed_image: &YuvPackedImage<u8>,
596    bgr: &mut [u8],
597    bgr_stride: u32,
598    range: YuvRange,
599    matrix: YuvStandardMatrix,
600) -> Result<(), YuvError> {
601    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgr as u8 }, { Yuy2Description::YVYU as usize }>(
602        packed_image,
603        bgr,
604        bgr_stride,
605        range,
606        matrix,
607    )
608}
609
610/// Convert YVYU (YUV Packed) format to BGRA image.
611///
612/// This function takes YVYU (4:2:2 Packed) format data with 8-bit precision,
613/// and converts it to BGRA with 8-bit per channel precision.
614///
615/// # Arguments
616///
617/// * `packed_image` - Source packed image.
618/// * `bgra` - A mutable slice to store the converted BGRA data.
619/// * `bgra_stride` - The stride (components per row) for the BGRA image data.
620/// * `range` - The YUV range (limited or full).
621/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
622///
623/// # Panics
624///
625/// This function panics if the lengths of the planes or the input YVYU data are not valid based
626/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
627///
628pub fn yvyu422_to_bgra(
629    packed_image: &YuvPackedImage<u8>,
630    bgra: &mut [u8],
631    bgra_stride: u32,
632    range: YuvRange,
633    matrix: YuvStandardMatrix,
634) -> Result<(), YuvError> {
635    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgra as u8 }, { Yuy2Description::YVYU as usize }>(
636        packed_image,
637        bgra,
638        bgra_stride,
639        range,
640        matrix,
641    )
642}
643
644/// Convert VYUY (YUV Packed) format to RGB image.
645///
646/// This function takes VYUY (4:2:2 Packed) format data with 8-bit precision,
647/// and converts it to RGB with 8-bit per channel precision.
648///
649/// # Arguments
650///
651/// * `packed_image` - Source packed image.
652/// * `rgb` - A mutable slice to store the converted RGB data.
653/// * `rgb_stride` - The stride (components per row) for the RGB image data.
654/// * `range` - The YUV range (limited or full).
655/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
656///
657/// # Panics
658///
659/// This function panics if the lengths of the planes or the input VYUY data are not valid based
660/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
661///
662pub fn vyuy422_to_rgb(
663    packed_image: &YuvPackedImage<u8>,
664    rgb: &mut [u8],
665    rgb_stride: u32,
666    range: YuvRange,
667    matrix: YuvStandardMatrix,
668) -> Result<(), YuvError> {
669    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgb as u8 }, { Yuy2Description::VYUY as usize }>(
670        packed_image,
671        rgb,
672        rgb_stride,
673        range,
674        matrix,
675    )
676}
677
678/// Convert VYUY (YUV Packed) format to RGBA image.
679///
680/// This function takes VYUY (4:2:2 Packed) format data with 8-bit precision,
681/// and converts it to RGBA with 8-bit per channel precision.
682///
683/// # Arguments
684///
685/// * `packed_image` - Source packed image.
686/// * `rgba` - A mutable slice to store the converted RGBA data.
687/// * `rgba_stride` - The stride (components per row) for the RGBA image data.
688/// * `range` - The YUV range (limited or full).
689/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
690///
691/// # Panics
692///
693/// This function panics if the lengths of the planes or the input VYUY data are not valid based
694/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
695///
696pub fn vyuy422_to_rgba(
697    packed_image: &YuvPackedImage<u8>,
698    rgba: &mut [u8],
699    rgba_stride: u32,
700    range: YuvRange,
701    matrix: YuvStandardMatrix,
702) -> Result<(), YuvError> {
703    yuy2_to_rgb_impl::<{ YuvSourceChannels::Rgba as u8 }, { Yuy2Description::VYUY as usize }>(
704        packed_image,
705        rgba,
706        rgba_stride,
707        range,
708        matrix,
709    )
710}
711
712/// Convert VYUY (YUV Packed) format to BGR image.
713///
714/// This function takes VYUY (4:2:2 Packed) format data with 8-bit precision,
715/// and converts it to BGR with 8-bit per channel precision.
716///
717/// # Arguments
718///
719/// * `packed_image` - Source packed image.
720/// * `bgr` - A mutable slice to store the converted BGR data.
721/// * `bgr_stride` - The stride (components per row) for the BGR image data.
722/// * `range` - The YUV range (limited or full).
723/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
724///
725/// # Panics
726///
727/// This function panics if the lengths of the planes or the input VYUY data are not valid based
728/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
729///
730pub fn vyuy422_to_bgr(
731    packed_image: &YuvPackedImage<u8>,
732    bgr: &mut [u8],
733    bgr_stride: u32,
734    range: YuvRange,
735    matrix: YuvStandardMatrix,
736) -> Result<(), YuvError> {
737    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgr as u8 }, { Yuy2Description::VYUY as usize }>(
738        packed_image,
739        bgr,
740        bgr_stride,
741        range,
742        matrix,
743    )
744}
745
746/// Convert VYUY (YUV Packed) format to BGRA image.
747///
748/// This function takes VYUY (4:2:2 Packed) format data with 8-bit precision,
749/// and converts it to BGRA with 8-bit per channel precision.
750///
751/// # Arguments
752///
753/// * `packed_image` - Source packed image.
754/// * `bgra` - A mutable slice to store the converted BGRA data.
755/// * `bgra_stride` - The stride (components per row) for the BGRA image data.
756/// * `range` - The YUV range (limited or full).
757/// * `matrix` - The YUV standard matrix (BT.601 or BT.709 or BT.2020 or other).
758///
759/// # Panics
760///
761/// This function panics if the lengths of the planes or the input VYUY data are not valid based
762/// on the specified width, height, and strides, or if invalid YUV range or matrix is provided.
763///
764pub fn vyuy422_to_bgra(
765    packed_image: &YuvPackedImage<u8>,
766    bgra: &mut [u8],
767    bgra_stride: u32,
768    range: YuvRange,
769    matrix: YuvStandardMatrix,
770) -> Result<(), YuvError> {
771    yuy2_to_rgb_impl::<{ YuvSourceChannels::Bgra as u8 }, { Yuy2Description::VYUY as usize }>(
772        packed_image,
773        bgra,
774        bgra_stride,
775        range,
776        matrix,
777    )
778}