feat(saju): 호령 캐릭터 PNG 6개 추출 (horyung.png + saju_color_sheet.png)
PIL-based extraction script with measured crop coordinates: - horyung.png (1055x1491, 3-view layout): bust shot + front view - saju_color_sheet.png (1536x1024, 6 emotion stickers row): greeting, thinking, pointing, happy (left 4 of 6) Output files (public/images/saju/horyung/): - horyung-bust.png (590x478) - horyung-front.png (697x507) - horyung-greeting.png (150x216) - horyung-thinking.png (150x216) - horyung-pointing.png (150x216) - horyung-happy.png (150x216) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
BIN
public/images/saju/horyung/horyung-bust.png
Normal file
BIN
public/images/saju/horyung/horyung-bust.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 KiB |
BIN
public/images/saju/horyung/horyung-front.png
Normal file
BIN
public/images/saju/horyung/horyung-front.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 554 KiB |
BIN
public/images/saju/horyung/horyung-greeting.png
Normal file
BIN
public/images/saju/horyung/horyung-greeting.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
public/images/saju/horyung/horyung-happy.png
Normal file
BIN
public/images/saju/horyung/horyung-happy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
public/images/saju/horyung/horyung-pointing.png
Normal file
BIN
public/images/saju/horyung/horyung-pointing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
BIN
public/images/saju/horyung/horyung-thinking.png
Normal file
BIN
public/images/saju/horyung/horyung-thinking.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
86
scripts/extract_horyung.py
Normal file
86
scripts/extract_horyung.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
"""호령 캐릭터 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.")
|
||||||
Reference in New Issue
Block a user