use crate::ColorMatrix;
#[cfg(any(
feature = "gbr",
feature = "gray",
feature = "rgb",
feature = "yuv-444-packed",
feature = "yuva",
))]
pub(crate) mod alpha_extract;
#[cfg(feature = "yuv-444-packed")]
mod ayuv64;
#[cfg(feature = "bayer")]
mod bayer;
#[cfg(feature = "gray")]
pub(crate) mod gray;
#[cfg(feature = "gray")]
pub(crate) mod grayf32;
mod hsv;
#[cfg(feature = "rgb-legacy")]
pub(crate) mod legacy_rgb;
#[cfg(feature = "mono")]
pub(crate) mod mono1bit;
#[cfg(feature = "rgb")]
mod packed_rgb;
#[cfg(feature = "rgb")]
mod packed_rgb_16bit;
#[cfg(feature = "rgb-float")]
mod packed_rgb_float;
#[cfg(feature = "yuv-packed")]
mod packed_yuv_4_1_1;
#[cfg(feature = "yuv-packed")]
mod packed_yuv_8bit;
#[cfg(feature = "mono")]
pub(crate) mod pal8;
#[cfg(feature = "gbr")]
mod planar_gbr;
#[cfg(feature = "gbr")]
pub(crate) mod planar_gbr_f16;
#[cfg(feature = "gbr")]
pub(crate) mod planar_gbr_float;
#[cfg(feature = "gbr")]
pub(crate) mod planar_gbr_high_bit;
mod rgb_expand;
#[cfg(feature = "yuv-semi-planar")]
mod semi_planar_8bit;
#[cfg(feature = "yuv-semi-planar")]
mod subsampled_high_bit_pn;
#[cfg(feature = "v210")]
mod v210;
#[cfg(feature = "yuv-444-packed")]
mod v30x;
#[cfg(feature = "yuv-444-packed")]
mod v410;
#[cfg(feature = "yuv-444-packed")]
mod vuya;
#[cfg(feature = "yuv-444-packed")]
mod xv36;
#[cfg(all(feature = "xyz", any(feature = "std", feature = "alloc")))]
pub(crate) mod xyz12;
#[cfg(all(feature = "xyz", any(feature = "std", feature = "alloc")))]
pub(crate) mod xyz12_constants;
#[cfg(feature = "y2xx")]
mod y216;
#[cfg(feature = "y2xx")]
mod y2xx;
#[cfg(any(
feature = "gray",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
pub(crate) mod y_plane_to_luma_u16;
#[cfg(feature = "gray")]
pub(crate) mod ya16;
#[cfg(feature = "gray")]
pub(crate) mod ya8;
#[cfg(any(feature = "yuv-planar", feature = "yuv-semi-planar"))]
mod yuv_planar_16bit;
#[cfg(feature = "yuv-planar")]
mod yuv_planar_8bit;
#[cfg(feature = "yuv-planar")]
mod yuv_planar_high_bit;
#[cfg(any(
feature = "gbr",
feature = "gray",
feature = "rgb",
feature = "yuv-444-packed",
feature = "yuva",
))]
#[allow(unused_imports)]
pub(crate) use alpha_extract::*;
#[cfg(feature = "yuv-444-packed")]
pub(crate) use ayuv64::*;
#[cfg(feature = "bayer")]
pub(crate) use bayer::*;
#[cfg(feature = "rgb-legacy")]
#[allow(unused_imports)]
pub(crate) use legacy_rgb::*;
#[cfg(feature = "gray")]
#[allow(unused_imports)]
pub(crate) use gray::*;
#[cfg(feature = "gray")]
#[allow(unused_imports)]
pub(crate) use grayf32::*;
pub(crate) use hsv::*;
#[cfg(feature = "mono")]
#[allow(unused_imports)]
pub(crate) use mono1bit::*;
#[cfg(feature = "rgb")]
pub(crate) use packed_rgb::*;
#[cfg(feature = "rgb")]
pub(crate) use packed_rgb_16bit::*;
#[cfg(feature = "rgb-float")]
pub(crate) use packed_rgb_float::*;
#[cfg(feature = "yuv-packed")]
pub(crate) use packed_yuv_4_1_1::*;
#[cfg(feature = "yuv-packed")]
pub(crate) use packed_yuv_8bit::*;
#[cfg(feature = "gbr")]
pub(crate) use planar_gbr::*;
#[cfg(feature = "gbr")]
#[allow(unused_imports)]
pub(crate) use planar_gbr_f16::*;
#[cfg(feature = "gbr")]
#[allow(unused_imports)]
pub(crate) use planar_gbr_float::*;
#[cfg(feature = "gbr")]
pub(crate) use planar_gbr_high_bit::*;
#[cfg(all(
any(feature = "std", feature = "alloc"),
any(
feature = "gbr",
feature = "gray",
feature = "rgb",
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
),
))]
pub(crate) use rgb_expand::*;
#[cfg(feature = "yuv-semi-planar")]
pub(crate) use semi_planar_8bit::*;
#[cfg(feature = "yuv-semi-planar")]
pub(crate) use subsampled_high_bit_pn::*;
#[cfg(feature = "yuv-444-packed")]
pub(crate) use v30x::*;
#[cfg(feature = "v210")]
pub(crate) use v210::*;
#[cfg(feature = "yuv-444-packed")]
pub(crate) use v410::*;
#[cfg(feature = "yuv-444-packed")]
pub(crate) use vuya::*;
#[cfg(feature = "yuv-444-packed")]
pub(crate) use xv36::*;
#[cfg(feature = "y2xx")]
pub(crate) use y2xx::*;
#[cfg(feature = "y2xx")]
pub(crate) use y216::*;
#[cfg(feature = "gray")]
#[allow(unused_imports)]
pub(crate) use ya8::*;
#[cfg(feature = "gray")]
#[allow(unused_imports)]
pub(crate) use ya16::*;
#[cfg(feature = "yuv-planar")]
pub(crate) use yuv_planar_8bit::*;
#[cfg(feature = "yuv-planar")]
pub(crate) use yuv_planar_16bit::*;
#[cfg(feature = "yuv-planar")]
pub(crate) use yuv_planar_high_bit::*;
#[cfg(feature = "y2xx")]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) unsafe fn load_endian_u16<const BE: bool>(ptr: *const u8) -> u16 {
let bytes = unsafe { [*ptr, *ptr.add(1)] };
if BE {
u16::from_be_bytes(bytes)
} else {
u16::from_le_bytes(bytes)
}
}
#[cfg(feature = "v210")]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) unsafe fn load_endian_u32<const BE: bool>(ptr: *const u8) -> u32 {
let bytes = unsafe { [*ptr, *ptr.add(1), *ptr.add(2), *ptr.add(3)] };
if BE {
u32::from_be_bytes(bytes)
} else {
u32::from_le_bytes(bytes)
}
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) fn clamp_u8(v: i32) -> u8 {
v.clamp(0, 255) as u8
}
#[cfg(any(feature = "yuv-planar", feature = "yuv-semi-planar", feature = "yuva",))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn load_u16<const BE: bool>(v: u16) -> u16 {
if BE { u16::from_be(v) } else { u16::from_le(v) }
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) fn q15_scale(sample: i32, scale_q15: i32) -> i32 {
(sample * scale_q15 + (1 << 14)) >> 15
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) fn q15_chroma(c_u: i32, u_d: i32, c_v: i32, v_d: i32) -> i32 {
(c_u * u_d + c_v * v_d + (1 << 14)) >> 15
}
#[cfg(any(
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) fn q15_chroma64(c_u: i32, u_d: i32, c_v: i32, v_d: i32) -> i32 {
let sum = (c_u as i64) * (u_d as i64) + (c_v as i64) * (v_d as i64);
((sum + (1 << 14)) >> 15) as i32
}
#[cfg(any(
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) fn q15_scale64(sample: i32, scale_q15: i32) -> i32 {
(((sample as i64) * (scale_q15 as i64) + (1 << 14)) >> 15) as i32
}
#[cfg(any(feature = "gray", feature = "yuv-planar", feature = "yuva"))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn bits_mask<const BITS: u32>() -> u16 {
((1u32 << BITS) - 1) as u16
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn chroma_bias<const BITS: u32>() -> i32 {
128i32 << (BITS - 8)
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn range_params_n<const BITS: u32, const OUT_BITS: u32>(
full_range: bool,
) -> (i32, i32, i32) {
let in_max: i64 = (1i64 << BITS) - 1;
let out_max: i64 = (1i64 << OUT_BITS) - 1;
if full_range {
let scale = ((out_max << 15) + in_max / 2) / in_max;
(0, scale as i32, scale as i32)
} else {
let y_off = 16i32 << (BITS - 8);
let y_range: i64 = 219i64 << (BITS - 8);
let c_range: i64 = 224i64 << (BITS - 8);
let y_scale = ((out_max << 15) + y_range / 2) / y_range;
let c_scale = ((out_max << 15) + c_range / 2) / c_range;
(y_off, y_scale as i32, c_scale as i32)
}
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
pub(super) struct Coefficients {
r_u: i32,
r_v: i32,
g_u: i32,
g_v: i32,
b_u: i32,
b_v: i32,
}
#[cfg(any(
feature = "v210",
feature = "y2xx",
feature = "yuv-444-packed",
feature = "yuv-packed",
feature = "yuv-planar",
feature = "yuv-semi-planar",
feature = "yuva",
))]
impl Coefficients {
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn for_matrix(m: ColorMatrix) -> Self {
match m {
ColorMatrix::Bt601 | ColorMatrix::Fcc => Self {
r_u: 0,
r_v: 45941,
g_u: -11277,
g_v: -23401,
b_u: 58065,
b_v: 0,
},
ColorMatrix::Bt709 => Self {
r_u: 0,
r_v: 51606,
g_u: -6136,
g_v: -15339,
b_u: 60808,
b_v: 0,
},
ColorMatrix::Bt2020Ncl => Self {
r_u: 0,
r_v: 48325,
g_u: -5391,
g_v: -18722,
b_u: 61653,
b_v: 0,
},
ColorMatrix::Smpte240m => Self {
r_u: 0,
r_v: 51642,
g_u: -7383,
g_v: -15620,
b_u: 59834,
b_v: 0,
},
ColorMatrix::YCgCo => Self {
r_u: -32768,
r_v: 32768,
g_u: 32768,
g_v: 0,
b_u: -32768,
b_v: -32768,
},
_ => Self {
r_u: 0,
r_v: 51606,
g_u: -6136,
g_v: -15339,
b_u: 60808,
b_v: 0,
},
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn r_u(&self) -> i32 {
self.r_u
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn r_v(&self) -> i32 {
self.r_v
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn g_u(&self) -> i32 {
self.g_u
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn g_v(&self) -> i32 {
self.g_v
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn b_u(&self) -> i32 {
self.b_u
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(super) const fn b_v(&self) -> i32 {
self.b_v
}
}
#[cfg(feature = "rgb")]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr_rgb_swap_row(input: &[u8], output: &mut [u8], width: usize) {
debug_assert!(input.len() >= width * 3, "input row too short");
debug_assert!(output.len() >= width * 3, "output row too short");
for x in 0..width {
let i = x * 3;
output[i] = input[i + 2];
output[i + 1] = input[i + 1];
output[i + 2] = input[i];
}
}
#[cfg(all(test, feature = "std"))]
mod tests;