use std::fs; use hcie_io::psd::PsdLoader; use hcie_fx::generate_bevel_tuned; use image::{RgbaImage, GenericImageView}; 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.0; let mut inner_count = 0; let mut outer_mae = 0.0; let mut outer_count = 0; let mut emboss_mae = 0.0; let mut emboss_count = 0; let lb = 15; let hl = 1.0; let sh = 1.0; 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 mut psd = PsdLoader::new(&psd_path).unwrap(); let layers = psd.get_layers(); let mut layer = None; for l in layers { if l.effects.is_some() && l.effects.as_ref().unwrap().bevel_emboss.is_some() { layer = Some(l); break; } } if layer.is_none() { continue; } let layer = layer.unwrap(); let fx = layer.effects.unwrap(); let bevel = fx.bevel_emboss.unwrap(); use hcie_fx::types::*; let mut style = BevelStyle::InnerBevel; if name.contains("InnerBevel") { style = BevelStyle::InnerBevel; } if name.contains("OuterBevel") { style = BevelStyle::OuterBevel; } if name.contains("Emboss") { style = BevelStyle::Emboss; } let (out_w, out_h, out_pixels) = generate_bevel_tuned( layer.width as usize, layer.height as usize, &layer.rgba, bevel.size as f32, bevel.depth as f32, bevel.soften as f32, bevel.angle as f32, bevel.altitude as f32, style, lb, hl, sh ); let mut diff_sum = 0.0; let mut px_count = 0; let offset_x = (out_w as i32 - target.width() as i32) / 2; let offset_y = (out_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 < out_w as i32 && sy >= 0 && sy < out_h as i32 { let s_idx = ((sy as usize) * out_w + (sx as usize)) * 4; let t_idx = ((y as usize) * target.width() as usize + (x as usize)) * 4; let src_a = layer.rgba[s_idx+3]; if src_a > 0 { diff_sum += (out_pixels[s_idx] as f32 - target[t_idx] as f32).abs(); diff_sum += (out_pixels[s_idx+1] as f32 - target[t_idx+1] as f32).abs(); diff_sum += (out_pixels[s_idx+2] as f32 - target[t_idx+2] as f32).abs(); px_count += 3; // R, G, B } } } } if px_count > 0 { let mae = diff_sum / px_count as f32; 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; } } } println!("Inner Bevel MAE: {:.4} ({} samples)", inner_mae / inner_count as f32, inner_count); println!("Outer Bevel MAE: {:.4} ({} samples)", outer_mae / outer_count as f32, outer_count); println!("Emboss MAE: {:.4} ({} samples)", emboss_mae / emboss_count as f32, emboss_count); }