Files
image-suite-studio/.zcode/plans/plan-sess_09baa2fe-f66c-4c4c-a76b-38813a98e415.md
T
2026-08-24 17:15:08 +08:00

3.1 KiB
Raw Blame History

水印功能实现计划(服务端后处理合成,非 AI 模型加水印)

架构决策

  • 水印在 AI 出图返回后、落盘前 由服务端合成(run_suitegenerator() 返回字节之后、storage.write_bytes 之前)。预览(/media URL)与导出 ZIP 自然都是带水印图,所见即所得;不经过提示词/AI 模型。
  • 开关与配置放插件"服务端设置"Popover,随生成请求下发(服务端不做 .env 配置项);持久化在 chrome.storage.local。
  • 默认样式复刻 ozonSeller「图表处理」:图片水印 = imgs/watermark.jpg 圆形徽章(宽 15%、右下、透明度 30%);文字水印 = 默认文案 xiongmaoyx(白字黑描边、字号 6% 宽度、加粗)。位置本期固定右下,不做调节。

服务端(server/

  1. 依赖与资产

    • requirements.txtpillow 并安装(venv 现无 PIL
    • 复制 ozon-seller-kit/web/imgs/watermark.jpgserver/assets/watermark.jpg200×200 JPEG
    • config.pywatermark_image_path(默认指向上述资产)
  2. 新模块 services/watermark.py

    • apply_watermark(data: bytes, opts: dict) -> bytes:魔数识别 PNG/JPEG → PIL 打开转 RGBA 合成 → 按原格式保存(JPEG quality≈95
    • 图片水印:资产中心裁方 → 圆形遮罩 → 缩放到图宽 15% → 按 opacity 合成 → 右下角贴入(边距 ≈1% 图宽)
    • 文字水印:字号 = 图宽 6%(下限 12px)、白色填充 + 黑色描边(alpha 0.55、描边宽 fontSize/8);字体回退链 PingFang → Hiragino Sans GB → STHeiti → Pillow 默认(模块级缓存首次命中)
    • 容错:字体/资产缺失时 log warning 并返回原图,绝不阻断生图
  3. 协议与流转

    • schemas.py:新增 WatermarkOptionsenabled=False, type='image'|'text', text='xiongmaoyx', opacity=30),GenerateRequestwatermark 字段
    • tasks.pyTaskwatermark: dict | None
    • api/generate.pycreate_task 透传
    • generator.py run_suite:落盘前 if watermark enabled: data = apply_watermark(...)

插件端(extension/

  1. 设置与请求
    • src/storage/settings.tsBackendSettingswatermark: { enabled: false, type: 'image', text: 'xiongmaoyx', opacity: 30 }loadSettings 对该子对象做深合并(兼容老数据)
    • src/api/client.tsGeneratePayloadwatermark?buildGeneratePayload 透传
  2. UIApp.tsx settingsPopup
    • 加水印设置块:开启 checkbox、类型 pills(图片/文字)、文字内容 input(仅文字类型显示)、透明度 number(0–100 步进 5,带 %);Popover 宽度 260→300
    • startGenerate 的 config 在开启时带 watermark,关闭不下发

验证

  • 烟测:对已有生成图字节分别跑图片/文字两种水印(含透明度边界),人工查看合成效果
  • 前端 tsc --noEmitREADME 补充说明

影响面

仅生成图被处理;参考图/上传图不动。水印合成失败自动跳过不阻断生成。开关关闭时生成的图保持干净,导出即所见。