#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LutPreviewViewConfig {
pub lut_size: usize,
pub intensity: f32,
pub enabled: bool,
pub show_before: bool,
}
impl Default for LutPreviewViewConfig {
fn default() -> Self {
LutPreviewViewConfig {
lut_size: 32,
intensity: 1.0,
enabled: true,
show_before: false,
}
}
}
#[derive(Debug, Clone)]
pub struct LutPreview {
pub config: LutPreviewViewConfig,
pub data: Vec<[f32; 3]>,
}
impl LutPreview {
pub fn new() -> Self {
let cfg = LutPreviewViewConfig::default();
let n = cfg.lut_size * cfg.lut_size * cfg.lut_size;
LutPreview {
config: cfg,
data: vec![[0.0; 3]; n],
}
}
}
impl Default for LutPreview {
fn default() -> Self {
LutPreview::new()
}
}
pub fn new_lut_preview() -> LutPreview {
LutPreview::new()
}
pub fn lpv2_set_intensity(lp: &mut LutPreview, intensity: f32) {
lp.config.intensity = intensity.clamp(0.0, 1.0);
}
pub fn lpv2_set_enabled(lp: &mut LutPreview, enabled: bool) {
lp.config.enabled = enabled;
}
pub fn lpv2_toggle_before(lp: &mut LutPreview) {
lp.config.show_before = !lp.config.show_before;
}
pub fn lpv2_sample(lp: &LutPreview, rgb: [f32; 3]) -> [f32; 3] {
let s = lp.config.lut_size as f32;
let idx_r = (rgb[0] * (s - 1.0)).clamp(0.0, s - 1.0) as usize;
let idx_g = (rgb[1] * (s - 1.0)).clamp(0.0, s - 1.0) as usize;
let idx_b = (rgb[2] * (s - 1.0)).clamp(0.0, s - 1.0) as usize;
let flat = idx_r + idx_g * lp.config.lut_size + idx_b * lp.config.lut_size * lp.config.lut_size;
let lut_val = lp.data.get(flat).copied().unwrap_or([0.0; 3]);
let t = lp.config.intensity;
[
rgb[0] * (1.0 - t) + lut_val[0] * t,
rgb[1] * (1.0 - t) + lut_val[1] * t,
rgb[2] * (1.0 - t) + lut_val[2] * t,
]
}
pub fn lpv2_to_json(lp: &LutPreview) -> String {
format!(
r#"{{"lut_size":{},"intensity":{:.4},"enabled":{}}}"#,
lp.config.lut_size, lp.config.intensity, lp.config.enabled
)
}
pub fn lpv2_data_size(lp: &LutPreview) -> usize {
lp.data.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_lut_size() {
let l = new_lut_preview();
assert_eq!(l.config.lut_size, 32 ,);
}
#[test]
fn test_data_size_cube() {
let l = new_lut_preview();
assert_eq!(
lpv2_data_size(&l),
32 * 32 * 32,
);
}
#[test]
fn test_set_intensity() {
let mut l = new_lut_preview();
lpv2_set_intensity(&mut l, 0.7);
assert!((l.config.intensity - 0.7).abs() < 1e-5, );
}
#[test]
fn test_set_intensity_clamps() {
let mut l = new_lut_preview();
lpv2_set_intensity(&mut l, 2.0);
assert!((l.config.intensity - 1.0).abs() < 1e-5, );
}
#[test]
fn test_set_enabled_false() {
let mut l = new_lut_preview();
lpv2_set_enabled(&mut l, false);
assert!(!l.config.enabled ,);
}
#[test]
fn test_toggle_before() {
let mut l = new_lut_preview();
lpv2_toggle_before(&mut l);
assert!(l.config.show_before ,);
}
#[test]
fn test_sample_at_zero_intensity_returns_original() {
let mut l = new_lut_preview();
lpv2_set_intensity(&mut l, 0.0);
let rgb = [0.5, 0.3, 0.7];
let out = lpv2_sample(&l, rgb);
assert!((out[0] - 0.5).abs() < 1e-5, );
}
#[test]
fn test_to_json_contains_lut_size() {
let l = new_lut_preview();
let j = lpv2_to_json(&l);
assert!(j.contains("lut_size") ,);
}
#[test]
fn test_default_intensity_one() {
let l = new_lut_preview();
assert!((l.config.intensity - 1.0).abs() < 1e-5, );
}
#[test]
fn test_default_enabled() {
let l = new_lut_preview();
assert!(l.config.enabled ,);
}
#[test]
fn test_sample_returns_three_components() {
let l = new_lut_preview();
let out = lpv2_sample(&l, [0.5, 0.5, 0.5]);
assert_eq!(out.len(), 3 ,);
}
}