Files
Ajasra 6772e0cf37 perf(booth): optimize assets and result flow
WebP reduces UI payload; JPEG keeps portrait saves compatible.\nFinish ends the visit without prompting another portrait.
2026-10-30 00:00:16 +08:00

71 lines
2.8 KiB
Python

import io
from PIL import Image, ImageDraw, ImageFont
import os
def watermark_portrait(image_path_or_buffer):
"""
Overlays:
1. Shanghai Karate Club transparent logo in top-left corner
2. WeChat-scannable school QR code with clean high-contrast backing in bottom-right corner
3. Bottom branding text: '上海健志空手道馆 · Shanghai Karate Club · Est. 2008'
"""
if isinstance(image_path_or_buffer, str):
base = Image.open(image_path_or_buffer).convert("RGBA")
else:
base = Image.open(io.BytesIO(image_path_or_buffer)).convert("RGBA")
bw, bh = base.size
# 1. School Logo (Top-Left)
logo_path = os.path.join(process_cwd(), "public", "assets", "brand", "shanghai_karate_logo.webp")
if os.path.exists(logo_path):
logo = Image.open(logo_path).convert("RGBA")
target_logo_w = int(bw * 0.28)
target_logo_h = int(logo.height * (target_logo_w / logo.width))
logo_resized = logo.resize((target_logo_w, target_logo_h), Image.Resampling.LANCZOS)
margin = int(bw * 0.035)
base.paste(logo_resized, (margin, margin), logo_resized)
else:
margin = int(bw * 0.035)
# 2. QR Code (Bottom-Right)
qr_path = os.path.join(process_cwd(), "public", "assets", "brand", "dojo_qr.png")
if os.path.exists(qr_path):
qr = Image.open(qr_path).convert("RGBA")
target_qr_w = int(bw * 0.17)
qr_resized = qr.resize((target_qr_w, target_qr_w), Image.Resampling.LANCZOS)
qr_pad = 5
# Clean white backing ensures WeChat scans perfectly regardless of photo background
qr_bg = Image.new("RGBA", (target_qr_w + qr_pad * 2, target_qr_w + qr_pad * 2), (255, 255, 255, 250))
qr_pos_x = bw - (target_qr_w + qr_pad * 2) - margin
qr_pos_y = bh - (target_qr_w + qr_pad * 2) - int(margin * 1.5)
base.paste(qr_bg, (qr_pos_x, qr_pos_y), qr_bg)
base.paste(qr_resized, (qr_pos_x + qr_pad, qr_pos_y + qr_pad), qr_resized)
# 3. Bottom Text
draw = ImageDraw.Draw(base)
font_path = os.path.join(process_cwd(), "public", "fonts", "ZCOOLKuaiLe.ttf")
font_size = max(14, int(bw * 0.026))
try:
font = ImageFont.truetype(font_path, font_size)
except Exception:
font = ImageFont.load_default()
text = "上海健志空手道馆 · Shanghai Karate Club · Est. 2008"
bbox = draw.textbbox((0, 0), text, font=font)
th = bbox[3] - bbox[1]
tx = margin
ty = bh - int(margin * 1.2) - th
# Subtle drop shadow + crisp warm white text
draw.text((tx + 1, ty + 1), text, font=font, fill=(0, 0, 0, 210))
draw.text((tx, ty), text, font=font, fill=(255, 240, 200, 255))
out_bytes = io.BytesIO()
base.convert("RGB").save(out_bytes, format="JPEG", quality=94)
return out_bytes.getvalue()
def process_cwd():
return r"C:\Users\user\Desktop\katare_helloween"