diff --git a/README.md b/README.md index 2694bc4..e03afb6 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ GitHub 交付配置: - 多张 3:4 或 9:16 独立 PNG - `prompts/`、`slide_jobs.json`、`slide_run_state.json` - `final_manifest.json` -- 可选 `watermarked_assets/`:用 `uv run python scripts/maomomo_tile_watermark.py` 生成 `MAOMOMO.COM` 45° 白色半透明平铺水印版 +- 可选 `watermarked_assets/`:用 `uv run python scripts/maomomo_tile_watermark.py` 生成 `MAOMOMO.COM` 45° 自动对比色半透明平铺水印版 - GitHub 分批链接 GitHub 分批交付前,技能会先引导配置: @@ -188,7 +188,7 @@ GitHub 分批交付前,技能会先引导配置: - 涉及金融、券商、银行、数字货币和合规内容时,保留谨慎措辞 - 配图统一使用白橘猫、暖橙色、干净金融科技教程风 - 如果用户没有指定配图风格,先在 `recommended-styles.md` 和 `image-styles/` 中按文章类型推荐 2-3 个方向,例如 `clean-professional`、`data-card-dashboard`、`handdrawn-note`、`e-ink-editorial` 或 `xiaohongshu-vertical`。 -- 小红书卡片出图前必须确认 `2D 扁平风` / `3D 轻拟物风` 和 `3:4` / `9:16`;用户没指定时默认推荐 2D,并按原生竖版重新构图,不能把横版图压进竖图。用户要求防盗图 / 水印时,可用 `uv run python scripts/maomomo_tile_watermark.py --input assets --output watermarked_assets` 生成 `MAOMOMO.COM` 45° 白色半透明平铺水印版,并保留无水印原图。 +- 小红书卡片出图前必须确认 `2D 扁平风` / `3D 轻拟物风` 和 `3:4` / `9:16`;用户没指定时默认推荐 2D,并按原生竖版重新构图,不能把横版图压进竖图。用户要求防盗图 / 水印时,可用 `uv run python scripts/maomomo_tile_watermark.py --input assets --output watermarked_assets` 生成 `MAOMOMO.COM` 45° 自动对比色半透明平铺水印版,并保留无水印原图。 文章不应当: diff --git a/SKILL.md b/SKILL.md index 9867095..8720b13 100644 --- a/SKILL.md +++ b/SKILL.md @@ -17,7 +17,7 @@ description: 生成或优化符合 maomomo / 猫MOMO 风格的中文出海金融 - 活动规则整理、开户教程、转账 / 入金 / 出金教程、保号方案、用卡姿势、对比总结、避坑经验。 - 已有文章 SEO 优化、发布用 Markdown、配图规划、独立配图、ZIP 打包和后续改稿。 - 小红书卡片、多图信息卡、3:4 或 9:16 竖版 PNG 系列图、封面 / 内容卡 / 结尾卡分批交付。 -- 对最终配图批量或单张叠加 `MAOMOMO.COM` 45° 白色半透明平铺水印。 +- 对最终配图批量或单张叠加 `MAOMOMO.COM` 45° 自动对比色半透明平铺水印。 不适合: @@ -51,7 +51,7 @@ description: 生成或优化符合 maomomo / 猫MOMO 风格的中文出海金融 - 图片交付完成后必须生成或更新 `final_manifest.json`,最终推送、打包或链接交付只能读取 `final_manifest.json` 或状态文件里明确标记为 final 的 assets;不得把 `draft`、`v2`、旧比例、失败图或未通过 QA 的图一起交付。 - 面向 Telegram / 聊天渠道的大文件交付默认改为 GitHub 分批推送:例如 `batch-01-cover`、`batch-02-content-cards`、`batch-03-final-assets`。Telegram 只负责通知进度和给 GitHub 文件路径、commit、release 或下载链接,不承载大 ZIP 或大图片包。 - 需要 GitHub 分批交付,或用户提到 GitHub 仓库、专用 KEY、token、PAT、deploy key 时,必须先读 `references/github-delivery.md`,引导配置专用私有交付仓库和最小权限凭据;不得要求用户在聊天里粘贴密钥,不得把 token / 私钥写入 prompt、manifest、状态文件、README、日志或提交记录。 -- 用户要求“水印”“平铺水印”“防盗图”“打水印”时,先读 `references/visual-assets.md` 的平铺水印规则;水印只处理最终 QA 通过的交付图或交付副本,默认保留无水印原图。水印必须用 `uv run python scripts/maomomo_tile_watermark.py` 生成,不得手工覆盖。 +- 用户要求“水印”“平铺水印”“防盗图”“打水印”时,先读 `references/visual-assets.md` 的平铺水印规则;水印只处理最终 QA 通过的交付图或交付副本,默认保留无水印原图。水印必须用 `uv run python scripts/maomomo_tile_watermark.py` 生成,不得手工覆盖。默认自动对比色:浅底黑字、深底白字;默认 alpha=70、font-size=50、spacing=28;每张图至少可见 2 个完整 `MAOMOMO.COM`。 - 每张图都必须在状态文件记录:prompt 文件、生成结果、QA 状态、是否进入 `assets/`、是否已推送 GitHub。中断恢复时先读状态文件和 `final_manifest.json`,不要依赖聊天记忆。 - 配图文件必须是独立 PNG;不要用一张大拼图代替多张图,不要只给提示词冒充图片文件。 - 后续改稿必须更新文件本体;影响图片、来源区、标题、摘要或 ZIP 时同步更新。 diff --git a/references/visual-assets.md b/references/visual-assets.md index 2ef79da..2474be1 100644 --- a/references/visual-assets.md +++ b/references/visual-assets.md @@ -28,10 +28,11 @@ - 水印文字:`MAOMOMO.COM` - 角度:45° -- 颜色:白色 `#FFFFFF` -- 透明度:半透明,默认 alpha `72/255` +- 颜色:自动对比色:浅底黑字 `#000000`,深底白字 `#FFFFFF` +- 透明度:半透明,默认 alpha `70/255` - 排列:对角线平铺 - 工具:`uv run python scripts/maomomo_tile_watermark.py` +- 密度:每张图至少可见 2 个完整 `MAOMOMO.COM`;默认 `font-size=50`、`spacing=28`。 执行示例: @@ -54,7 +55,7 @@ uv run python scripts/maomomo_tile_watermark.py \ - 水印只加到最终 QA 通过的 `assets/` 或交付副本;不要在样张确认前加水印,避免影响用户判断画面文字质量。 - 默认保留无水印原图在 `origin_image/` 和 / 或 `assets/`;水印图输出到 `watermarked_assets/`,或 GitHub 交付批次中的 `watermarked/`。 - 不要对官方截图证据原图、需要继续发给图片模型编辑的素材、尚未 QA 的图直接覆盖水印。 -- `final_manifest.json` 应记录 `watermark` 字段,至少包含 `text`、`angle`、`color`、`alpha`、`output_dir` 和水印文件清单。 +- `final_manifest.json` 应记录 `watermark` 字段,至少包含 `text`、`angle`、`color_rule`、`brightness_threshold`、`alpha`、`font_size`、`spacing`、`density_rule`、`output_dir` 和水印文件清单。 - 交付回复中说明是否提供水印版,以及无水印原图是否保留。 ## 可见文字与 prompt 边界 diff --git a/scripts/maomomo_tile_watermark.py b/scripts/maomomo_tile_watermark.py index 07065a0..f8213d4 100755 --- a/scripts/maomomo_tile_watermark.py +++ b/scripts/maomomo_tile_watermark.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """为 MAOMOMO 配图叠加 45° 平铺半透明水印。 -默认水印:MAOMOMO.COM,白色半透明,45° 对角线平铺。 +默认水印:MAOMOMO.COM,45° 对角线平铺;自动对比色,浅底黑字、深底白字。 用法: uv run python scripts/maomomo_tile_watermark.py --input assets --output watermarked_assets @@ -48,14 +48,24 @@ def ensure_pillow() -> Tuple[Any, Any, Any]: def parse_color(value: str) -> Tuple[int, int, int]: text = value.strip() + if text.lower() == "auto": + die("auto color must be resolved after reading each image") if text.startswith("#"): text = text[1:] if len(text) != 6: - die("颜色必须是 #RRGGBB,例如 #FFFFFF") + die("颜色必须是 auto 或 #RRGGBB,例如 #000000 / #FFFFFF") try: return tuple(int(text[i : i + 2], 16) for i in (0, 2, 4)) # type: ignore[return-value] except ValueError: - die("颜色必须是有效十六进制,例如 #FFFFFF") + die("颜色必须是有效十六进制,例如 #000000 / #FFFFFF") + + +def auto_contrast_color(image_path: Path, threshold: float = 150.0) -> Tuple[int, int, int]: + Image, _, _ = ensure_pillow() + with Image.open(image_path) as src: + r, g, b = src.convert("RGB").resize((1, 1)).getpixel((0, 0)) + luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b + return (0, 0, 0) if luminance >= threshold else (255, 255, 255) def load_font(ImageFont: Any, font_path: Optional[str], font_size: int) -> Any: @@ -173,11 +183,11 @@ def build_parser() -> argparse.ArgumentParser: parser.add_argument("--output", required=True, help="输出图片文件或目录。目录模式会保持相对路径。") parser.add_argument("--text", default="MAOMOMO.COM", help="水印文字,默认 MAOMOMO.COM。") parser.add_argument("--angle", type=float, default=45.0, help="水印旋转角度,默认 45。") - parser.add_argument("--alpha", type=int, default=72, help="透明度 0-255,默认 72。") - parser.add_argument("--color", default="#FFFFFF", help="水印颜色,默认 #FFFFFF。") - parser.add_argument("--font-size", type=int, default=42, help="字体大小,默认 42。") + parser.add_argument("--alpha", type=int, default=70, help="透明度 0-255,默认 70。") + parser.add_argument("--color", default="auto", help="水印颜色,默认 auto:浅底黑字、深底白字;也可指定 #000000 / #FFFFFF。") + parser.add_argument("--font-size", type=int, default=50, help="字体大小,默认 50。") parser.add_argument("--font", default=None, help="可选字体路径。") - parser.add_argument("--spacing", type=int, default=120, help="水印间距 / 内边距,默认 120。") + parser.add_argument("--spacing", type=int, default=28, help="水印间距 / 内边距,默认 28;目标是每张图至少可见 2 个完整 MAOMOMO.COM。") parser.add_argument("--quality", type=int, default=95, help="JPG/WEBP 输出质量,默认 95。") return parser @@ -187,7 +197,6 @@ def main(argv: Optional[Iterable[str]] = None) -> int: args = parser.parse_args(list(argv) if argv is not None else None) input_path = Path(args.input).expanduser().resolve() output_path = Path(args.output).expanduser().resolve() - color = parse_color(args.color) images = list(iter_images(input_path)) if not images: die(f"没有找到支持的图片:{input_path}") @@ -202,7 +211,7 @@ def main(argv: Optional[Iterable[str]] = None) -> int: text=args.text, angle=args.angle, alpha=args.alpha, - color=color, + color=auto_contrast_color(image_path) if str(args.color).lower() == "auto" else parse_color(args.color), font_size=args.font_size, font_path=args.font, spacing=args.spacing,