2026-10-28 01:20:01 +08:00
|
|
|
import io
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
|
|
|
|
|
|
def apply_watermark(input_img_path, output_img_path):
|
|
|
|
|
base = Image.open(input_img_path).convert("RGBA")
|
|
|
|
|
bw, bh = base.size
|
|
|
|
|
|
|
|
|
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
2026-10-30 00:00:16 +08:00
|
|
|
logo_path = os.path.join(base_dir, "public", "assets", "brand", "shanghai_karate_logo.webp")
|
2026-10-28 01:20:01 +08:00
|
|
|
qr_path = os.path.join(base_dir, "public", "assets", "brand", "dojo_qr.png")
|
|
|
|
|
|
|
|
|
|
margin = int(bw * 0.035)
|
|
|
|
|
|
|
|
|
|
# 1. School Logo without background (Top-Left Corner)
|
|
|
|
|
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)
|
|
|
|
|
base.paste(logo_resized, (margin, margin), logo_resized)
|
|
|
|
|
|
|
|
|
|
# 2. WeChat-Scannable QR Code (Bottom-Right Corner)
|
|
|
|
|
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 reliably even on dark or textured photos
|
|
|
|
|
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: '上海健志空手道馆 · Shanghai Karate Club · Est. 2008'
|
|
|
|
|
draw = ImageDraw.Draw(base)
|
|
|
|
|
font_path = os.path.join(base_dir, "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 + high-contrast text
|
|
|
|
|
draw.text((tx + 1, ty + 1), text, font=font, fill=(0, 0, 0, 220))
|
|
|
|
|
draw.text((tx, ty), text, font=font, fill=(255, 240, 200, 255))
|
|
|
|
|
|
|
|
|
|
base.convert("RGB").save(output_img_path, format="JPEG", quality=94)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
if len(sys.argv) >= 3:
|
|
|
|
|
apply_watermark(sys.argv[1], sys.argv[2])
|
|
|
|
|
else:
|
|
|
|
|
apply_watermark(
|
|
|
|
|
r"public/test_style1_v2.jpg",
|
|
|
|
|
r"public/test_watermarked_result.jpg"
|
|
|
|
|
)
|