Some code clean-up in the RGB32 encoding/decoding code.
This commit is contained in:
parent
d6ab9d06be
commit
bd6cf359b4
|
@ -33,8 +33,3 @@ fn fiddle_log2(n: f32) -> i32 {
|
||||||
use std::f32;
|
use std::f32;
|
||||||
((f32::to_bits(n) >> 23) & 0b1111_1111) as i32 - 127
|
((f32::to_bits(n) >> 23) & 0b1111_1111) as i32 - 127
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn clamp_0_1(n: f32) -> f32 {
|
|
||||||
n.max(0.0).min(1.0)
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
//! The Y-mantissa has an implicit leading one, giving 11 bits of
|
//! The Y-mantissa has an implicit leading one, giving 11 bits of
|
||||||
//! precision.
|
//! precision.
|
||||||
|
|
||||||
use crate::clamp_0_1;
|
|
||||||
|
|
||||||
const EXP_BIAS: i32 = 23;
|
const EXP_BIAS: i32 = 23;
|
||||||
|
|
||||||
/// The largest value this format can store.
|
/// The largest value this format can store.
|
||||||
|
@ -44,6 +42,30 @@ pub const MAX: f32 = ((1u64 << (63 - EXP_BIAS)) - (1 << (52 - EXP_BIAS))) as f32
|
||||||
/// of the over-all RGB color.
|
/// of the over-all RGB color.
|
||||||
pub const MIN: f32 = 1.0 / (1 << (EXP_BIAS - 2)) as f32;
|
pub const MIN: f32 = 1.0 / (1 << (EXP_BIAS - 2)) as f32;
|
||||||
|
|
||||||
|
/// The output c1 and c2 values should always be in the range [0, 1].
|
||||||
|
#[inline(always)]
|
||||||
|
fn rgb2ycc(rgb: (f32, f32, f32)) -> (f32, f32, f32) {
|
||||||
|
let rb = rgb.0 + rgb.2;
|
||||||
|
let y = (rb * 0.5) + rgb.1;
|
||||||
|
let c1 = rgb.1 / y;
|
||||||
|
let c2 = if rb > 0.0 { rgb.0 / rb } else { 0.5 };
|
||||||
|
|
||||||
|
(y, c1, c2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The input c1 and c2 values should always be in the range [0, 1].
|
||||||
|
#[inline(always)]
|
||||||
|
fn ycc2rgb(ycc: (f32, f32, f32)) -> (f32, f32, f32) {
|
||||||
|
let (y, c1, c2) = ycc;
|
||||||
|
|
||||||
|
let g = y * c1;
|
||||||
|
let rb = (y - g) * 2.0;
|
||||||
|
let r = rb * c2;
|
||||||
|
let b = rb - r;
|
||||||
|
|
||||||
|
(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
/// Encodes three floating point RGB values into a packed 32-bit format.
|
/// Encodes three floating point RGB values into a packed 32-bit format.
|
||||||
///
|
///
|
||||||
/// Warning: negative values and NaN's are _not_ supported. There are
|
/// Warning: negative values and NaN's are _not_ supported. There are
|
||||||
|
@ -68,14 +90,7 @@ pub fn encode(floats: (f32, f32, f32)) -> u32 {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Convert to Y/Green-Magenta/Red-Blue components.
|
// Convert to Y/Green-Magenta/Red-Blue components.
|
||||||
let u = floats.0 + floats.2;
|
let (y, c1, c2) = rgb2ycc(floats);
|
||||||
let y = (u * 0.5) + floats.1;
|
|
||||||
let green_magenta = clamp_0_1(floats.1 / y);
|
|
||||||
let red_blue = if u > 0.0 {
|
|
||||||
clamp_0_1(floats.0 / u)
|
|
||||||
} else {
|
|
||||||
0.5
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bit-fiddle to get the float components of Y.
|
// Bit-fiddle to get the float components of Y.
|
||||||
// This assumes we're working with a standard 32-bit IEEE float.
|
// This assumes we're working with a standard 32-bit IEEE float.
|
||||||
|
@ -84,8 +99,8 @@ pub fn encode(floats: (f32, f32, f32)) -> u32 {
|
||||||
let y_exp = ((y_ieee_bits >> 23) & 0b1111_1111) as i32 - 127;
|
let y_exp = ((y_ieee_bits >> 23) & 0b1111_1111) as i32 - 127;
|
||||||
|
|
||||||
// Encode Cg and Cr as 8-bit integers.
|
// Encode Cg and Cr as 8-bit integers.
|
||||||
let gm_8bit = ((green_magenta * 254.0) + 0.5) as u8;
|
let c1_8bit = ((c1 * 254.0) + 0.5) as u8;
|
||||||
let rb_8bit = ((red_blue * 254.0) + 0.5) as u8;
|
let c2_8bit = ((c2 * 254.0) + 0.5) as u8;
|
||||||
|
|
||||||
// Pack values into a u32 and return.
|
// Pack values into a u32 and return.
|
||||||
if y_exp <= (0 - EXP_BIAS) {
|
if y_exp <= (0 - EXP_BIAS) {
|
||||||
|
@ -102,12 +117,12 @@ pub fn encode(floats: (f32, f32, f32)) -> u32 {
|
||||||
// just go with white.
|
// just go with white.
|
||||||
0xffff7f7f
|
0xffff7f7f
|
||||||
} else {
|
} else {
|
||||||
0xffff0000 | ((gm_8bit as u32) << 8) | rb_8bit as u32
|
0xffff0000 | ((c1_8bit as u32) << 8) | c2_8bit as u32
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Common case.
|
// Common case.
|
||||||
let exp = (y_exp + EXP_BIAS) as u32;
|
let exp = (y_exp + EXP_BIAS) as u32;
|
||||||
(exp << 26) | (y_mantissa << 16) | ((gm_8bit as u32) << 8) | rb_8bit as u32
|
(exp << 26) | (y_mantissa << 16) | ((c1_8bit as u32) << 8) | c2_8bit as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,22 +142,17 @@ pub fn decode(packed_rgb: u32) -> (f32, f32, f32) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let green_magenta = {
|
let c1 = {
|
||||||
let gm_8bit = (packed_rgb >> 8) & 0xff;
|
let c1_8bit = (packed_rgb >> 8) & 0xff;
|
||||||
(gm_8bit as f32) * (1.0 / 254.0)
|
(c1_8bit as f32) * (1.0 / 254.0)
|
||||||
};
|
};
|
||||||
let red_blue = {
|
let c2 = {
|
||||||
let rb_8bit = packed_rgb & 0xff;
|
let c2_8bit = packed_rgb & 0xff;
|
||||||
(rb_8bit as f32) * (1.0 / 254.0)
|
(c2_8bit as f32) * (1.0 / 254.0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert back to RGB.
|
// Convert back to RGB.
|
||||||
let g = y * green_magenta;
|
ycc2rgb((y, c1, c2))
|
||||||
let u = (y - g) * 2.0;
|
|
||||||
let r = u * red_blue;
|
|
||||||
let b = u - r;
|
|
||||||
|
|
||||||
(r, g, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user