Skip to content

Commit

Permalink
Added basic RGBA1010102 and RGBA2101010 support
Browse files Browse the repository at this point in the history
  • Loading branch information
awxkee committed Nov 20, 2024
1 parent 8402a08 commit a2912a7
Show file tree
Hide file tree
Showing 7 changed files with 1,422 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ workspace = { members = ["app"] }

[package]
name = "yuvutils-rs"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
description = "High performance utilities for YUV format handling and conversion."
readme = "README.md"
Expand Down
41 changes: 27 additions & 14 deletions app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,7 @@ use image::{ColorType, EncodableLayout, GenericImageView, ImageReader};
use std::fs::File;
use std::io::Read;
use std::time::Instant;
use yuvutils_rs::{
rgb_to_sharp_yuv422, rgb_to_yuv_nv12_p16, yuv422_to_rgb, yuv_nv12_to_rgb_p16,
SharpYuvGammaTransfer, YuvBiPlanarImageMut, YuvBytesPacking, YuvChromaSubsampling,
YuvEndianness, YuvPlanarImageMut, YuvRange, YuvStandardMatrix,
};
use yuvutils_rs::{ab30_to_rgb8, ar30_to_rgb8, ra30_to_rgb8, rgb_to_sharp_yuv422, rgb_to_yuv420_p16, rgb_to_yuv422_p16, rgb_to_yuv_nv12_p16, yuv422_p16_to_ab30, yuv422_p16_to_ar30, yuv422_p16_to_ra30, yuv422_to_rgb, yuv444_p16_to_ar30, yuv_nv12_to_rgb_p16, Rgb30ByteOrder, SharpYuvGammaTransfer, YuvBiPlanarImageMut, YuvBytesPacking, YuvChromaSubsampling, YuvEndianness, YuvPlanarImageMut, YuvRange, YuvStandardMatrix};

fn read_file_bytes(file_path: &str) -> Result<Vec<u8>, String> {
// Open the file
Expand Down Expand Up @@ -93,13 +89,13 @@ fn main() {
);

let mut planar_image =
YuvPlanarImageMut::<u8>::alloc(width as u32, height as u32, YuvChromaSubsampling::Yuv422);
YuvPlanarImageMut::<u16>::alloc(width as u32, height as u32, YuvChromaSubsampling::Yuv422);

let mut bytes_16: Vec<u16> = src_bytes.iter().map(|&x| (x as u16) << 2).collect();

let start_time = Instant::now();
rgb_to_yuv_nv12_p16(
&mut bi_planar_image,
rgb_to_yuv422_p16(
&mut planar_image,
&bytes_16,
rgba_stride as u32,
10,
Expand Down Expand Up @@ -218,24 +214,41 @@ fn main() {
// bytes_16.resize(width as usize * height as usize * 4, 0u16);
// rgba.resize(width as usize * height as usize * 4, 0u8);

yuv_nv12_to_rgb_p16(
&fixed_biplanar,
&mut bytes_16,
rgba_stride as u32,
let mut ar30 = vec![0u32; width as usize * height as usize];

yuv422_p16_to_ab30(
&fixed_planar,
&mut ar30,
width,
Rgb30ByteOrder::Host,
10,
YuvRange::Limited,
YuvStandardMatrix::Bt601,
YuvEndianness::LittleEndian,
YuvBytesPacking::LeastSignificantBytes,
)
.unwrap();
rgba.fill(0);
ab30_to_rgb8(&ar30, width, Rgb30ByteOrder::Host, &mut rgba, rgba_stride as u32, width, height).unwrap();

// yuv_nv12_to_rgb_p16(
// &fixed_biplanar,
// &mut bytes_16,
// rgba_stride as u32,
// 10,
// YuvRange::Limited,
// YuvStandardMatrix::Bt601,
// YuvEndianness::LittleEndian,
// YuvBytesPacking::LeastSignificantBytes,
// )
// .unwrap();

println!("Backward time: {:?}", start_time.elapsed());

rgba = bytes_16.iter().map(|&x| (x >> 2) as u8).collect();
// rgba = bytes_16.iter().map(|&x| (x >> 2) as u8).collect();

image::save_buffer(
"converted_sharp15.png",
"converted_sharp15.jpg",
rgba.as_bytes(),
dimensions.0,
dimensions.1,
Expand Down
12 changes: 11 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ mod internals;
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
mod neon;
mod numerics;
mod rgb_ar30;
mod rgb_to_nv_p16;
mod rgb_to_y;
mod rgb_to_ycgco;
Expand All @@ -73,6 +74,7 @@ mod yuv_nv_p10_to_rgba;
mod yuv_nv_p16_to_rgb;
mod yuv_nv_to_rgba;
mod yuv_p10_rgba;
mod yuv_p16_ar30;
mod yuv_p16_rgba;
mod yuv_p16_rgba16_alpha;
mod yuv_p16_rgba_alpha;
Expand All @@ -88,7 +90,8 @@ mod yuy2_to_yuv;
mod yuy2_to_yuv_p16;

pub use yuv_support::{
YuvBytesPacking, YuvChromaSubsampling, YuvEndianness, YuvRange, YuvStandardMatrix,
Rgb30ByteOrder, YuvBytesPacking, YuvChromaSubsampling, YuvEndianness, YuvRange,
YuvStandardMatrix,
};

pub use yuv_nv_p10_to_rgba::yuv_nv12_p10_to_bgr;
Expand Down Expand Up @@ -436,3 +439,10 @@ pub use yuv_p16_rgba::*;
pub use yuv_p16_rgba16_alpha::*;
pub use yuv_p16_rgba_alpha::*;
pub use yuv_p16_rgba_p16::*;

pub use rgb_ar30::{ab30_to_rgb8, ar30_to_rgb8, ba30_to_rgb8, ra30_to_rgb8};
pub use yuv_p16_ar30::{
yuv420_p16_to_ab30, yuv420_p16_to_ar30, yuv420_p16_to_ra30, yuv422_p16_to_ab30,
yuv422_p16_to_ar30, yuv422_p16_to_ra30, yuv444_p16_to_ab30, yuv444_p16_to_ar30,
yuv444_p16_to_ra30,
};
219 changes: 219 additions & 0 deletions src/rgb_ar30.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* Copyright (c) Radzivon Bartoshyk, 11/2024. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
use crate::yuv_error::check_rgba_destination;
use crate::yuv_support::{Rgb30, YuvSourceChannels};
use crate::{Rgb30ByteOrder, YuvError};

fn ar30_to_rgb8_impl<
const AR30_LAYOUT: usize,
const AR30_BYTE_ORDER: usize,
const RGBA_LAYOUT: u8,
>(
ar30: &[u32],
ar30_stride: u32,
rgba: &mut [u8],
rgba_stride: u32,
width: u32,
height: u32,
) -> Result<(), YuvError> {
let rgba_layout: YuvSourceChannels = RGBA_LAYOUT.into();
let ar30_layout: Rgb30 = AR30_LAYOUT.into();
check_rgba_destination(ar30, ar30_stride, width, height, 1)?;
check_rgba_destination(
rgba,
rgba_stride,
width,
height,
rgba_layout.get_channels_count(),
)?;

for (dst, src) in rgba
.chunks_exact_mut(rgba_stride as usize)
.zip(ar30.chunks_exact(ar30_stride as usize))
{
for (dst, &src) in dst
.chunks_exact_mut(rgba_layout.get_channels_count())
.zip(src.iter())
{
let unpacked = ar30_layout.unpack::<AR30_BYTE_ORDER>(src);
let r = unpacked.0 >> 2;
let g = unpacked.1 >> 2;
let b = unpacked.2 >> 2;
dst[rgba_layout.get_r_channel_offset()] = r as u8;
dst[rgba_layout.get_g_channel_offset()] = g as u8;
dst[rgba_layout.get_b_channel_offset()] = b as u8;
if rgba_layout.has_alpha() {
let expanded_a =
(unpacked.3 << 6) | (unpacked.3 << 4) | (unpacked.3 << 2) | unpacked.3;
dst[rgba_layout.get_a_channel_offset()] = expanded_a as u8;
}
}
}
Ok(())
}

/// Converts RGBA2101010 to RGB 8 bit depth
///
/// # Arguments
///
/// * `ar30`: Source AR30 data
/// * `ar30_stride`: Source AR30 stride
/// * `byte_order`: See [Rgb30ByteOrder] for more info
/// * `rgb`: Destination RGB data
/// * `rgb_stride`: Destination RGB stride
/// * `width`: Image width
/// * `height`: Image height
///
pub fn ar30_to_rgb8(
ar30: &[u32],
ar30_stride: u32,
byte_order: Rgb30ByteOrder,
rgb: &mut [u8],
rgb_stride: u32,
width: u32,
height: u32,
) -> Result<(), YuvError> {
match byte_order {
Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
{ Rgb30::Ar30 as usize },
{ Rgb30ByteOrder::Host as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
{ Rgb30::Ar30 as usize },
{ Rgb30ByteOrder::Network as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
}
}

/// Converts BGBA2101010 to RGB 8 bit depth
///
/// # Arguments
///
/// * `ab30`: Source AR30 data
/// * `ab30_stride`: Source AR30 stride
/// * `byte_order`: See [Rgb30ByteOrder] for more info
/// * `rgb`: Destination RGB data
/// * `rgb_stride`: Destination RGB stride
/// * `width`: Image width
/// * `height`: Image height
///
pub fn ab30_to_rgb8(
ab30: &[u32],
ab30_stride: u32,
byte_order: Rgb30ByteOrder,
rgb: &mut [u8],
rgb_stride: u32,
width: u32,
height: u32,
) -> Result<(), YuvError> {
match byte_order {
Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
{ Rgb30::Ab30 as usize },
{ Rgb30ByteOrder::Host as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ab30, ab30_stride, rgb, rgb_stride, width, height),
Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
{ Rgb30::Ab30 as usize },
{ Rgb30ByteOrder::Network as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ab30, ab30_stride, rgb, rgb_stride, width, height),
}
}

/// Converts RGBA1010102 to RGB 8 bit depth
///
/// # Arguments
///
/// * `ar30`: Source RA30 data
/// * `ar30_stride`: Source RA30 stride
/// * `byte_order`: See [Rgb30ByteOrder] for more info
/// * `rgb`: Destination RGB data
/// * `rgb_stride`: Destination RGB stride
/// * `width`: Image width
/// * `height`: Image height
///
pub fn ra30_to_rgb8(
ar30: &[u32],
ar30_stride: u32,
byte_order: Rgb30ByteOrder,
rgb: &mut [u8],
rgb_stride: u32,
width: u32,
height: u32,
) -> Result<(), YuvError> {
match byte_order {
Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
{ Rgb30::Ra30 as usize },
{ Rgb30ByteOrder::Host as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
{ Rgb30::Ra30 as usize },
{ Rgb30ByteOrder::Network as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
}
}

/// Converts BGRA1010102 to RGB 8 bit depth
///
/// # Arguments
///
/// * `ar30`: Source RA30 data
/// * `ar30_stride`: Source RA30 stride
/// * `byte_order`: See [Rgb30ByteOrder] for more info
/// * `rgb`: Destination RGB data
/// * `rgb_stride`: Destination RGB stride
/// * `width`: Image width
/// * `height`: Image height
///
pub fn ba30_to_rgb8(
ar30: &[u32],
ar30_stride: u32,
byte_order: Rgb30ByteOrder,
rgb: &mut [u8],
rgb_stride: u32,
width: u32,
height: u32,
) -> Result<(), YuvError> {
match byte_order {
Rgb30ByteOrder::Host => ar30_to_rgb8_impl::<
{ Rgb30::Ba30 as usize },
{ Rgb30ByteOrder::Host as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
Rgb30ByteOrder::Network => ar30_to_rgb8_impl::<
{ Rgb30::Ba30 as usize },
{ Rgb30ByteOrder::Network as usize },
{ YuvSourceChannels::Rgb as u8 },
>(ar30, ar30_stride, rgb, rgb_stride, width, height),
}
}
Loading

0 comments on commit a2912a7

Please sign in to comment.