use std::fs; use std::path::Path; fn main() { let base_dir = "_tmp/psd_tunes/bevel_emboss_png_set"; let mut samples = vec![]; for entry in fs::read_dir(base_dir).unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().unwrap() == "png" { let name = path.file_stem().unwrap().to_str().unwrap().to_string(); samples.push((name, path)); } } let mut inner_mae = 0.0f64; let mut inner_count = 0usize; let mut outer_mae = 0.0f64; let mut outer_count = 0usize; let mut emboss_mae = 0.0f64; let mut emboss_count = 0usize; let lb = 5; let hl = 0.05; let sh = 2.5; let tilt = 0.05; println!("Evaluating {} samples", samples.len()); for (name, png_path) in samples { let psd_name = name.split('_').next().unwrap().to_string() + ".psd"; let psd_path = format!("_tmp/psd_tunes/{}", psd_name); if !Path::new(&psd_path).exists() { continue; } let target = image::open(&png_path).unwrap().to_rgba8(); let layers = hcie_psd::import_psd(std::path::Path::new(&psd_path)).unwrap(); let mut layer = None; for l in &layers { for e in &l.effects { if let hcie_protocol::effects::LayerEffect::BevelEmboss { enabled: true, .. } = e { layer = Some(l); break; } } if layer.is_some() { break; } } if layer.is_none() { continue; } let layer = layer.unwrap(); let (depth, size, soften, angle, altitude, direction, technique, style) = { let mut d = 0.0f32; let mut sz = 0.0f32; let mut sof = 0.0f32; let mut ang = 0.0f32; let mut alt = 0.0f32; let mut dir = hcie_protocol::effects::Direction::Up; let mut tech = hcie_protocol::effects::Technique::Smooth; let mut sty = hcie_protocol::effects::BevelStyle::InnerBevel; for e in &layer.effects { if let hcie_protocol::effects::LayerEffect::BevelEmboss { enabled: true, depth, size, soften, angle, altitude, direction, technique, style, .. } = e { d = *depth; sz = *size; sof = *soften; ang = *angle; alt = *altitude; dir = direction.clone(); tech = technique.clone(); sty = style.clone(); } } ( d, sz, sof, ang, alt, match dir { hcie_protocol::effects::Direction::Up => hcie_fx::types::Direction::Up, _ => hcie_fx::types::Direction::Down, }, match tech { hcie_protocol::effects::Technique::Smooth => hcie_fx::types::Technique::Smooth, hcie_protocol::effects::Technique::ChiselHard => { hcie_fx::types::Technique::ChiselHard } _ => hcie_fx::types::Technique::ChiselSoft, }, match sty { hcie_protocol::effects::BevelStyle::InnerBevel => { hcie_fx::types::BevelStyle::InnerBevel } hcie_protocol::effects::BevelStyle::OuterBevel => { hcie_fx::types::BevelStyle::OuterBevel } hcie_protocol::effects::BevelStyle::Emboss => hcie_fx::types::BevelStyle::Emboss, hcie_protocol::effects::BevelStyle::PillowEmboss => { hcie_fx::types::BevelStyle::PillowEmboss } _ => hcie_fx::types::BevelStyle::StrokeEmboss, }, ) }; let w = layer.width; let h = layer.height; let px = (w * h) as usize; let alpha: Vec = layer.pixels.iter().skip(3).step_by(4).copied().collect(); let (hl_buf, sh_buf) = hcie_fx::tuned::generate_bevel_tuned( &alpha, w, h, depth, size, soften, angle, altitude, &direction, &technique, &style, lb, hl, sh, 1.0, tilt, ); let mut out = layer.pixels.clone(); for i in 0..px { let dst = [out[i * 4], out[i * 4 + 1], out[i * 4 + 2], out[i * 4 + 3]]; let hl_src = [hl_buf[i * 4], hl_buf[i * 4 + 1], hl_buf[i * 4 + 2], hl_buf[i * 4 + 3]]; let sh_src = [sh_buf[i * 4], sh_buf[i * 4 + 1], sh_buf[i * 4 + 2], sh_buf[i * 4 + 3]]; let blended = hcie_blend::blend_pixels(dst, hl_src, hcie_blend::BlendMode::Screen, 0.75); let blended = hcie_blend::blend_pixels(blended, sh_src, hcie_blend::BlendMode::Multiply, 0.75); out[i * 4..i * 4 + 4].copy_from_slice(&blended); } let mut diff_sum = 0.0f64; let mut px_count = 0usize; let target_raw = target.as_raw(); let offset_x = (w as i32 - target.width() as i32) / 2; let offset_y = (h as i32 - target.height() as i32) / 2; for y in 0..target.height() { for x in 0..target.width() { let sx = x as i32 + offset_x; let sy = y as i32 + offset_y; if sx >= 0 && sx < w as i32 && sy >= 0 && sy < h as i32 { let s_idx = ((sy as usize) * w as usize + (sx as usize)) * 4; let t_idx = ((y as usize) * target.width() as usize + (x as usize)) * 4; let src_a = layer.pixels[s_idx + 3]; if src_a > 0 { diff_sum += (out[s_idx] as f64 - target_raw[t_idx] as f64).abs(); diff_sum += (out[s_idx + 1] as f64 - target_raw[t_idx + 1] as f64).abs(); diff_sum += (out[s_idx + 2] as f64 - target_raw[t_idx + 2] as f64).abs(); px_count += 3; } } } } if px_count > 0 { let mae = diff_sum / px_count as f64; if name.contains("InnerBevel") { inner_mae += mae; inner_count += 1; } if name.contains("OuterBevel") { outer_mae += mae; outer_count += 1; } if name.contains("Emboss") { emboss_mae += mae; emboss_count += 1; } } } if inner_count > 0 { println!( "Inner Bevel MAE: {:.4} ({} samples)", inner_mae / inner_count as f64, inner_count ); } if outer_count > 0 { println!( "Outer Bevel MAE: {:.4} ({} samples)", outer_mae / outer_count as f64, outer_count ); } if emboss_count > 0 { println!( "Emboss MAE: {:.4} ({} samples)", emboss_mae / emboss_count as f64, emboss_count ); } }