Bestiary portraits in the high-res style: a painted pixel-art bust for every creature
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a24fc51605
commit
8d2362fc11
41 files changed
+308
-1
No files matched your search
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
# Raw portraits (1024x1024) -> 128x128 pixel-art portraits (box downscale, 48 colours, no
|
||||
# dithering, opaque) and the atlas assets/portraits/portraits.png (8 columns) + order.txt.
|
||||
import os, sys
|
||||
from PIL import Image, ImageEnhance
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
from portraits import CREATURES
|
||||
|
||||
ROOT = "/home/zink/Projects/dungeoncraft"
|
||||
D = f"{ROOT}/art/generated/portraits"
|
||||
OUT = f"{ROOT}/assets/portraits"
|
||||
SIZE, COLORS, COLS = 128, 48, 8
|
||||
CROP = {} # id -> (l, t, r, b) fractions, default the whole picture
|
||||
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
rows = (len(CREATURES) + COLS - 1) // COLS
|
||||
atlas = Image.new("RGB", (COLS * SIZE, rows * SIZE), (0, 0, 0))
|
||||
order = []
|
||||
for i, c in enumerate(CREATURES):
|
||||
im = Image.open(f"{D}/{c['id']}-raw.png").convert("RGB")
|
||||
l, t, r, b = CROP.get(c["id"], (0, 0, 1, 1))
|
||||
w, h = im.size
|
||||
im = im.crop((round(l * w), round(t * h), round(r * w), round(b * h)))
|
||||
im = im.resize((SIZE, SIZE), Image.BOX)
|
||||
im = ImageEnhance.Sharpness(im).enhance(1.6)
|
||||
im = im.quantize(colors=COLORS, method=Image.Quantize.MAXCOVERAGE, kmeans=4, dither=Image.Dither.NONE).convert("RGB")
|
||||
im.save(f"{D}/{c['id']}-{SIZE}.png", optimize=True)
|
||||
atlas.paste(im, ((i % COLS) * SIZE, (i // COLS) * SIZE))
|
||||
order.append(c["kind"])
|
||||
atlas.save(f"{OUT}/portraits.png", optimize=True)
|
||||
open(f"{OUT}/order.txt", "w").write("\n".join(order) + "\n")
|
||||
print(atlas.size, os.path.getsize(f"{OUT}/portraits.png"), "bytes")
|
||||
Reference in new issue
Block a user