BurningTimesAi/공유/기획/FirstRising/아이템/icon_finalize.py

49 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
# 2026-10-02 PD 지시 — "기준에 맞는지 검토해서 배경을 투명하게 … 리소스화 할 수 있도록 제작".
# 검토에서 고른 그림을 게임 리소스 규격으로 다듬는다: 옅은 잔여 알파 제거 → 물체 테두리로 잘라 → 캔버스(1024) 가운데에 같은 여백(물체 긴 변 = 캔버스의 82%)으로 놓는다.
# python icon_finalize.py <원본 폴더> <고른 목록 json> <출력 폴더>
# 목록 json: {"<출력 이름>": "<원본 파일 이름>", …}. 끝에 고른 것 전체를 한 장(final_sheet.png)으로 묶는다.
import io, json, os, sys
from PIL import Image, ImageDraw
SIZE, FIT = 1024, 0.82 # FR 원본 아이콘과 같은 1024 · 여백 통일
ALPHA_FLOOR = 24 # 이보다 옅은 알파(배경 제거가 남긴 안개)는 지운다
def finalize(path):
im = Image.open(path).convert("RGBA")
a = im.getchannel("A").point(lambda v: 0 if v < ALPHA_FLOOR else v)
im.putalpha(a)
box = a.getbbox()
if box:
im = im.crop(box)
scale = SIZE * FIT / float(max(im.size))
im = im.resize((max(1, int(round(im.width * scale))), max(1, int(round(im.height * scale)))), Image.LANCZOS)
canvas = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
canvas.paste(im, ((SIZE - im.width) // 2, (SIZE - im.height) // 2), im)
return canvas
def main():
src, picks_path, out = sys.argv[1], sys.argv[2], sys.argv[3]
picks = json.load(io.open(picks_path, encoding="utf-8"))
os.makedirs(out, exist_ok=True)
names = sorted(picks.keys())
cell, pad, cols = 200, 4, 8
rows = (len(names) + cols - 1) // cols
sheet = Image.new("RGB", (cols * (cell + pad) + pad, rows * (cell + pad) + pad), (24, 24, 28))
draw = ImageDraw.Draw(sheet)
for i, name in enumerate(names):
im = finalize(os.path.join(src, picks[name]))
im.save(os.path.join(out, name + ".png"))
# 게임 칸과 비슷한 어두운 바탕에 올려 본다
bg = Image.new("RGB", (cell, cell), (40, 40, 46)); small = im.resize((cell, cell), Image.LANCZOS); bg.paste(small, (0, 0), small)
x, y = pad + (i % cols) * (cell + pad), pad + (i // cols) * (cell + pad)
sheet.paste(bg, (x, y)); draw.text((x + 3, y + 2), name, fill=(220, 220, 220))
sheet.save(os.path.join(out, "final_sheet.png"))
print("%d icons -> %s" % (len(names), out))
if __name__ == "__main__":
main()