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}