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

312 lines
11 KiB
Rust

use hcie_protocol::Layer;
use hcie_protocol::effects::{LayerEffect, BevelStyle, Technique, Direction, StrokePosition, StrokeFillType, GradientDef};
use std::path::Path;
fn create_layer(name: &str, w: u32, h: u32, fill_r: u8, fill_g: u8, fill_b: u8) -> Layer {
create_layer_at(name, w, h, fill_r, fill_g, fill_b, w / 2, h / 2)
}
fn create_layer_at(name: &str, w: u32, h: u32, fill_r: u8, fill_g: u8, fill_b: u8, offset_x: u32, offset_y: u32) -> Layer {
let px_count = (w * h) as usize;
let mut pixels = vec![0u8; px_count * 4];
for y in 0..h {
for x in 0..w {
let idx = (y * w + x) as usize * 4;
let cx = offset_x as f32;
let cy = offset_y as f32;
let rx = (w as f32 * 0.2) + (y as f32 * 0.1).sin() * 20.0;
let ry = (h as f32 * 0.2) + (x as f32 * 0.1).cos() * 20.0;
let dx = (x as f32 - cx).abs();
let dy = (y as f32 - cy).abs();
if dx < rx && dy < ry {
pixels[idx] = fill_r;
pixels[idx + 1] = fill_g;
pixels[idx + 2] = fill_b;
pixels[idx + 3] = 255;
}
}
}
Layer::from_rgba(name, w, h, pixels)
}
fn create_layer_with_effect(name: &str, w: u32, h: u32, effect: LayerEffect) -> Layer {
let mut layer = create_layer(name, w, h, 120, 140, 200);
layer.effects = vec![effect];
layer
}
fn save_png(path: &str, pixels: &[u8], w: u32, h: u32) {
if let Some(img) = image::ImageBuffer::<image::Rgba<u8>, _>::from_raw(w, h, pixels.to_vec()) {
let _ = img.save(path);
}
}
fn main() {
let out_dir = "_images/_psd_stil_test";
let w: u32 = 512;
let h: u32 = 512;
let tests: Vec<(&str, Layer)> = vec![
(
"fx_drop_shadow",
create_layer_with_effect("Drop Shadow", w, h, LayerEffect::DropShadow {
enabled: true,
blend_mode: "Multiply".to_string(),
color: [0, 0, 0, 255],
opacity: 0.75,
angle: 120.0,
distance: 15.0,
spread: 0.0,
size: 25.0,
noise: 0.0,
contour: None,
})
),
(
"fx_inner_shadow",
create_layer_with_effect("Inner Shadow", w, h, LayerEffect::InnerShadow {
enabled: true,
blend_mode: "Multiply".to_string(),
color: [0, 0, 0, 255],
opacity: 0.75,
angle: 120.0,
distance: 15.0,
choke: 0.0,
size: 25.0,
noise: 0.0,
contour: None,
})
),
(
"fx_outer_glow",
create_layer_with_effect("Outer Glow", w, h, LayerEffect::OuterGlow {
enabled: true,
blend_mode: "Normal".to_string(),
color: [255, 100, 0, 255],
opacity: 0.75,
spread: 0.0,
size: 30.0,
noise: 0.0,
contour: None,
})
),
(
"fx_inner_glow",
create_layer_with_effect("Inner Glow", w, h, LayerEffect::InnerGlow {
enabled: true,
blend_mode: "Normal".to_string(),
color: [0, 200, 255, 255],
opacity: 0.75,
choke: 0.0,
size: 15.0,
noise: 0.0,
contour: None,
source: 0,
})
),
(
"fx_bevel_inner",
create_layer_with_effect("Bevel Inner", w, h, LayerEffect::BevelEmboss {
enabled: true,
style: BevelStyle::InnerBevel,
technique: Technique::Smooth,
depth: 100.0,
direction: Direction::Up,
size: 15.0,
soften: 0.0,
angle: 120.0,
altitude: 30.0,
highlight_blend: "Screen".to_string(),
highlight_color: [255, 255, 255, 255],
highlight_opacity: 0.75,
shadow_blend: "Multiply".to_string(),
shadow_color: [0, 0, 0, 255],
shadow_opacity: 0.75,
contour: None,
})
),
(
"fx_bevel_outer",
create_layer_with_effect("Bevel Outer", w, h, LayerEffect::BevelEmboss {
enabled: true,
style: BevelStyle::OuterBevel,
technique: Technique::Smooth,
depth: 100.0,
direction: Direction::Up,
size: 15.0,
soften: 0.0,
angle: 120.0,
altitude: 30.0,
highlight_blend: "Screen".to_string(),
highlight_color: [255, 255, 255, 255],
highlight_opacity: 0.75,
shadow_blend: "Multiply".to_string(),
shadow_color: [0, 0, 0, 255],
shadow_opacity: 0.75,
contour: None,
})
),
(
"fx_emboss",
create_layer_with_effect("Emboss", w, h, LayerEffect::BevelEmboss {
enabled: true,
style: BevelStyle::Emboss,
technique: Technique::Smooth,
depth: 100.0,
direction: Direction::Up,
size: 15.0,
soften: 0.0,
angle: 120.0,
altitude: 30.0,
highlight_blend: "Screen".to_string(),
highlight_color: [255, 255, 255, 255],
highlight_opacity: 0.75,
shadow_blend: "Multiply".to_string(),
shadow_color: [0, 0, 0, 255],
shadow_opacity: 0.75,
contour: None,
})
),
(
"fx_pillow_emboss",
create_layer_with_effect("Pillow Emboss", w, h, LayerEffect::BevelEmboss {
enabled: true,
style: BevelStyle::PillowEmboss,
technique: Technique::Smooth,
depth: 100.0,
direction: Direction::Up,
size: 15.0,
soften: 0.0,
angle: 120.0,
altitude: 30.0,
highlight_blend: "Screen".to_string(),
highlight_color: [255, 255, 255, 255],
highlight_opacity: 0.75,
shadow_blend: "Multiply".to_string(),
shadow_color: [0, 0, 0, 255],
shadow_opacity: 0.75,
contour: None,
})
),
(
"fx_satin",
create_layer_with_effect("Satin", w, h, LayerEffect::Satin {
enabled: true,
blend_mode: "Multiply".to_string(),
color: [0, 0, 0, 255],
opacity: 0.5,
angle: 120.0,
distance: 15.0,
size: 25.0,
invert: false,
contour: None,
})
),
(
"fx_color_overlay",
create_layer_with_effect("Color Overlay", w, h, LayerEffect::ColorOverlay {
enabled: true,
blend_mode: "Normal".to_string(),
color: [255, 0, 180, 255],
opacity: 0.6,
})
),
(
"fx_gradient_overlay",
create_layer_with_effect("Gradient Overlay", w, h, LayerEffect::GradientOverlay {
enabled: true,
blend_mode: "Normal".to_string(),
opacity: 0.8,
angle: 90.0,
scale: 100.0,
gradient: GradientDef {
color_stops: vec![
(0, [255, 80, 0, 255]),
(4096, [255, 220, 0, 255]),
],
transparency_stops: vec![
(0, 100),
(4096, 100),
],
midpoint: 50.0,
angle: 90.0,
scale: 100.0,
gradient_type: 0,
},
})
),
(
"fx_pattern_overlay",
create_layer_with_effect("Pattern Overlay", w, h, LayerEffect::PatternOverlay {
enabled: true,
blend_mode: "Normal".to_string(),
opacity: 0.6,
scale: 100.0,
pattern_id: "b4d43394-d71c-11e5-b1ae-a548a96ef5f9".to_string(),
})
),
(
"fx_stroke_inside",
create_layer_with_effect("Stroke Inside", w, h, LayerEffect::Stroke {
enabled: true,
position: StrokePosition::Inside,
fill_type: StrokeFillType::Color,
blend_mode: "Normal".to_string(),
opacity: 1.0,
size: 12.0,
color: [255, 220, 0, 255],
})
),
(
"fx_stroke_center",
create_layer_with_effect("Stroke Center", w, h, LayerEffect::Stroke {
enabled: true,
position: StrokePosition::Center,
fill_type: StrokeFillType::Color,
blend_mode: "Normal".to_string(),
opacity: 1.0,
size: 12.0,
color: [255, 220, 0, 255],
})
),
(
"fx_stroke_outside",
create_layer_with_effect("Stroke Outside", w, h, LayerEffect::Stroke {
enabled: true,
position: StrokePosition::Outside,
fill_type: StrokeFillType::Color,
blend_mode: "Normal".to_string(),
opacity: 1.0,
size: 12.0,
color: [255, 220, 0, 255],
})
),
];
// Generate PLAIN PSDs (no effects) — user will apply effects manually in Photopea
let effect_labels: Vec<&str> = tests.iter().map(|(n, _)| *n).collect();
for name in &effect_labels {
let layer = create_layer(name, w, h, 120, 140, 200);
let composited = layer.pixels.clone();
let plain_path = format!("{}/plain_{}.psd", out_dir, name);
if let Err(e) = hcie_psd::save_psd(&[layer.clone()], w, h, &composited, Path::new(&plain_path)) {
eprintln!("Failed to save {}: {}", name, e);
} else {
println!("Generated: {}", plain_path);
}
}
// Also generate baseline with no effects
let baseline = create_layer("Baseline", w, h, 100, 180, 140);
let composited = baseline.pixels.clone();
let path = format!("{}/fx_baseline.psd", out_dir);
if let Err(e) = hcie_psd::save_psd(&[baseline.clone()], w, h, &composited, Path::new(&path)) {
eprintln!("Failed to save fx_baseline: {}", e);
} else {
println!("Generated: {}", path);
}
let png_path = format!("{}/fx_baseline.png", out_dir);
save_png(&png_path, &composited, w, h);
println!(" PNG: {}", png_path);
}