use std::sync::OnceLock;
const CHUNK: usize = 4096;
static DECODE_LUT: OnceLock<Box<[f32; 65536]>> = OnceLock::new();
#[doc(hidden)]
pub fn generate_decode_lut() -> Box<[f32; 65536]> {
let mut v: Vec<f32> = (0..65536u32).map(|i| i as f32 * (1.0 / 65535.0)).collect();
for chunk in v.chunks_mut(CHUNK) {
crate::simd::srgb_to_linear_slice(chunk);
}
v.into_boxed_slice().try_into().ok().unwrap()
}
#[inline]
pub(crate) fn decode_lut() -> &'static [f32; 65536] {
DECODE_LUT.get_or_init(generate_decode_lut)
}
static ENCODE_LUT: OnceLock<Box<[u16; 65537]>> = OnceLock::new();
pub(crate) const ENCODE_LUT_N: usize = 65537;
pub(crate) const ENCODE_SQRT_SCALE: f32 = (ENCODE_LUT_N - 1) as f32;
#[doc(hidden)]
pub fn generate_encode_lut() -> Box<[u16; 65537]> {
let mut lut: Vec<u16> = Vec::with_capacity(ENCODE_LUT_N);
let mut scratch = [0.0f32; CHUNK];
let mut i = 0u32;
while (i as usize) < ENCODE_LUT_N {
let n = CHUNK.min(ENCODE_LUT_N - i as usize);
for (j, s) in scratch[..n].iter_mut().enumerate() {
let t = (i + j as u32) as f32 * (1.0 / ENCODE_SQRT_SCALE);
*s = t * t;
}
crate::simd::linear_to_srgb_slice(&mut scratch[..n]);
for &s in &scratch[..n] {
lut.push((s * 65535.0 + 0.5) as u16);
}
i += n as u32;
}
lut.into_boxed_slice().try_into().ok().unwrap()
}
#[inline]
pub(crate) fn encode_lut() -> &'static [u16; 65537] {
ENCODE_LUT.get_or_init(generate_encode_lut)
}