Added a FloatLuv decode function to decode to Yuv instead of XYZ.
This is useful because it's super fast, and chromaticity lookups are typical for spectral upsampling anyway, so this will likely enable cutting out a bunch of unecessary intermediate calculations.
This commit is contained in:
parent
0ba1acc42d
commit
05f9621ac5
|
@ -105,6 +105,16 @@ fn fluv32_decode_1000_values(bench: &mut Bencher) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fluv32_decode_yuv_1000_values(bench: &mut Bencher) {
|
||||||
|
let mut rng = SmallRng::from_entropy();
|
||||||
|
bench.iter(|| {
|
||||||
|
let v = rng.gen::<u32>();
|
||||||
|
for _ in 0..1000 {
|
||||||
|
black_box(fluv32::decode_yuv(black_box(v)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//----
|
//----
|
||||||
|
|
||||||
benchmark_group!(
|
benchmark_group!(
|
||||||
|
@ -117,5 +127,6 @@ benchmark_group!(
|
||||||
signed48_decode_1000_values,
|
signed48_decode_1000_values,
|
||||||
fluv32_encode_1000_values,
|
fluv32_encode_1000_values,
|
||||||
fluv32_decode_1000_values,
|
fluv32_decode_1000_values,
|
||||||
|
fluv32_decode_yuv_1000_values,
|
||||||
);
|
);
|
||||||
benchmark_main!(benches);
|
benchmark_main!(benches);
|
||||||
|
|
|
@ -46,7 +46,9 @@
|
||||||
#![allow(clippy::cast_lossless)]
|
#![allow(clippy::cast_lossless)]
|
||||||
|
|
||||||
const EXP_BIAS: i32 = 27;
|
const EXP_BIAS: i32 = 27;
|
||||||
const UV_SCALE: f32 = 410.0;
|
|
||||||
|
/// The scale factor of the quantized UV components.
|
||||||
|
pub const UV_SCALE: f32 = 410.0;
|
||||||
|
|
||||||
/// Largest representable Y component.
|
/// Largest representable Y component.
|
||||||
pub const Y_MAX: f32 = ((1u64 << (64 - EXP_BIAS)) - (1u64 << (64 - EXP_BIAS - 11))) as f32;
|
pub const Y_MAX: f32 = ((1u64 << (64 - EXP_BIAS)) - (1u64 << (64 - EXP_BIAS - 11))) as f32;
|
||||||
|
@ -143,6 +145,27 @@ pub fn decode(fluv32: u32) -> (f32, f32, f32) {
|
||||||
(x, y, z)
|
(x, y, z)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decodes from 32-bit FloatLuv to Yuv.
|
||||||
|
///
|
||||||
|
/// The Y component is the luminance, and is simply the Y from CIE XYZ.
|
||||||
|
///
|
||||||
|
/// The u and v components are the CIE LUV u' and v' chromaticity coordinates,
|
||||||
|
/// but returned as `u8`s, and scaled by `UV_SCALE` to fit the range 0-255.
|
||||||
|
#[inline]
|
||||||
|
pub fn decode_yuv(fluv32: u32) -> (f32, u8, u8) {
|
||||||
|
// Check for zero.
|
||||||
|
if fluv32 & 0xffff0000 == 0 {
|
||||||
|
return (0.0, (fluv32 >> 8) as u8, fluv32 as u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate y.
|
||||||
|
let l_exp = fluv32 >> 26;
|
||||||
|
let l_mant = (fluv32 >> 16) & 0x3ff;
|
||||||
|
let y = f32::from_bits(((l_exp + 127 - EXP_BIAS as u32) << 23) | (l_mant << 13));
|
||||||
|
|
||||||
|
(y, (fluv32 >> 8) as u8, fluv32 as u8)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -231,6 +254,14 @@ mod tests {
|
||||||
assert_eq!(2048.0, round_trip(fs).1);
|
assert_eq!(2048.0, round_trip(fs).1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decode_yuv_01() {
|
||||||
|
let fs = (1.0, 1.0, 1.0);
|
||||||
|
let a = encode(fs);
|
||||||
|
|
||||||
|
assert_eq!((1.0, 0x56, 0xc2), decode_yuv(a));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn saturate_y() {
|
fn saturate_y() {
|
||||||
let fs = (1.0e+20, 1.0e+20, 1.0e+20);
|
let fs = (1.0e+20, 1.0e+20, 1.0e+20);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user