mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-29 12:27:38 -06:00
Blurs run as box passes now filter the whole area at once instead of tile by tile: the horizontal passes run over the source rows only and the vertical passes over column strips, with the canvas edge repeated virtually instead of materialising a 3-sigma margin around every tile (at radius 500 that margin was ~25 MP of floats per 4 MP tile, copied and transposed several times). The results are written to the layer's tile columns in parallel. Output matches the previous running sums (8-bit: identical except 114 of 2.1 M samples one level apart; 16-bit: within 2/65535) and a direct-convolution oracle at every depth. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
29 lines
1.4 KiB
Rust
29 lines
1.4 KiB
Rust
//! Timing: Gaussian Blur radius 10 on a 6016×6016 RGBA8 layer, as a document layer filling the
|
||
//! canvas is filtered (edges repeated at the canvas edge).
|
||
//! `cargo run --release -p photocraft-algo --example bench_gaussian [-- <size> <radius>]`
|
||
use photocraft_algo::{FilterParams, apply_in, output_area};
|
||
use photocraft_color::PixelFormat;
|
||
use photocraft_geom::Rect;
|
||
use photocraft_raster::Surface;
|
||
|
||
fn main() {
|
||
let n: i32 = std::env::args().nth(1).and_then(|v| v.parse().ok()).unwrap_or(6016);
|
||
let radius: f32 = std::env::args().nth(2).and_then(|v| v.parse().ok()).unwrap_or(10.0);
|
||
let r = Rect::new(0, 0, n, n);
|
||
let mut s = Surface::new(PixelFormat::RGBA8);
|
||
let row: Vec<u8> = (0..n).flat_map(|x| [(x % 256) as u8, (x / 7 % 256) as u8, 128, 255]).collect();
|
||
let bytes: Vec<u8> = (0..n).flat_map(|_| row.iter().copied()).collect();
|
||
s.write_interleaved(r, &bytes);
|
||
let p = FilterParams::GaussianBlur { radius };
|
||
let area = output_area(&p, s.content_bounds(), r, None).intersect(&r);
|
||
// Best of a few runs (the first also pays for page faults).
|
||
let mut dt = std::time::Duration::MAX;
|
||
let mut out = s.clone();
|
||
for _ in 0..5 {
|
||
let t = std::time::Instant::now();
|
||
out = apply_in(&s, &p, area, r, None, r);
|
||
dt = dt.min(t.elapsed());
|
||
}
|
||
println!("gaussian radius {radius} on {n}x{n} RGBA8: {:.2?} ({} tiles)", dt, out.tile_count());
|
||
}
|