Files
photocraft/crates/engine/examples/retouch_bench.rs
T
Brandon ThomasandClaude Opus 5.5 f7eb6ea9e7 Format: adopt the craft-family rustfmt.toml and format the workspace
CI's `cargo fmt --all -- --check` has failed on every run because the
repo had no rustfmt config and was never formatted. Use the same settings
as EffectCraft/FilmCraft (max_width 160, use_small_heuristics Max), which
also keeps the churn small. Formatting only; no code changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:31:17 -04:00

61 lines
3.1 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Timing: Healing Brush and Spot Healing dab cost on a 6016×6016 document.
//! `cargo run --release -p photocraft-engine --example retouch_bench [side] [depth]`
//!
//! Each measurement is one single-dab stroke through the full command path (`Session::execute`:
//! undo snapshot, source sampling, solve/fill, composite), on a textured area of the canvas.
use std::time::Instant;
use photocraft_engine::Session;
use photocraft_geom::Rect;
use serde_json::json;
fn main() {
let side: u32 = std::env::args().nth(1).and_then(|v| v.parse().ok()).unwrap_or(6016);
let depth: u64 = std::env::args().nth(2).and_then(|v| v.parse().ok()).unwrap_or(8);
let mut s = Session::new();
s.execute("file.new", json!({"width": side, "height": side, "depth": depth})).unwrap();
// Texture a 2048² area in the middle (the rest stays white) with a gradient, noise and blemishes.
let area = Rect::new(2000, 2000, 4048, 4048).intersect(&Rect::new(0, 0, side as i32, side as i32));
s.edit("texture", |doc, active| {
let surf = doc.layer_mut(active.unwrap()).unwrap().surface_mut().unwrap();
let fmt = surf.format();
let mut data = Vec::with_capacity(area.width() as usize * area.height() as usize * 4);
for y in area.y0..area.y1 {
for x in area.x0..area.x1 {
let n = ((x.wrapping_mul(73_856_093) ^ y.wrapping_mul(19_349_663)) as u32 % 1000) as f32 / 1000.0 * 0.08 - 0.04;
let blemish = (x % 400 - 200).abs() < 8 && (y % 400 - 200).abs() < 8;
let v =
if blemish { [0.05, 0.05, 0.05, 1.0] } else { [0.3 + 0.0002 * x as f32 + n, 0.4 + ((x + y) as f32 * 0.01).sin() * 0.1 + n, 0.5 + n, 1.0] };
data.extend(photocraft_raster::from_rgba(&fmt, v));
}
}
surf.write_region(area, &data);
Ok(())
})
.unwrap();
println!("document {side}x{side}, {depth}-bit RGB");
let mut k = 0;
let mut spot = || {
k += 1;
(2200 + (k % 4) * 400, 2200 + (k / 4 % 4) * 400)
};
for size in [50.0, 100.0, 200.0, 300.0] {
let (x, y) = spot();
let t = Instant::now();
s.execute("paint.healingBrush", json!({"points": [[x, y]], "offset": [-150, -130], "size": size, "hardness": 50})).unwrap();
println!("healingBrush size {size:>4}: {:>8.1?}", t.elapsed());
}
for kind in ["contentAware", "proximityMatch", "createTexture"] {
for size in [50.0, 100.0, 200.0, 300.0] {
let (x, y) = spot();
let t = Instant::now();
s.execute("paint.spotHealing", json!({"points": [[x, y]], "size": size, "hardness": 50, "type": kind})).unwrap();
println!("spotHealing {kind:<15} size {size:>4}: {:>8.1?}", t.elapsed());
}
}
// A short multi-dab heal stroke (spacing 25 %): the whole stroke is solved at once.
let t = Instant::now();
s.execute("paint.healingBrush", json!({"points": [[2300, 3500], [2700, 3500]], "offset": [0, -300], "size": 100, "hardness": 50})).unwrap();
println!("healingBrush stroke 400 px long, size 100: {:.1?}", t.elapsed());
}