88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
OUTPUT_DIR = REPO_ROOT / "public" / "branding" / "taonier-logo-anti-candy-concepts"
|
|
CONTACT_SHEET_PATH = OUTPUT_DIR / "taonier-logo-anti-candy-contact-sheet.png"
|
|
|
|
ITEMS = [
|
|
("01 哑光陶泥印章", "taonier-anti-candy-01-matte-clay-stamp"),
|
|
("02 窑印星核", "taonier-anti-candy-02-kiln-mark-core"),
|
|
("03 负形星核", "taonier-anti-candy-03-cutout-negative-star"),
|
|
("04 干陶颗粒", "taonier-anti-candy-04-dry-clay-grain"),
|
|
("05 手压泥币", "taonier-anti-candy-05-hand-pressed-token"),
|
|
("06 数字泥符", "taonier-anti-candy-06-digital-clay-glyph"),
|
|
("07 精品扁平标", "taonier-anti-candy-07-premium-flat-mark"),
|
|
("08 单色验证版", "taonier-anti-candy-08-monochrome-proof"),
|
|
]
|
|
|
|
|
|
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: str) -> Path | None:
|
|
for extension in ("png", "webp", "jpg", "jpeg"):
|
|
candidate = OUTPUT_DIR / f"{stem}.{extension}"
|
|
if candidate.exists():
|
|
return candidate
|
|
return None
|
|
|
|
|
|
def main() -> None:
|
|
cell_size = 300
|
|
label_height = 58
|
|
gap = 24
|
|
columns = 4
|
|
rows = 2
|
|
width = columns * cell_size + (columns + 1) * gap
|
|
height = rows * (cell_size + label_height) + (rows + 1) * gap
|
|
|
|
sheet = Image.new("RGB", (width, height), "#ebe6dc")
|
|
draw = ImageDraw.Draw(sheet)
|
|
font = load_font(20)
|
|
|
|
for index, (label, stem) in enumerate(ITEMS):
|
|
row = index // columns
|
|
column = index % columns
|
|
x = gap + column * (cell_size + gap)
|
|
y = gap + row * (cell_size + label_height + gap)
|
|
|
|
image_path = find_image(stem)
|
|
if image_path is None:
|
|
continue
|
|
|
|
source = Image.open(image_path).convert("RGB")
|
|
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="#fbfaf6",
|
|
)
|
|
text_box = draw.textbbox((0, 0), label, font=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=font)
|
|
|
|
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
|
sheet.save(CONTACT_SHEET_PATH, quality=95)
|
|
print(CONTACT_SHEET_PATH)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|