"""호령 캐릭터 PNG 추출. source/characters/horyung.png (3 view layout: bust / back / front) source/images/saju_page/saju_color_sheet.png (5 emotion stickers in bottom row) 에서 호령 PNG 6개를 추출하여 public/images/saju/horyung/에 저장. """ import os from PIL import Image SOURCE_ROOT = "../source" HORYUNG_PATH = f"{SOURCE_ROOT}/characters/horyung.png" COLORSHEET_PATH = f"{SOURCE_ROOT}/images/saju_page/saju_color_sheet.png" OUT_DIR = "public/images/saju/horyung" os.makedirs(OUT_DIR, exist_ok=True) def crop_save(src_path, box, out_name): im = Image.open(src_path).convert("RGBA") cropped = im.crop(box) cropped.save(f"{OUT_DIR}/{out_name}") print(f"saved {out_name} ({cropped.size})") # ---- horyung.png: 1055 x 1491 (3 vertical views) ---- # 1. BUST SHOT (top): character is slightly right of center. # 2. BACK VIEW (middle): not used. # 3. FRONT VIEW (bottom): character with sword, slightly right of center. src_horyung = Image.open(HORYUNG_PATH) HW, HH = src_horyung.size print(f"horyung dims: {HW}x{HH}") # bust shot — top 1/3, character occupies horizontal middle-right area crop_save( HORYUNG_PATH, (int(HW * 0.22), int(HH * 0.01), int(HW * 0.78), int(HH * 0.33)), "horyung-bust.png", ) # front view — bottom 1/3. Measured: top of hat at y≈0.66, character spans x≈0.18~0.82 crop_save( HORYUNG_PATH, (int(HW * 0.16), int(HH * 0.66), int(HW * 0.82), int(HH * 1.0)), "horyung-front.png", ) # ---- saju_color_sheet.png: 1536 x 1024 ---- # Bottom row contains 6 emotion stickers laid horizontally. # Visual inspection: stickers occupy roughly x=0.439~0.986, y=0.82~1.0. # We need 4 stickers (greeting, thinking, pointing, happy) from positions 0~3. src_sheet = Image.open(COLORSHEET_PATH) SW, SH = src_sheet.size print(f"colorsheet dims: {SW}x{SH}") # 6 stickers in a single row at bottom-right # Measured visually with red grid overlay: # Sticker 1 (greeting): x = 600..750 # Sticker 2 (thinking): x = 750..900 # Sticker 3 (pointing): x = 900..1050 # Sticker 4 (happy): x = 1050..1200 # Sticker 5 (caution): x = 1200..1350 (unused) # Sticker 6 (lucky): x = 1350..1500 (unused) EMO_X_START = 600 EMO_X_END = 1500 EMO_Y_START = int(SH * 0.79) EMO_Y_END = int(SH * 1.00) EMO_COLS = 6 EMO_W = (EMO_X_END - EMO_X_START) / EMO_COLS EMO_H = EMO_Y_END - EMO_Y_START # left-to-right: greeting, thinking, pointing, happy, (5th: unused) positions = [ ("horyung-greeting.png", 0), ("horyung-thinking.png", 1), ("horyung-pointing.png", 2), ("horyung-happy.png", 3), ] for name, col in positions: x1 = int(EMO_X_START + col * EMO_W) y1 = EMO_Y_START x2 = int(EMO_X_START + (col + 1) * EMO_W) y2 = EMO_Y_END crop_save(COLORSHEET_PATH, (x1, y1, x2, y2), name) print("Done.")