Files
RustRaptor/mods/iron_coast_railburst/prepare_art.rs
T

77 lines
2.6 KiB
Rust

const SHOT_W: u32 = 4;
const SHOT_H: u32 = 20;
// Fit untouched generated masters to shared logical canvases and four-times HD.
// Compile with this project's pinned image crate; see README for reproduction.
use image::{Rgba, RgbaImage, imageops};
use std::{env, fs, path::Path};
fn fit(source: &RgbaImage, w: u32, h: u32, scale: u32) -> RgbaImage {
let mut bounds = (source.width(), source.height(), 0, 0);
for (x, y, p) in source.enumerate_pixels() {
if p[3] >= 128 {
bounds.0 = bounds.0.min(x);
bounds.1 = bounds.1.min(y);
bounds.2 = bounds.2.max(x + 1);
bounds.3 = bounds.3.max(y + 1);
}
}
assert!(
bounds.2 > bounds.0 && bounds.3 > bounds.1,
"no meaningful source alpha"
);
let crop = imageops::crop_imm(
source,
bounds.0,
bounds.1,
bounds.2 - bounds.0,
bounds.3 - bounds.1,
)
.to_image();
// Exactly one logical pixel of clear margin, shared across SD and HD.
let factor = ((w - 2) as f64 / crop.width() as f64).min((h - 2) as f64 / crop.height() as f64);
let nw = (crop.width() as f64 * factor).round().max(1.) as u32;
let nh = (crop.height() as f64 * factor).round().max(1.) as u32;
let filter = if scale == 1 {
imageops::FilterType::Triangle
} else {
imageops::FilterType::Lanczos3
};
let mut scaled = imageops::resize(&crop, nw * scale, nh * scale, filter);
for p in scaled.pixels_mut() {
if p[3] < 128 {
*p = Rgba([0, 0, 0, 0]);
} else {
p[3] = 255;
}
}
let mut out = RgbaImage::new(w * scale, h * scale);
imageops::overlay(
&mut out,
&scaled,
((w * scale - nw * scale) / 2) as i64,
((h * scale - nh * scale) / 2) as i64,
);
out
}
fn main() {
let args: Vec<_> = env::args().collect();
assert_eq!(args.len(), 2, "usage: prepare_art PACKAGE_DIRECTORY");
let root = Path::new(&args[1]);
for (kind, w, h) in [("equipment", 16, 16), ("projectile", SHOT_W, SHOT_H)] {
let source = image::open(root.join(format!("art/{kind}-generated-source-v1.png")))
.unwrap()
.into_rgba8();
for (mode, scale) in [("sd", 1), ("hd", 4)] {
let image = fit(&source, w, h, scale);
let path = root.join(format!("art/{kind}-{mode}.png"));
image.save(&path).unwrap();
println!("{} {}x{}", path.display(), image.width(), image.height());
}
}
assert!(
fs::metadata(root.join("art/equipment-hd.png"))
.unwrap()
.len()
> 0
);
}