mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-12 11:13:55 +00:00
* craft-psd: raise the 64-bit .abr sample budget to 2 GiB Photoshop writes brush packs up to its 2 GB .abr limit; a 1 GiB budget refused valid packs over it. 32-bit targets keep 512 MiB. Ported from storytold/photocraft#13282 (photocraft#5949). * craft-psd: FELS is checked and transcoded as filter effects FELS holds the smart-filter masks of linked smart objects in the FEid layout. check_structure now re-parses it, and a layered TIFF transcodes it field by field: a little-endian save dropped the block as unknown. Ported from storytold/photocraft#8275 (photocraft#8260); the test is new. * craft-psd: a layered TIFF keeps external smart-object links An external linked file (liFE) holds the descriptor of its link, and from version 3 its bytes. The TIFF transcoder skipped both, so the record failed to convert and a little-endian save dropped the lnkE block. Ported from storytold/photocraft#6072; the test is new. * craft-psd: the example and the save test write into fresh private directories The big_psb example and the save_and_open test used a predictable temp directory name, which a planted directory or symlink could take over. They now create a new owner-only directory, and the example removes a half-written fixture from its own default folder. Ported from storytold/photocraft#13266 (its crates/psd part). * craft-psd: the pixel preflight sees the merged image's compression and size from_bytes_and_merged_preflight_info and from_source_and_merged_preflight_info hand the preflight the merged image's compression and encoded length before the image is read, so a caller can estimate the memory a decode will need (an opaque RGB image stored raw needs no inflate buffer). A missing compression field is None, and a refusal takes precedence over it. Ported from storytold/photocraft#11288 (its crates/psd part); the test is new. * craft-psd: typed layer selection ids (resource 1069) ResourceData::LayerSelectionIds: the selected layers' ids in stored order, duplicates and zero kept. The count is checked against the whole payload before anything is allocated; truncated or trailing data is malformed, not a partial selection. Ported from storytold/photocraft#10268 (its crates/psd part). * craft-psd: README matches the code The typed blocks tsly, lmgm and vmgm, vector masks and slices typed by path and slices, the resources ImageResource::parsed types, the ATN round-trip caveats and version-12 reading, and the corpus test's known-bad file. Ported from storytold/photocraft#11600 (its crates/psd part), with the resource list brought up to date. * craft-psd: atn_dump escapes control characters from the file A set's names, warnings, paths and errors are printed with control characters escaped, so a file cannot drive the terminal. Ported from storytold/photocraft#11218 (merged into PhotoCraft's copy after craft-psd was moved). * craft-psd: the .abr budget test checks the 64-bit bound at compile time clippy refuses an assertion whose value is constant. --------- Co-authored-by: rgoza1996 <97354241+rgoza1996@users.noreply.github.com> Co-authored-by: Korg1ch <57859048+Korg1ch@users.noreply.github.com> Co-authored-by: PJaYOfficial <1597623+PJaYOfficial@users.noreply.github.com> Co-authored-by: acilione <antoninocilione96@gmail.com> Co-authored-by: kirubhakaran12 <27127513+kirubhakaran12@users.noreply.github.com> Co-authored-by: Nicolas Falesy <112726756+nicolasfalesy@users.noreply.github.com>
56 lines
2.6 KiB
Rust
56 lines
2.6 KiB
Rust
//! Writes multi-gigabyte PSB files (and the 2 GB PSD) for large-file tests (photocraft#375, photocraft#216), straight
|
|
//! from the Adobe PSD spec and independent of this crate's writer, so the fixtures don't inherit
|
|
//! its limits. The generator is `craft_psd::fixtures` (feature `testgen`).
|
|
//!
|
|
//! `cargo run --release -p craft-psd --example big_psb -- <out dir> [case...]`
|
|
//!
|
|
//! Every sample follows `fixtures::sample`, so a reader can check any pixel without the file. RLE
|
|
//! cases keep each row constant (tiny files, full decoded size); raw cases vary along x too.
|
|
|
|
use craft_psd::fixtures::{PSB_CASES, PSD_2GB};
|
|
|
|
fn main() -> std::io::Result<()> {
|
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
|
// The default folder is created fresh (`create_dir` fails on a planted directory or symlink);
|
|
// an explicit one is the operator's choice.
|
|
let out = match args.first() {
|
|
Some(dir) => {
|
|
std::fs::create_dir_all(dir)?;
|
|
std::path::PathBuf::from(dir)
|
|
}
|
|
None => {
|
|
let mut n = 0u32;
|
|
loop {
|
|
let dir = std::env::temp_dir().join(format!("craft-psd-big-psb-{}-{n}", std::process::id()));
|
|
#[cfg_attr(not(unix), allow(unused_mut))]
|
|
let mut builder = std::fs::DirBuilder::new();
|
|
#[cfg(unix)]
|
|
std::os::unix::fs::DirBuilderExt::mode(&mut builder, 0o700);
|
|
match builder.create(&dir) {
|
|
Ok(()) => {
|
|
// Kept after the run (the fixtures are the point): remove it when done.
|
|
eprintln!("writing fixtures to {} (remove it when done)", dir.display());
|
|
break dir;
|
|
}
|
|
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists && n < 1000 => n += 1,
|
|
Err(e) => return Err(e),
|
|
}
|
|
}
|
|
}
|
|
};
|
|
let wanted = args.get(1..).unwrap_or(&[]);
|
|
for case in PSB_CASES.iter().chain([&PSD_2GB]).filter(|c| wanted.is_empty() || wanted.iter().any(|w| w == c.name)) {
|
|
let path = out.join(case.file_name());
|
|
let t = std::time::Instant::now();
|
|
// In the fresh default folder only: a half-written fixture is removed, but never a file an
|
|
// operator-chosen folder already held.
|
|
let len = case.write_file(&path).inspect_err(|_| {
|
|
if args.is_empty() {
|
|
let _ = std::fs::remove_file(&path);
|
|
}
|
|
})?;
|
|
println!("{}: {:.2} GB in {:.1} s", path.display(), len as f64 / 1e9, t.elapsed().as_secs_f64());
|
|
}
|
|
Ok(())
|
|
}
|