Files
hcie-rust-v3.05/hcie-io/examples/generate_test_psds.rs
T

125 lines
4.6 KiB
Rust
Raw Normal View History

2026-07-09 02:59:53 +03:00
use hcie_protocol::Layer;
use hcie_protocol::effects::LayerEffect;
use std::path::Path;
fn main() {
let output_dir = Path::new("_tmp/psd_test_output");
std::fs::create_dir_all(output_dir).ok();
println!("=== Generate Test PSDs ===");
// Test 1: Simple layer, no effects
{
let layers = vec![
Layer::new_blank("Background", 256, 256),
];
let composited = vec![255u8; 256 * 256 * 4];
let path = output_dir.join("test_simple.psd");
hcie_psd::save_psd(&layers, 256, 256, &composited, &path).unwrap();
verify_psd(&path, "Simple (no effects)");
}
// Test 2: Layer with InnerShadow effect
{
let mut layer = Layer::new_blank("Effect Layer", 256, 256);
layer.effects.push(LayerEffect::InnerShadow {
enabled: true,
blend_mode: "normal".to_string(),
color: [0, 0, 0, 255],
opacity: 0.75,
angle: 120.0,
distance: 10.0,
choke: 5.0,
size: 15.0,
noise: 0.0,
contour: None,
});
let layers = vec![layer];
let composited = vec![255u8; 256 * 256 * 4];
let path = output_dir.join("test_inner_shadow.psd");
hcie_psd::save_psd(&layers, 256, 256, &composited, &path).unwrap();
verify_psd(&path, "InnerShadow");
}
// Test 3: Two layers, one with effects
{
let bg = Layer::new_blank("Background", 256, 256);
let mut fg = Layer::new_blank("Foreground", 256, 256);
fg.effects.push(LayerEffect::DropShadow {
enabled: true,
blend_mode: "normal".to_string(),
color: [0, 0, 0, 255],
opacity: 0.5,
angle: 120.0,
distance: 5.0,
spread: 0.0,
size: 10.0,
noise: 0.0,
contour: None,
});
let layers = vec![bg, fg];
let composited = vec![255u8; 256 * 256 * 4];
let path = output_dir.join("test_two_layers.psd");
hcie_psd::save_psd(&layers, 256, 256, &composited, &path).unwrap();
verify_psd(&path, "Two layers + DropShadow");
}
// Test 4: Roundtrip the reference PSD
{
let ref_path = Path::new("_images/_psd_stil_test/inner_shadow/black_triangle_green_inner_shadow_normal_blend.psd");
if ref_path.exists() {
let layers = hcie_psd::import_psd(ref_path).unwrap();
let orig_bytes = std::fs::read(ref_path).unwrap();
let psd = hcie_psd::Psd::from_bytes(&orig_bytes).unwrap();
let composited = psd.rgba();
let path = output_dir.join("test_roundtrip.psd");
hcie_psd::save_psd(&layers, psd.width(), psd.height(), &composited, &path).unwrap();
verify_psd(&path, "Roundtrip from reference PSD");
}
}
// Test 5: Verify pixel data round-trip
{
println!("\n=== Pixel Data Verification ===");
let ref_path = Path::new("_images/_psd_stil_test/inner_shadow/black_triangle_green_inner_shadow_normal_blend.psd");
if ref_path.exists() {
let orig_bytes = std::fs::read(ref_path).unwrap();
let orig_psd = hcie_psd::Psd::from_bytes(&orig_bytes).unwrap();
let orig_rgba = orig_psd.rgba();
let saved_path = output_dir.join("test_roundtrip.psd");
let saved_bytes = std::fs::read(&saved_path).unwrap();
let saved_psd = hcie_psd::Psd::from_bytes(&saved_bytes).unwrap();
let saved_rgba = saved_psd.rgba();
let mut diff_count = 0;
let mut max_diff: u8 = 0;
for i in 0..orig_rgba.len().min(saved_rgba.len()) {
let d = (orig_rgba[i] as i16 - saved_rgba[i] as i16).unsigned_abs() as u8;
if d > 0 {
diff_count += 1;
max_diff = max_diff.max(d);
}
}
println!("Original RGBA: {} bytes", orig_rgba.len());
println!("Saved RGBA: {} bytes", saved_rgba.len());
println!("Differing bytes: {} / {}", diff_count, orig_rgba.len());
println!("Max per-byte diff: {}", max_diff);
println!("MAE: {:.2}", diff_count as f64 / orig_rgba.len() as f64);
}
}
}
fn verify_psd(path: &Path, label: &str) {
let bytes = std::fs::read(path).unwrap();
match hcie_psd::Psd::from_bytes(&bytes) {
Ok(psd) => {
println!("[OK] {}: {} bytes, {}x{}, {} layers",
label, bytes.len(), psd.width(), psd.height(), psd.layers().len());
}
Err(e) => {
println!("[FAIL] {}: {} bytes, error: {:?}", label, bytes.len(), e);
}
}
}