mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-27 03:17:05 -06:00
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>
81 lines
3.1 KiB
Rust
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" });
|
|
}
|
|
}
|