Files
dungeoncraft/tools/make_material.py
T

54 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Turn a generated material picture into a texture for the furniture (props.rs): cropped,
optionally turned into grey detail (the furniture's colours tint it in the game), brightened to
a common mean and scaled to the high-res size and the pixel-art size.
Usage:
make_material.py raw.png out_prefix [--crop x0,y0,x1,y1] [--trim] [--color] [--mean 0.8]
--crop fractions of the picture to keep
--trim crop to the picture's object (everything that is not near-white background)
--color keep the colours (else grey detail)
--mean mean brightness of the result (0..1)
Writes out_prefix-64.png and out_prefix-16.png. Needs Pillow.
"""
import argparse
from PIL import Image, ImageOps, ImageStat
def main():
ap = argparse.ArgumentParser()
ap.add_argument("raw")
ap.add_argument("out")
ap.add_argument("--crop", default=None)
ap.add_argument("--trim", action="store_true")
ap.add_argument("--color", action="store_true")
ap.add_argument("--mean", type=float, default=0.8)
a = ap.parse_args()
img = Image.open(a.raw).convert("RGB")
if a.crop:
f = [float(v) for v in a.crop.split(",")]
img = img.crop((int(f[0] * img.width), int(f[1] * img.height), int(f[2] * img.width), int(f[3] * img.height)))
if a.trim:
# the object: everything darker than the white background, a few pixels in
mask = img.convert("L").point(lambda v: 255 if v < 235 else 0)
box = mask.getbbox()
if box:
img = img.crop((box[0] + 4, box[1] + 4, box[2] - 4, box[3] - 4))
if not a.color:
img = ImageOps.grayscale(img).convert("RGB")
mean = ImageStat.Stat(img.convert("L")).mean[0] / 255
k = a.mean / max(mean, 0.01)
img = img.point(lambda v: min(255, int(v * k)))
img.resize((64, 64), Image.LANCZOS).save(f"{a.out}-64.png")
small = img.resize((16, 16), Image.BOX)
small.quantize(colors=8, method=Image.Quantize.MEDIANCUT, dither=Image.Dither.NONE).convert("RGB").save(f"{a.out}-16.png")
print(f"{a.out}-64.png, {a.out}-16.png")
if __name__ == "__main__":
main()