Skip to content

Commit

Permalink
Merge pull request #17 from awxkee/dev
Browse files Browse the repository at this point in the history
GBR improvements, YUV 4:0:0 improvements
  • Loading branch information
awxkee authored Nov 30, 2024
2 parents a4c0264 + 79028e6 commit 27a6868
Show file tree
Hide file tree
Showing 44 changed files with 1,604 additions and 218 deletions.
43 changes: 42 additions & 1 deletion Cargo.lock

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

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
workspace = { members = ["app"] }
workspace = { members = ["app", "coeffs"] }

[package]
name = "yuvutils-rs"
version = "0.5.8"
version = "0.5.9"
edition = "2021"
description = "High performance utilities for YUV format handling and conversion."
readme = "README.md"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,11 @@ Tests performed on the image 5763x3842
|------------------------|:----------:|:---------:|
| utils RGB->YUV 4:2:0 | 3.16ms | 3.53ms |
| libyuv RGB->YUV 4:2:0 | 3.58ms | 33.87ms |
| utils RGBA->YUV 4:2:0 | 4.07ms | 5.47ms |
| utils RGBA->YUV 4:2:0 | 4.04ms | 5.47ms |
| libyuv RGBA->YUV 4:2:0 | 4.87ms | 23.48ms |
| utils RGBA->YUV 4:2:2 | 4.46ms | 7.08ms |
| utils RGBA->YUV 4:2:2 | 4.37ms | 7.08ms |
| libyuv RGBA->YUV 4:2:2 | 5.90ms | 35.23ms |
| utils RGBA->YUV 4:4:4 | 4.66ms | 7.97ms |
| utils RGBA->YUV 4:4:4 | 4.49ms | 7.97ms |

### Decoding

Expand Down
27 changes: 23 additions & 4 deletions app/benches/yuv8/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ use yuv_sys::{
rs_NV21ToABGR, rs_RGB24ToI420,
};
use yuvutils_rs::{
rgb_to_yuv420, rgb_to_yuv422, rgb_to_yuv444, rgb_to_yuv_nv12, rgba_to_yuv420, rgba_to_yuv422,
rgba_to_yuv444, yuv420_to_rgb, yuv420_to_rgba, yuv422_to_rgba, yuv444_to_rgba,
yuv_nv12_to_rgba, YuvBiPlanarImageMut, YuvChromaSubsampling, YuvPlanarImageMut, YuvRange,
YuvStandardMatrix,
gbr_to_rgba, rgb_to_gbr, rgb_to_yuv420, rgb_to_yuv422, rgb_to_yuv444, rgb_to_yuv_nv12,
rgba_to_yuv420, rgba_to_yuv422, rgba_to_yuv444, yuv420_to_rgb, yuv420_to_rgba, yuv422_to_rgba,
yuv444_to_rgba, yuv_nv12_to_rgba, YuvBiPlanarImageMut, YuvChromaSubsampling, YuvPlanarImageMut,
YuvRange, YuvStandardMatrix,
};

pub fn criterion_benchmark(c: &mut Criterion) {
Expand All @@ -53,9 +53,14 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let mut planar_image =
YuvPlanarImageMut::<u8>::alloc(dimensions.0, dimensions.1, YuvChromaSubsampling::Yuv420);

let mut gbr_image =
YuvPlanarImageMut::<u8>::alloc(dimensions.0, dimensions.1, YuvChromaSubsampling::Yuv444);

let mut bi_planar_image =
YuvBiPlanarImageMut::<u8>::alloc(dimensions.0, dimensions.1, YuvChromaSubsampling::Yuv420);

rgb_to_gbr(&mut gbr_image, &src_bytes, stride as u32, YuvRange::Limited).unwrap();

rgb_to_yuv420(
&mut planar_image,
&src_bytes,
Expand All @@ -79,6 +84,20 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let fixed_planar = planar_image.to_fixed();

let rgba_image = img.to_rgba8();
let fixed_gbr = gbr_image.to_fixed();

c.bench_function("yuvutils GBR -> RGBA Limited", |b| {
let mut rgb_bytes = vec![0u8; dimensions.0 as usize * 4 * dimensions.1 as usize];
b.iter(|| {
gbr_to_rgba(
&fixed_gbr,
&mut rgb_bytes,
dimensions.0 * 4,
YuvRange::Limited,
)
.unwrap();
})
});

c.bench_function("yuvutils RGB -> YUV 4:2:0", |b| {
let mut test_planar = YuvPlanarImageMut::<u8>::alloc(
Expand Down
31 changes: 13 additions & 18 deletions app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ use std::io::Read;
use std::time::Instant;
use yuv_sys::{rs_I420ToRGB24, rs_NV12ToRGB24, rs_NV21ToABGR, rs_NV21ToRGB24};
use yuvutils_rs::{
rgb_to_yuv420, rgb_to_yuv420_p16, rgb_to_yuv422, rgb_to_yuv422_p16, rgb_to_yuv444,
rgb_to_yuv_nv12, yuv420_p16_to_rgb16, yuv420_to_rgb, yuv420_to_yuyv422, yuv422_p16_to_rgb16,
yuv422_to_rgb, yuv444_to_rgb, yuv_nv12_to_rgb, yuv_nv12_to_rgba, yuyv422_to_yuv420,
BufferStoreMut, YuvBiPlanarImageMut, YuvBytesPacking, YuvChromaSubsampling, YuvEndianness,
YuvPackedImage, YuvPackedImageMut, YuvPlanarImageMut, YuvRange, YuvStandardMatrix,
gbr_to_rgb, rgb_to_gbr, rgb_to_yuv420, rgb_to_yuv420_p16, rgb_to_yuv422, rgb_to_yuv422_p16,
rgb_to_yuv444, rgb_to_yuv_nv12, yuv420_p16_to_rgb16, yuv420_to_rgb, yuv420_to_yuyv422,
yuv422_p16_to_rgb16, yuv422_to_rgb, yuv444_to_rgb, yuv_nv12_to_rgb, yuv_nv12_to_rgba,
yuyv422_to_yuv420, BufferStoreMut, YuvBiPlanarImageMut, YuvBytesPacking, YuvChromaSubsampling,
YuvEndianness, YuvPackedImage, YuvPackedImageMut, YuvPlanarImageMut, YuvRange,
YuvStandardMatrix,
};

fn read_file_bytes(file_path: &str) -> Result<Vec<u8>, String> {
Expand Down Expand Up @@ -94,20 +95,17 @@ fn main() {
YuvBiPlanarImageMut::<u8>::alloc(width as u32, height as u32, YuvChromaSubsampling::Yuv420);

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

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

let start_time = Instant::now();
rgb_to_yuv422_p16(
rgb_to_yuv420(
&mut planar_image,
&bytes_16,
&src_bytes,
rgba_stride as u32,
12,
YuvRange::Limited,
YuvStandardMatrix::Bt601,
YuvEndianness::LittleEndian,
YuvBytesPacking::LeastSignificantBytes,
)
.unwrap();
// bytes_16.fill(0);
Expand Down Expand Up @@ -260,15 +258,12 @@ fn main() {
// let rgba_stride = width as usize * 4;
// let mut rgba = vec![0u8; height as usize * rgba_stride];

yuv422_p16_to_rgb16(
yuv420_to_rgb(
&fixed_planar,
&mut bytes_16,
&mut rgba,
rgba_stride as u32,
12,
YuvRange::Limited,
YuvStandardMatrix::Bt601,
YuvEndianness::LittleEndian,
YuvBytesPacking::LeastSignificantBytes,
)
.unwrap();

Expand Down Expand Up @@ -309,7 +304,7 @@ fn main() {
// chunk[2] = b;
// });

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

image::save_buffer(
"converted_sharp15.jpg",
Expand Down
50 changes: 23 additions & 27 deletions coeffs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,31 +182,31 @@ fn get_forward_coeffs_integral(

CbCrForwardTransform {
yr: (yr * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
yg: (yg * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
yb: (yb * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cb_r: (cb_r * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cb_g: (cb_g * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cb_b: (cb_b * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cr_r: (cr_r * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cr_g: (cr_g * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
cr_b: (cr_b * Float::with_val(BITS, prec))
.to_i32_saturating_round(Round::Down)
.to_i32_saturating_round(Round::Nearest)
.unwrap(),
}
}
Expand Down Expand Up @@ -300,21 +300,16 @@ pub fn get_inverse_transform_integral(
* range_uv();
let prec = (1 << prec) as f32;
let y_coeff = y_coef * Float::with_val(BITS, prec);
println!("Y Coeff {}", y_coeff);
let cr_coeff = cr_coeff * Float::with_val(BITS, prec);
println!("Cr Coeff {}", cr_coeff);
let cb_coeff = cb_coeff * Float::with_val(BITS, prec);
println!("Cb Coeff {}", cr_coeff);
let g_coeff_1 = g_coeff_1 * Float::with_val(BITS, prec);
println!("G Coeff 1 {}", g_coeff_1);
let g_coeff_2 = g_coeff_2 * Float::with_val(BITS, prec);
println!("G Coeff 2 {}", g_coeff_2);
CbCrInverseTransform::new(
y_coeff.to_i32_saturating_round(Round::Down).unwrap(),
cr_coeff.to_i32_saturating_round(Round::Down).unwrap(),
cb_coeff.to_i32_saturating_round(Round::Down).unwrap(),
g_coeff_1.to_i32_saturating_round(Round::Down).unwrap(),
g_coeff_2.to_i32_saturating_round(Round::Down).unwrap(),
y_coeff.to_i32_saturating_round(Round::Nearest).unwrap(),
cr_coeff.to_i32_saturating_round(Round::Nearest).unwrap(),
cb_coeff.to_i32_saturating_round(Round::Nearest).unwrap(),
g_coeff_1.to_i32_saturating_round(Round::Nearest).unwrap(),
g_coeff_2.to_i32_saturating_round(Round::Nearest).unwrap(),
)
}

Expand Down Expand Up @@ -369,15 +364,16 @@ impl YuvStandardMatrix {
}

fn main() {
let transform = get_forward_coeffs(0.2220f32, 0.0713f32, 8, YuvRange::Limited);
println!("Precise {:?}", transform);
let integral = get_forward_coeffs_integral(0.2220f32, 0.0713f32, 8, YuvRange::Limited, 13);
println!("Integral {:?}", integral);
let kr_kb = YuvStandardMatrix::Bt2020.get_kr_kb();
let range = YuvRange::Full;
let bit_depth = 12;
let transform = get_forward_coeffs(kr_kb.kr, kr_kb.kb, bit_depth, range);
println!("Precise {:?};", transform);
let integral = get_forward_coeffs_integral(kr_kb.kr, kr_kb.kb, bit_depth, range, 13);
println!("Integral {:?};", integral);

let kr_kb = YuvStandardMatrix::Bt601.get_kr_kb();
let inverse = get_inverse_transform(kr_kb.kr, kr_kb.kb, 8, YuvRange::Limited);
let inverse = get_inverse_transform(kr_kb.kr, kr_kb.kb, bit_depth, range);
println!("Inverse {:?}", inverse);
let inverse_integral =
get_inverse_transform_integral(kr_kb.kr, kr_kb.kb, 8, 13, YuvRange::Limited);
let inverse_integral = get_inverse_transform_integral(kr_kb.kr, kr_kb.kb, bit_depth, 13, range);
println!("Inverse Integral {:?};", inverse_integral);
}
Loading

0 comments on commit 27a6868

Please sign in to comment.