Files
photocraft/crates/io/examples/big_psb_check.rs
David MannandClaude Opus 5.5 8eef90bf7e Tests: generated large-file fixtures and a P20 number (#5107)
photocraft_psd::fixtures (feature testgen) generates the FILE-216-2
fixtures at test time: a 20 MP layered PSD and a 150-layer A4 layout
(groups, masks, hidden layers, drop shadows, known merged colours), a
2.02 GB PSD just under Photoshop's cap and the 4-5 GB PSBs, streamed row
by row. io tests/large_files.rs opens, checks, saves and re-opens each
(the 2 GB PSD and 4.38 GB PSB are opt-in). The ui-egui large_file_bench
times opening the big two, wired to P20 and a new P60.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 17:58:38 +02:00

81 lines
3.1 KiB
Rust

//! Opens the files written by `photocraft-psd`'s `big_psb` example and checks their pixels.
//!
//! `cargo run --release -p photocraft-io --example big_psb_check -- <file.psb>...`
//!
//! The opt-in tests in `tests/large_files.rs` generate and check the same files.
use photocraft_psd::fixtures::sample;
fn main() {
for path in std::env::args().skip(1) {
let rle = path.contains("rle");
let t = std::time::Instant::now();
let bytes = match std::fs::read(&path) {
Ok(b) => b,
Err(e) => {
println!("{path}: read failed: {e}");
continue;
}
};
let read_s = t.elapsed().as_secs_f64();
let t = std::time::Instant::now();
let res = match photocraft_io::import(&path, &bytes) {
Ok(r) => r,
Err(e) => {
println!("{path}: import failed: {e}");
continue;
}
};
drop(bytes);
// With SAVE set: save as PSB, then check the re-opened file instead.
let res = if std::env::var_os("SAVE").is_some() {
let t = std::time::Instant::now();
let out = match photocraft_io::export(&res.document, "x.psb", &photocraft_io::ExportOptions::default()) {
Ok(o) => o,
Err(e) => {
println!("{path}: save failed: {e}");
continue;
}
};
println!("{path}: saved {:.2} GB in {:.1} s, warnings {:?}", out.bytes.len() as f64 / 1e9, t.elapsed().as_secs_f64(), out.warnings);
drop(res);
match photocraft_io::import("x.psb", &out.bytes) {
Ok(r) => r,
Err(e) => {
println!("{path}: re-open failed: {e}");
continue;
}
}
} else {
res
};
let doc = &res.document;
println!(
"{path}: read {read_s:.1} s, import {:.1} s, {}x{}, {} layer(s)",
t.elapsed().as_secs_f64(),
doc.size.width,
doc.size.height,
doc.layers.len()
);
for w in &res.warnings {
println!(" warning: {w}");
}
let Some(s) = doc.layers.first().and_then(|l| l.surface()) else {
println!(" FAIL: no pixel layer");
continue;
};
let (w, h) = (doc.size.width, doc.size.height);
let mut bad = 0;
let points = [(0, 0), (w - 1, 0), (0, h - 1), (w - 1, h - 1), (w / 2, h / 2), (w / 3, h * 2 / 3), (12_345 % w, (h - 7) % h)];
for &(x, y) in &points {
let got = s.pixel(x as i32, y as i32);
let want: Vec<f32> = (0..4).map(|c| f32::from(sample(x, y, c, rle)) / 255.0).collect();
if got.len() != 4 || got.iter().zip(&want).any(|(g, w)| (g - w).abs() > 1.0 / 510.0) {
bad += 1;
println!(" mismatch at ({x}, {y}): got {got:?}, want {want:?}");
}
}
println!(" {}", if bad == 0 { "OK: all sampled pixels match" } else { "FAIL" });
}
}