# -*- coding: utf-8 -*-
"""给黑板报配色图 / 线条图 叠加粉笔标题（中文一律 Pillow 叠字）"""
import os, glob, numpy as np
from PIL import Image, ImageDraw, ImageFont, ImageFilter

CHALK = '/data/www/files/heibanbaoArt/chalk'
LINE = '/data/www/files/heibanbaoArt/line'
OUT_C = '/data/www/files/heibanbaoArt/color_final'
OUT_L = '/data/www/files/heibanbaoArt/line_final'
os.makedirs(OUT_C, exist_ok=True)
os.makedirs(OUT_L, exist_ok=True)

FONT = '/usr/share/fonts/opentype/noto/NotoSansCJK-Bold.ttc'
IDX = 2  # Noto Sans CJK SC Bold

TITLES = {
 '1_安全伴我行_盾牌': ('安全伴我行', '校园安全 · 交通安全 · 消防安全 · 防溺水 · 防欺凌 · 食品安全'),
 '2_文明出行_交通标志': ('文明出行 平安相伴', '交通安全 · 消防安全 · 安全小贴士'),
 '3_珍爱生命_防溺水': ('珍爱生命 谨防溺水', '防溺水 · 食品安全 · 自我保护常识'),
 '4_反诈小卫士_手机': ('反诈小卫士', '防范电信网络诈骗 · 不轻信 · 不透露 · 不转账'),
 '5_远离毒品_健康成长': ('远离毒品 健康成长', '禁毒教育 · 珍爱生命 · 拒绝第一口'),
}

WHITE = (246, 242, 230)
YELLOW = (247, 217, 94)


def text_mask(size, text, fs, y_baseline):
    f = ImageFont.truetype(FONT, fs, index=IDX)
    m = Image.new('L', size, 0)
    ImageDraw.Draw(m).text((size[0] // 2, y_baseline), text, font=f,
                           fill=255, anchor='ms')
    return m, f


def chalkify(mask, seed, body=0.42):
    """把实心字mask变成粉笔字alpha：明暗颗粒 + 细微挖孔 + 边缘毛糙"""
    rng = np.random.default_rng(seed)
    a = np.array(mask).astype(np.float32) / 255.0
    h, w = a.shape
    # 成块噪声（模拟粉笔在板面上的不均匀附着）
    n = Image.fromarray((rng.random((h, w)) * 255).astype('uint8')).filter(ImageFilter.GaussianBlur(2.2))
    n = np.array(n).astype(np.float32) / 255.0
    n = (n - n.min()) / max(n.max() - n.min(), 1e-6)
    alpha = a * (body + (1 - body) * n)
    # 小孔（粉笔没压到的点）
    holes = (rng.random((h, w)) < 0.035).astype('uint8') * 255
    holes = np.array(Image.fromarray(holes).filter(ImageFilter.GaussianBlur(0.7))).astype(np.float32) / 255.0
    alpha = alpha * (1 - 0.75 * holes)
    # 边缘毛糙：随机小幅位移后的最小值
    er = np.array(Image.fromarray((alpha * 255).astype('uint8')).filter(ImageFilter.GaussianBlur(0.6))).astype(np.float32) / 255.0
    alpha = np.clip(alpha * 0.75 + er * 0.35, 0, 1)
    return alpha


def compose(base, text, fs_main, y_main, y_sub, main_color, sub_color, seed):
    img = base.convert('RGBA')
    size = img.size
    m_main, f_main = text_mask(size, text[0], fs_main, y_main)
    fs_sub = 44
    m_sub, _ = text_mask(size, text[1], fs_sub, y_sub)

    # 粉笔灰晕（底层）
    halo_a = np.array(m_main.filter(ImageFilter.GaussianBlur(9))).astype(np.float32) / 255.0 * 0.16
    halo = Image.new('RGBA', size, main_color + (0,))
    halo.putalpha(Image.fromarray((halo_a * 255).astype('uint8')))
    img = Image.alpha_composite(img, halo)

    for mask, color, sd, body in ((m_main, main_color, seed, 0.42), (m_sub, sub_color, seed + 7, 0.55)):
        a = chalkify(mask, sd, body)
        layer = Image.new('RGBA', size, color + (0,))
        layer.putalpha(Image.fromarray((a * 255).astype('uint8')))
        img = Image.alpha_composite(img, layer)
    return img.convert('RGB')


def hollow(base, text, fs_main, y_main, y_sub):
    """线稿版：空心字（黑描边 + 白色填充）"""
    img = base.convert('RGB')
    d = ImageDraw.Draw(img)
    size = img.size
    f = ImageFont.truetype(FONT, fs_main, index=IDX)
    d.text((size[0] // 2, y_main), text[0], font=f, fill=(255, 255, 255),
           stroke_width=max(5, fs_main // 26), stroke_fill=(25, 25, 25), anchor='ms')
    f2 = ImageFont.truetype(FONT, 44, index=IDX)
    d.text((size[0] // 2, y_sub), text[1], font=f2, fill=(25, 25, 25), anchor='ms')
    return img


def fit_fs(text, target_w=1880, cap=210):
    n = len(text.replace(' ', '')) + text.count(' ') * 0.55
    return int(min(cap, target_w / max(n, 1)))


if __name__ == '__main__':
    for name, text in TITLES.items():
        fs = fit_fs(text[0])
        y_main = int(fs * 1.02)
        y_sub = y_main + 78
        p = os.path.join(CHALK, name + '.jpg')
        c = compose(Image.open(p), text, fs, y_main, y_sub, WHITE, YELLOW, seed=abs(hash(name)) % 9999)
        c.save(os.path.join(OUT_C, name + '.jpg'), quality=95, subsampling=0)
        p2 = os.path.join(LINE, name + '.jpg')
        if os.path.exists(p2):
            l = hollow(Image.open(p2), text, fs, y_main, y_sub)
            l.save(os.path.join(OUT_L, name + '.jpg'), quality=95, subsampling=0)
        print('OK', name, 'fs', fs)
