Files
Genarrative/scripts/generate-taonier-capybara-jar-ref01-logo-refine-contact-sheet.py

145 lines
4.9 KiB
Python

from __future__ import annotations
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageOps
REPO_ROOT = Path(__file__).resolve().parents[1]
OUTPUT_DIR = (
REPO_ROOT
/ "public"
/ "branding"
/ "taonier-logo-capybara-jar-ref01-logo-refine-concepts"
)
CONTACT_SHEET_PATH = (
OUTPUT_DIR / "taonier-logo-capybara-jar-ref01-logo-refine-contact-sheet.png"
)
REFERENCE_IMAGE = (
REPO_ROOT
/ "public"
/ "branding"
/ "taonier-logo-peeking-head-jar-new-animals-concepts"
/ "taonier-peeking-head-jar-new-animals-01-capybara.png"
)
ITEMS = [
("REF 原01", REFERENCE_IMAGE),
("01 扁平陶橙", "taonier-capybara-jar-ref01-logo-refine-01-flat-terracotta"),
("02 奶白可可", "taonier-capybara-jar-ref01-logo-refine-02-cream-cocoa"),
("03 鼠尾草陶", "taonier-capybara-jar-ref01-logo-refine-03-sage-clay"),
("04 线面徽记", "taonier-capybara-jar-ref01-logo-refine-04-outline-emblem"),
("05 抽象几何", "taonier-capybara-jar-ref01-logo-refine-05-abstract-geometric"),
("06 黑白优先", "taonier-capybara-jar-ref01-logo-refine-06-monochrome-first"),
("07 轻渐变商标", "taonier-capybara-jar-ref01-logo-refine-07-soft-gradient-logo"),
("08 头像强识别", "taonier-capybara-jar-ref01-logo-refine-08-bold-avatar"),
]
def load_font(size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
candidates = [
Path("C:/Windows/Fonts/msyh.ttc"),
Path("C:/Windows/Fonts/simhei.ttf"),
Path("C:/Windows/Fonts/simsun.ttc"),
]
for candidate in candidates:
if candidate.exists():
return ImageFont.truetype(str(candidate), size)
return ImageFont.load_default()
def find_image(stem_or_path: str | Path) -> Path | None:
if isinstance(stem_or_path, Path):
return stem_or_path if stem_or_path.exists() else None
for extension in ("png", "webp", "jpg", "jpeg"):
candidate = OUTPUT_DIR / f"{stem_or_path}.{extension}"
if candidate.exists():
return candidate
return None
def normalize_square(image_path: Path) -> Image.Image:
image = Image.open(image_path).convert("RGB")
if image.size == (1024, 1024):
return image
if image.width == image.height:
normalized = image.resize((1024, 1024), Image.Resampling.LANCZOS)
else:
normalized = ImageOps.contain(image, (1024, 1024), Image.Resampling.LANCZOS)
canvas = Image.new("RGB", (1024, 1024), "#fffdf8")
x = (1024 - normalized.width) // 2
y = (1024 - normalized.height) // 2
canvas.paste(normalized, (x, y))
normalized = canvas
if image_path.is_relative_to(OUTPUT_DIR):
normalized.save(image_path, quality=95)
return normalized
def bw_preview(image: Image.Image, size: int) -> Image.Image:
thumb = ImageOps.grayscale(image).resize((size, size), Image.Resampling.LANCZOS)
return ImageOps.autocontrast(thumb).convert("RGB")
def main() -> None:
cell_size = 268
label_height = 54
test_height = 44
gap = 22
columns = 3
rows = 3
cell_total_height = cell_size + label_height + test_height
width = columns * cell_size + (columns + 1) * gap
height = rows * cell_total_height + (rows + 1) * gap
sheet = Image.new("RGB", (width, height), "#f0ebe5")
draw = ImageDraw.Draw(sheet)
label_font = load_font(18)
test_font = load_font(13)
for index, (label, stem_or_path) in enumerate(ITEMS):
row = index // columns
column = index % columns
x = gap + column * (cell_size + gap)
y = gap + row * (cell_total_height + gap)
image_path = find_image(stem_or_path)
if image_path is None:
continue
source = normalize_square(image_path)
thumbnail = source.resize((cell_size, cell_size), Image.Resampling.LANCZOS)
sheet.paste(thumbnail, (x, y))
draw.rounded_rectangle(
(x, y + cell_size, x + cell_size, y + cell_size + label_height),
radius=8,
fill="#fffdf8",
)
text_box = draw.textbbox((0, 0), label, font=label_font)
text_x = x + (cell_size - (text_box[2] - text_box[0])) / 2
text_y = y + cell_size + (label_height - (text_box[3] - text_box[1])) / 2 - 2
draw.text((text_x, text_y), label, fill="#302a25", font=label_font)
test_y = y + cell_size + label_height
draw.rounded_rectangle(
(x, test_y, x + cell_size, test_y + test_height),
radius=8,
fill="#f7f3ed",
)
tiny = source.resize((32, 32), Image.Resampling.LANCZOS)
mono = bw_preview(source, 32)
sheet.paste(tiny, (x + 52, test_y + 6))
sheet.paste(mono, (x + 104, test_y + 6))
draw.text((x + 150, test_y + 13), "32px / BW", fill="#5c5148", font=test_font)
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
sheet.save(CONTACT_SHEET_PATH, quality=95)
print(CONTACT_SHEET_PATH)
if __name__ == "__main__":
main()