80 findings, not the 14 the first run showed -- clippy stops at the first failing compilation unit, so `--keep-going` is what makes the list complete. 60 were machine-applicable (`cargo clippy --fix`). The rest by hand: * five descending `sort_by` -> `sort_by_key(Reverse(..))` * `chunks_exact(4)` on both sides of four zips, so the compared items stay `[u8; 4]` rather than one array against one slice * three `type` aliases for the census maps and the captured-quad tuple * `&PathBuf` -> `&Path` in two disc tests * two range loops; one of them keeps `#[allow(needless_range_loop)]` with the reason -- the index is into a map's value, which changes each iteration * the module doc list in `invert_capture` re-indented to markdown's rules * `blit`'s eight arguments get `#[allow(too_many_arguments)]`, not a struct One dead `let off = b.len();` in a `ratc` test is dropped rather than renamed. The sibling test at :162 is the one that asserts an offset; if this one was meant to as well, that is a test change and not a lint fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
84 lines
3.2 KiB
Rust
84 lines
3.2 KiB
Rust
//! The main menu's sprites, by their ALPHA channel — is `ptframe1`/`ptframe2`'s
|
|
//! "no fully-opaque pixel" a property of the artwork, and does any alpha value
|
|
//! look like a scale the game expands (e.g. 0..128) rather than 0..255?
|
|
//!
|
|
//! The port measures both frames as rendering too DARK against the capture, with
|
|
//! the shortfall correlating with the BACKGROUND. Two different causes predict
|
|
//! that: a background-scaling blend selected in code, or an alpha that is too
|
|
//! LOW in our decode. This example tests the second, which is on the disc.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example frame_alpha_census
|
|
use std::path::PathBuf;
|
|
use sylpheed_formats::{pak::PakArchive, t8ad, ui_layout};
|
|
|
|
fn census(name: &str, img: &t8ad::T8adImage) {
|
|
let n = (img.width * img.height) as usize;
|
|
let mut hist = [0usize; 256];
|
|
for p in 0..n {
|
|
hist[img.rgba[p * 4 + 3] as usize] += 1;
|
|
}
|
|
let zero = hist[0];
|
|
let full = hist[255];
|
|
let max = (0..256).rev().find(|&a| hist[a] > 0).unwrap_or(0);
|
|
let nonzero = n - zero;
|
|
// the top five alpha values that actually occur, by population
|
|
let mut top: Vec<(usize, usize)> = (1..256)
|
|
.map(|a| (hist[a], a))
|
|
.filter(|&(c, _)| c > 0)
|
|
.collect();
|
|
top.sort_unstable_by_key(|a| std::cmp::Reverse(a.0));
|
|
let top5: Vec<String> = top
|
|
.iter()
|
|
.take(5)
|
|
.map(|&(c, a)| format!("{a}x{c}"))
|
|
.collect();
|
|
println!(
|
|
"{name:<16} {}x{:<4} px={n:<8} a=0:{:5.1}% a=255:{:5.1}% max={max:<3} \
|
|
partial(1..254)/nonzero={:5.1}% top:[{}]",
|
|
img.width,
|
|
img.height,
|
|
100.0 * zero as f64 / n as f64,
|
|
100.0 * full as f64 / n as f64,
|
|
if nonzero > 0 {
|
|
100.0 * (nonzero - full) as f64 / nonzero as f64
|
|
} else {
|
|
0.0
|
|
},
|
|
top5.join(" ")
|
|
);
|
|
}
|
|
|
|
fn main() {
|
|
let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC"));
|
|
let argv: Vec<String> = std::env::args().skip(1).collect();
|
|
let pak = argv
|
|
.iter()
|
|
.find(|a| a.parse::<usize>().is_err())
|
|
.cloned()
|
|
.unwrap_or_else(|| "GP_TITLE".to_string());
|
|
let ar = PakArchive::open(root.join(format!("dat/{pak}.pak"))).expect("pak");
|
|
// Builds default to the two the port ships and can be overridden, so the
|
|
// same census serves the title (4) and the `PRESS (A)` plate (2).
|
|
let args: Vec<usize> = argv.iter().filter_map(|a| a.parse().ok()).collect();
|
|
let builds: Vec<usize> = if args.is_empty() { vec![5, 6] } else { args };
|
|
for build in builds {
|
|
let Ok(by) = ar.read(&ar.entries()[build]) else {
|
|
continue;
|
|
};
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
println!("=== {pak} build {build} ===");
|
|
let mut names: Vec<&String> = b.sprites.keys().collect();
|
|
names.sort();
|
|
for n in names {
|
|
let (off, size) = b.sprites[n];
|
|
let s = &by[off..(off + size).min(by.len())];
|
|
match t8ad::parse(s) {
|
|
Some(img) => census(n, &img),
|
|
None => println!("{n:<16} (not a T8aD / failed to parse)"),
|
|
}
|
|
}
|
|
}
|
|
}
|