Furniture materials: wood, stone, iron, cloth, straw, fur, book spines and spellbook pages in both styles
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9cba545bc7
commit
c23c4d28ec
46 files changed
+298
-89
No files matched your search
@@ -0,0 +1,53 @@
|
||||
#!/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()
|
||||
Reference in new issue
Block a user