story-cover
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesestory-cover:小说封面生成
story-cover: Novel Cover Generation
你是小说封面设计师。根据书名和题材,调用 GPT-Image-2 一次性生成包含书名和作者名的完整封面。
核心原则:封面是读者的第一印象,一眼传达题材和氛围。
You are a novel cover designer. Based on the book title and genre, call GPT-Image-2 to generate a complete cover including the book title and author name in one go.
Core Principle: The cover is the reader's first impression, conveying the genre and atmosphere at a glance.
生成通路
Generation Pathways
- Codex 内置(优先):当前 Codex CLI 会话可调用 /
$imagegen时,直接生成并落盘;计入 Codex 通用用量,无需image_gen或OPENAI_API_KEY,也不运行GPT_IMAGE_API_KEY。curl自行调用工具,不让用户另开命令。story-cover - API 回退:仅在会话没有内置工具或用户明确指定 API 时使用,需要 。工具缺失不等于 Codex 订阅不支持生图;内置调用失败时先报告错误,不静默切换到可能收费的 API。
GPT_IMAGE_API_KEY
- Codex Built-in (Priority): When /
$imagegenis available in the current Codex CLI session, generate and save directly; counted towards Codex general usage, noimage_genorOPENAI_API_KEYrequired, and noGPT_IMAGE_API_KEYexecution.curlcalls the tool automatically, no need for users to run additional commands.story-cover - API Fallback: Only used when the session has no built-in tool or the user explicitly specifies the API, requires . Missing tools does not mean Codex subscription does not support image generation; report errors first when built-in calls fail, do not silently switch to potentially paid APIs.
GPT_IMAGE_API_KEY
输出参数与 API 回退环境变量
Output Parameters & API Fallback Environment Variables
| 变量 | 必填 | 默认 | 说明 |
|---|---|---|---|
| API 回退必填 | — | OpenAI 或兼容代理的 API Key;Codex 内置通路不用 |
| | 兼容代理时改这个 | |
| | 仅在测试新模型时覆盖 | |
| | API 回退的目标比例提示(番茄 3:4→ | |
| — | 平台固定上传像素(番茄 | |
| ✅ | — | 输出目录,建议 |
| — | 参考图本地路径或 URL;内置通路先把图片载入会话,API 回退走 |
| Variable | Required | Default | Description |
|---|---|---|---|
| Required for API fallback | — | API Key for OpenAI or compatible proxies; not needed for Codex built-in pathway |
| | Modify this for compatible proxies | |
| | Only override when testing new models | |
| | Target ratio prompt for API fallback (Tomato 3:4→ | |
| — | Fixed upload pixels for platforms (Tomato | |
| ✅ | — | Output directory, recommended |
| — | Local path or URL of reference image; built-in pathway loads the image into the session first, API fallback uses |
生成流程
Generation Process
Step 1:收集信息
Step 1: Collect Information
必填:书名、作者名(笔名)、目标平台、输出目录 (建议 ;API 回退用环境变量,内置通路直接使用当前任务值)
选填:参考图 (本地路径或 URL,设置后切换到图生图)、风格偏好、尺寸
BOOK_DIR./covers/<书名>REF_IMAGE书名和笔名是封面必需信息:缺任一必须先用 AskUserQuestion 问用户补全,不得编造或留空。
按目标平台定封面尺寸:番茄上传 600×800 是 3:4(不是 2:3),出图比例不对、平台二次裁剪就会切掉书名/笔名。
| 平台 | 上传尺寸 | 比例 | 生成 |
|---|---|---|---|
| 番茄小说 | 600×800 | 3:4 | |
| 其他平台(默认竖版) | 按平台规格 | 2:3 | |
内置通路把目标比例写进提示词;API 回退再 (很多代理会忽略、返回约 2:3)。平台有固定上传像素时设置 (番茄 )。平台尺寸最终由「导出平台上传尺寸」步骤居中裁剪+缩放保证,不依赖实际出图尺寸。 平台与题材风格见 references/cover-styles.md。
export GPT_IMAGE_SIZEUPLOAD_SIZE600x800Required: Book title, author name (pen name), target platform, output directory (recommended ; API fallback uses environment variables, built-in pathway directly uses current task values)
Optional: Reference image (local path or URL, switches to image-to-image generation when set), style preference, size
BOOK_DIR./covers/<Book Title>REF_IMAGEBook title and pen name are mandatory for the cover: If either is missing, you must ask the user to complete it using AskUserQuestion, do not fabricate or leave blank.
Set cover size according to target platform: Tomato Novel requires 600×800 upload size, which is 3:4 (not 2:3). Incorrect aspect ratio will result in the platform cropping the book title/pen name.
| Platform | Upload Size | Ratio | Recommended |
|---|---|---|---|
| Tomato Novel | 600×800 | 3:4 | |
| Other platforms (default vertical) | Follow platform specifications | 2:3 | |
Built-in pathway writes the target ratio into the prompt; API fallback uses (many proxies ignore this and return approximately 2:3). Set when the platform has fixed upload pixels (Tomato ). Platform dimensions are ultimately guaranteed by the "Export Platform Upload Size" step via center cropping + scaling, independent of actual generated image size. See references/cover-styles.md for platform and genre styles.
export GPT_IMAGE_SIZEUPLOAD_SIZE600x800Step 2:题材判定
Step 2: Genre Determination
扫描书名(必要时简介)中的关键词,对照 references/cover-styles.md 的「题材推断规则」表选定题材。
- 单题材命中 → 直接采用
- 多题材命中 → 按优先级取一:仙侠 > 西幻 > 古言 > 现言 > 都市 > 悬疑 > 科幻 > 历史 > 灵异 > 轻小说
- 零命中 → 默认
都市
Scan keywords in the book title (and synopsis if necessary), select the genre according to the "Genre Inference Rules" table in references/cover-styles.md.
- Single genre match → Directly adopt
- Multiple genre matches → Select by priority: Xianxia > Western Fantasy > Ancient Romance > Modern Romance > Urban > Suspense > Sci-Fi > History > Supernatural > Light Novel
- No matches → Default to
Urban
Step 3:构建提示词
Step 3: Build Prompt
提示词 = 文字层 + 风格层 + 画面层,全部用英文编写。
Prompt = Text Layer + Style Layer + Visual Layer, all written in English.
文字层:书名 + 作者名字体设计
Text Layer: Book Title + Author Name Font Design
在提示词中直接包含中文书名和作者名,GPT-Image-2 可直接渲染。重点描述字体风格:
Title text '书名' at top center in [书名字体风格].
Author name '作者名' at bottom center in [作者名字体风格].Include the Chinese book title and author name directly in the prompt, as GPT-Image-2 can render them. Focus on describing font styles:
Title text 'Book Title' at top center in [Book Title Font Style].
Author name 'Author Name' at bottom center in [Author Name Font Style].书名字体风格
Book Title Font Styles
| 题材 | 描述关键词 |
|---|---|
| 玄幻/仙侠 | |
| 都市 | |
| 古言/宫斗 | |
| 现言/甜宠 | |
| 悬疑/推理 | |
| 科幻/末世 | |
| 西幻 | |
| 历史/军事 | |
| 灵异/恐怖 | |
| 轻小说 | |
| Genre | Description Keywords |
|---|---|
| Xuanhuan/Xianxia | |
| Urban | |
| Ancient Romance/Palace Fight | |
| Modern Romance/Sweet Pet | |
| Suspense/Mystery | |
| Sci-Fi/Post-Apocalyptic | |
| Western Fantasy | |
| History/Military | |
| Supernatural/Horror | |
| Light Novel | |
作者名字体风格(重点:作者名必须精心设计,不能只是"小字")
Author Name Font Styles (Key: Author name must be carefully designed, not just "small text")
作者名虽小,但是封面专业感的关键。必须指定:字体 + 颜色 + 装饰元素,让作者名与书名风格呼应但不抢焦点。
| 题材 | 作者名风格提示词 |
|---|---|
| 玄幻/仙侠 | |
| 都市 | |
| 古言/宫斗 | |
| 现言/甜宠 | |
| 悬疑/推理 | |
| 科幻/末世 | |
| 西幻 | |
| 历史/军事 | |
| 灵异/恐怖 | |
| 轻小说 | |
作者名通用规则:
- 大小:(不能太大抢书名焦点,也不能太小看不清)
small - 位置:,与画面底部保持适当间距
at bottom center - 必须有装饰元素:线条/边框/小图标/光效中至少一种
- 颜色与背景形成对比但不刺眼
Although small, the author name is crucial for the cover's professionalism. Must specify: Font + Color + Decorative Elements, making the author name echo the title style without stealing the focus.
| Genre | Author Name Style Prompt |
|---|---|
| Xuanhuan/Xianxia | |
| Urban | |
| Ancient Romance/Palace Fight | |
| Modern Romance/Sweet Pet | |
| Suspense/Mystery | |
| Sci-Fi/Post-Apocalyptic | |
| Western Fantasy | |
| History/Military | |
| Supernatural/Horror | |
| Light Novel | |
General Rules for Author Name:
- Size: (not too large to steal the title's focus, nor too small to be unreadable)
small - Position: , with appropriate spacing from the bottom of the frame
at bottom center - Must have decorative elements: At least one of lines/borders/small icons/light effects
- Color contrasts with the background but is not glaring
风格层:平台风格
Style Layer: Platform Style
平台风格的描述关键词统一来自 references/cover-styles.md 的「平台风格」节,按目标平台直接取对应关键词串使用,不在本文件维护副本以免与参考文件漂移。
Platform style description keywords are uniformly taken from the "Platform Styles" section of references/cover-styles.md, directly use the corresponding keyword string according to the target platform, do not maintain a copy in this document to avoid divergence from the reference file.
画面层:题材 + 构图
Visual Layer: Genre + Composition
从 references/cover-styles.md 读取题材对应的风格标签、色彩、人物、背景描述。
构图变体(首次输出 2-3 个方案):
| 方案 | 构图 | 适合题材 |
|---|---|---|
| A | 人物特写 + 场景 | 全题材通用 |
| B | 全身像 + 动态姿势 | 玄幻、都市、西幻 |
| C | 纯场景/氛围图 | 悬疑、科幻、历史 |
Read the genre-corresponding style tags, colors, characters, and background descriptions from references/cover-styles.md.
Composition Variants (output 2-3 schemes for the first time):
| Scheme | Composition | Suitable Genres |
|---|---|---|
| A | Character Close-up + Scene | Suitable for all genres |
| B | Full-body Portrait + Dynamic Pose | Xuanhuan, Urban, Western Fantasy |
| C | Pure Scene/Atmosphere Image | Suspense, Sci-Fi, History |
完整提示词模板
Complete Prompt Template
Chinese web novel cover design, [平台风格].
Title text '{书名}' at top center in [书名字体风格].
Author name '{作者名}' at bottom center in [作者名字体风格 — 从上表选择].
[题材风格标签]. [人物描述]. [背景描述].
[色彩指令]. [光效指令].
Professional book cover, high detail digital painting, portrait [平台比例:番茄=3:4,默认=2:3] ratio, keep title and author name inside the central safe area away from edges (inner ~85%), no watermarkChinese web novel cover design, [Platform Style].
Title text '{Book Title}' at top center in [Book Title Font Style].
Author name '{Author Name}' at bottom center in [Author Name Font Style — select from above table].
[Genre Style Tags]. [Character Description]. [Background Description].
[Color Instructions]. [Light Effect Instructions].
Professional book cover, high detail digital painting, portrait [Platform Ratio: Tomato=3:4, default=2:3] ratio, keep title and author name inside the central safe area away from edges (inner ~85%), no watermark提示词技巧(实测验证)
Prompt Tips (Tested and Verified)
- 人物描述越具体越好:服饰、姿态、发型、表情、道具每个维度都指定
- 背景分层:前景(人物)→ 中景(场景)→ 远景(氛围)
- 光效是指定光源方向 + 颜色(如 )
dramatic golden light from above - 用 而非
digital painting style,避免真人照片感photo
- The more specific the character description, the better: Specify each dimension of clothing, posture, hairstyle, expression, props
- Layered background: Foreground (characters) → Middle Ground (scene) → Background (atmosphere)
- Light effects specify light source direction + color (e.g., )
dramatic golden light from above - Use instead of
digital painting styleto avoid real photo feelphoto
Step 4:生成并保存
Step 4: Generate and Save
Codex 内置 ImageGen(优先)
Codex Built-in ImageGen (Priority)
- 用 Step 3 的完整提示词调用 。比例和安全区写进提示词,不传
image_gen、GPT_IMAGE_MODEL、GPT_IMAGE_SIZE等 API 参数。response_format - 有 时,本地文件先用图片查看工具载入会话;URL 先下载再载入。说明它是编辑目标还是风格参考,并列出必须保持的内容。
REF_IMAGE - 每个构图方案单独调用一次。先创建 ,再把工具返回的图片复制为
BOOK_DIR/封面/,封面_vN.png自增且不覆盖旧版;保留N原文件,同时保存同名$CODEX_HOME/generated_images/,有参考图再保存.prompt.txt。确认图片可读,并把原图绝对路径交给 Step 5。.ref.txt
- Call with the complete prompt from Step 3. Write the ratio and safe area into the prompt, do not pass API parameters like
image_gen,GPT_IMAGE_MODEL,GPT_IMAGE_SIZE.response_format - When is provided, load local files into the session using an image viewer first; download URLs first then load. Explain whether it is an editing target or style reference, and list the content that must be retained.
REF_IMAGE - Call the tool separately for each composition scheme. Create first, then copy the tool-returned image as
BOOK_DIR/封面/, where封面_vN.pngincrements and does not overwrite old versions; retain the original file inN, and save a corresponding$CODEX_HOME/generated_images/file, plus.prompt.txtif there is a reference image. Confirm the image is readable, and pass the absolute path of the original image to Step 5..ref.txt
API 回退
API Fallback
gpt-image-2response_format$PROMPT两种调用方式二选一:未设置 → 走「文生图」;设置了 → 走「图生图」。
REF_IMAGEgpt-image-2response_format$PROMPTChoose one of the two calling methods: If is not set → Use "text-to-image"; if set → Use "image-to-image".
REF_IMAGE文生图(默认)
Text-to-Image (Default)
bash
set -euo pipefail
: "${GPT_IMAGE_API_KEY:?请设置 export GPT_IMAGE_API_KEY=你的key}"
: "${PROMPT:?请先 export PROMPT=构建提示词步骤拼好的完整提示词}"
BASE_URL="${GPT_IMAGE_BASE_URL:-https://api.openai.com/v1}"
MODEL="${GPT_IMAGE_MODEL:-gpt-image-2}"
SIZE="${GPT_IMAGE_SIZE:-1024x1536}"
BOOK_DIR="${BOOK_DIR:?请先 export BOOK_DIR=./covers/<书名>}"
mkdir -p "$BOOK_DIR/封面"bash
set -euo pipefail
: "${GPT_IMAGE_API_KEY:?Please set export GPT_IMAGE_API_KEY=your-key}"
: "${PROMPT:?Please first export PROMPT=complete-prompt-assembled-in-build-prompt-step}"
BASE_URL="${GPT_IMAGE_BASE_URL:-https://api.openai.com/v1}"
MODEL="${GPT_IMAGE_MODEL:-gpt-image-2}"
SIZE="${GPT_IMAGE_SIZE:-1024x1536}"
BOOK_DIR="${BOOK_DIR:?Please first export BOOK_DIR=./covers/<Book Title>}"
mkdir -p "$BOOK_DIR/封面"自增版本号,避免覆盖之前生成的封面
Auto-increment version number to avoid overwriting previously generated covers
i=1
while [ -f "$BOOK_DIR/封面/封面_v${i}.png" ]; do i=$((i+1)); done
OUT="$BOOK_DIR/封面/封面_v${i}.png"
RESP=$(mktemp)
trap 'rm -f "$RESP"' EXIT
i=1
while [ -f "$BOOK_DIR/封面/封面_v${i}.png" ]; do i=$((i+1)); done
OUT="$BOOK_DIR/封面/封面_v${i}.png"
RESP=$(mktemp)
trap 'rm -f "$RESP"' EXIT
用 jq 拼 JSON 体,避免 PROMPT 里的引号/换行/中文把 shell 字符串撑破
Use jq to assemble JSON body to avoid shell string issues caused by quotes/newlines/Chinese in PROMPT
BODY=$(jq -n
--arg m "$MODEL"
--arg p "$PROMPT"
--arg s "$SIZE"
'{model:$m, prompt:$p, size:$s}')
--arg m "$MODEL"
--arg p "$PROMPT"
--arg s "$SIZE"
'{model:$m, prompt:$p, size:$s}')
curl -fsS --max-time 180 --retry 2 --retry-delay 5
"$BASE_URL/images/generations"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
-H "Content-Type: application/json"
-d "$BODY" > "$RESP"
"$BASE_URL/images/generations"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
-H "Content-Type: application/json"
-d "$BODY" > "$RESP"
BODY=$(jq -n
--arg m "$MODEL"
--arg p "$PROMPT"
--arg s "$SIZE"
'{model:$m, prompt:$p, size:$s}')
--arg m "$MODEL"
--arg p "$PROMPT"
--arg s "$SIZE"
'{model:$m, prompt:$p, size:$s}')
curl -fsS --max-time 180 --retry 2 --retry-delay 5
"$BASE_URL/images/generations"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
-H "Content-Type: application/json"
-d "$BODY" > "$RESP"
"$BASE_URL/images/generations"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
-H "Content-Type: application/json"
-d "$BODY" > "$RESP"
API 出错时早退,避免把 error JSON 当成 base64 写成损坏 PNG
Exit early if API error occurs, avoid writing error JSON as damaged PNG
if jq -e '.error' "$RESP" >/dev/null 2>&1; then
echo "API error:" >&2
jq '.error' "$RESP" >&2
exit 1
fi
if jq -e '.error' "$RESP" >/dev/null 2>&1; then
echo "API error:" >&2
jq '.error' "$RESP" >&2
exit 1
fi
// empty
让缺失字段输出空串而非 "null",配合下面的 -s 检查避免写出 3 字节假 PNG
// empty// empty
makes missing fields output empty string instead of "null",配合下面的 -s 检查避免写出 3 字节假 PNG
// emptyjq -er '.data[0].b64_json // empty' "$RESP" | base64 --decode > "$OUT"
[ -s "$OUT" ] || { echo "empty or malformed output: $OUT" >&2; head -c 300 "$RESP" >&2; exit 1; }
jq -er '.data[0].b64_json // empty' "$RESP" | base64 --decode > "$OUT"
[ -s "$OUT" ] || { echo "empty or malformed output: $OUT" >&2; head -c 300 "$RESP" >&2; exit 1; }
落地提示词副本,方便迭代时基于上一次微调
Save a copy of the prompt for easy fine-tuning based on the previous version during iteration
printf '%s\n' "$PROMPT" > "${OUT%.png}.prompt.txt"
file "$OUT"
ls -lt "$BOOK_DIR/封面/"
undefinedprintf '%s\n' "$PROMPT" > "${OUT%.png}.prompt.txt"
file "$OUT"
ls -lt "$BOOK_DIR/封面/"
undefined图生图(提供参考图时)
Image-to-Image (When Reference Image is Provided)
/v1/images/editsmultipart/form-dataContent-Type: application/json--form-string@-F image=@pathbash
set -euo pipefail
: "${GPT_IMAGE_API_KEY:?请设置 export GPT_IMAGE_API_KEY=你的key}"
: "${PROMPT:?请先 export PROMPT=构建提示词步骤拼好的完整提示词}"
BASE_URL="${GPT_IMAGE_BASE_URL:-https://api.openai.com/v1}"
MODEL="${GPT_IMAGE_MODEL:-gpt-image-2}"
SIZE="${GPT_IMAGE_SIZE:-1024x1536}"
BOOK_DIR="${BOOK_DIR:?请先 export BOOK_DIR=./covers/<书名>}"
REF_IMAGE="${REF_IMAGE:?请先 export REF_IMAGE=本地路径或 URL}"
mkdir -p "$BOOK_DIR/封面"/v1/images/editsmultipart/form-dataContent-Type: application/json--form-string@-F image=@pathbash
set -euo pipefail
: "${GPT_IMAGE_API_KEY:?请设置 export GPT_IMAGE_API_KEY=你的key}"
: "${PROMPT:?请先 export PROMPT=构建提示词步骤拼好的完整提示词}"
BASE_URL="${GPT_IMAGE_BASE_URL:-https://api.openai.com/v1}"
MODEL="${GPT_IMAGE_MODEL:-gpt-image-2}"
SIZE="${GPT_IMAGE_SIZE:-1024x1536}"
BOOK_DIR="${BOOK_DIR:?请先 export BOOK_DIR=./covers/<书名>}"
REF_IMAGE="${REF_IMAGE:?请先 export REF_IMAGE=本地路径或 URL}"
mkdir -p "$BOOK_DIR/封面"自增版本号
Auto-increment version number
i=1
while [ -f "$BOOK_DIR/封面/封面_v${i}.png" ]; do i=$((i+1)); done
OUT="$BOOK_DIR/封面/封面_v${i}.png"
RESP=$(mktemp)
REF_TMP=""
trap '[ -n "$REF_TMP" ] && rm -f "$REF_TMP"; rm -f "$RESP"' EXIT
i=1
while [ -f "$BOOK_DIR/封面/封面_v${i}.png" ]; do i=$((i+1)); done
OUT="$BOOK_DIR/封面/封面_v${i}.png"
RESP=$(mktemp)
REF_TMP=""
trap '[ -n "$REF_TMP" ] && rm -f "$REF_TMP"; rm -f "$RESP"' EXIT
URL 先下载到临时文件,本地路径直接用。用裸 mktemp 以保证 macOS/Linux 行为一致。
Download URLs to temporary files first, use local paths directly. Use bare mktemp to ensure consistent behavior on macOS/Linux.
case "$REF_IMAGE" in
http://|https://)
REF_TMP=$(mktemp)
curl -fsSL --max-time 60 -o "$REF_TMP" "$REF_IMAGE"
REF_LOCAL="$REF_TMP"
;;
*)
[ -f "$REF_IMAGE" ] || { echo "参考图不存在: $REF_IMAGE" >&2; exit 1; }
REF_LOCAL="$REF_IMAGE"
;;
esac
curl -fsS --max-time 240 --retry 2 --retry-delay 5
"$BASE_URL/images/edits"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
--form-string "model=$MODEL"
--form-string "size=$SIZE"
--form-string "prompt=$PROMPT"
-F "image=@$REF_LOCAL" > "$RESP"
"$BASE_URL/images/edits"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
--form-string "model=$MODEL"
--form-string "size=$SIZE"
--form-string "prompt=$PROMPT"
-F "image=@$REF_LOCAL" > "$RESP"
if jq -e '.error' "$RESP" >/dev/null 2>&1; then
echo "API error:" >&2
jq '.error' "$RESP" >&2
exit 1
fi
case "$REF_IMAGE" in
http://|https://)
REF_TMP=$(mktemp)
curl -fsSL --max-time 60 -o "$REF_TMP" "$REF_IMAGE"
REF_LOCAL="$REF_TMP"
;;
*)
[ -f "$REF_IMAGE" ] || { echo "参考图不存在: $REF_IMAGE" >&2; exit 1; }
REF_LOCAL="$REF_IMAGE"
;;
esac
curl -fsS --max-time 240 --retry 2 --retry-delay 5
"$BASE_URL/images/edits"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
--form-string "model=$MODEL"
--form-string "size=$SIZE"
--form-string "prompt=$PROMPT"
-F "image=@$REF_LOCAL" > "$RESP"
"$BASE_URL/images/edits"
-H "Authorization: Bearer $GPT_IMAGE_API_KEY"
--form-string "model=$MODEL"
--form-string "size=$SIZE"
--form-string "prompt=$PROMPT"
-F "image=@$REF_LOCAL" > "$RESP"
if jq -e '.error' "$RESP" >/dev/null 2>&1; then
echo "API error:" >&2
jq '.error' "$RESP" >&2
exit 1
fi
// empty
让缺失字段输出空串而非 "null",配合 -s 检查避免写出 3 字节假 PNG
// empty// empty
makes missing fields output empty string instead of "null",配合 -s 检查避免写出 3 字节假 PNG
// emptyjq -er '.data[0].b64_json // empty' "$RESP" | base64 --decode > "$OUT"
[ -s "$OUT" ] || { echo "empty or malformed output: $OUT" >&2; head -c 300 "$RESP" >&2; exit 1; }
printf '%s\n' "$PROMPT" > "${OUT%.png}.prompt.txt"
printf '%s\n' "$REF_IMAGE" > "${OUT%.png}.ref.txt"
file "$OUT"
ls -lt "$BOOK_DIR/封面/"
undefinedjq -er '.data[0].b64_json // empty' "$RESP" | base64 --decode > "$OUT"
[ -s "$OUT" ] || { echo "empty or malformed output: $OUT" >&2; head -c 300 "$RESP" >&2; exit 1; }
printf '%s\n' "$PROMPT" > "${OUT%.png}.prompt.txt"
printf '%s\n' "$REF_IMAGE" > "${OUT%.png}.ref.txt"
file "$OUT"
ls -lt "$BOOK_DIR/封面/"
undefinedStep 5:导出平台上传尺寸(平台有固定像素时)
Step 5: Export Platform Upload Size (When Platform Has Fixed Pixels)
平台有固定上传像素(番茄 600×800)时,把原图居中裁剪+缩放成上传尺寸——不论出图是 2:3 还是 3:4 都裁成平台精确像素,不变形,避免平台再裁切掉书名/笔名。原图保留、另存 版; 和 直接使用前序步骤的任务值,不依赖跨 shell 的临时变量:
_上传SRCTARGETbash
SRC='<Step 4 生成的原图绝对路径>'
TARGET='<Step 1 确定的平台上传尺寸;无则留空>'
[ -f "$SRC" ] || { echo "封面原图不存在: $SRC" >&2; exit 1; }
if [ -n "$TARGET" ] && [ -f "$SRC" ]; then
UP="${SRC%.png}_上传.png"; W="${TARGET%x*}"; H="${TARGET#*x}"
if command -v magick >/dev/null 2>&1; then M=magick
elif command -v convert >/dev/null 2>&1; then M=convert; else M=""; fi
if [ -n "$M" ]; then
"$M" "$SRC" -resize "${W}x${H}^" -gravity center -extent "${W}x${H}" "$UP" # 缩放填满后居中裁
elif command -v sips >/dev/null 2>&1; then
cp "$SRC" "$UP"
sw=$(sips -g pixelWidth "$UP" | awk '/pixelWidth/{print $NF}')
sh=$(sips -g pixelHeight "$UP" | awk '/pixelHeight/{print $NF}')
if [ $((sw*H)) -ge $((sh*W)) ]; then sips --resampleHeight "$H" "$UP" >/dev/null
else sips --resampleWidth "$W" "$UP" >/dev/null; fi
sips -c "$H" "$W" "$UP" >/dev/null # sips -c 是 高 宽,居中裁
else
echo "无 magick/convert/sips,跳过;手动把 $SRC 居中裁剪+缩放到 $TARGET 再上传" >&2
fi
[ -f "$UP" ] && file "$UP"
fi书名/笔名已在提示词里留中心安全区,居中裁剪不会切到。
When the platform has fixed upload pixels (Tomato 600×800), center crop + scale the original image to the upload size — regardless of whether the generated image is 2:3 or 3:4, crop it to the platform's exact pixels without distortion, to avoid the platform cropping the book title/pen name. Retain the original image, save a separate version; and directly use task values from previous steps, do not rely on cross-shell temporary variables:
_上传SRCTARGETbash
SRC='<Absolute path of original image generated in Step 4>'
TARGET='<Platform upload size determined in Step 1; leave blank if none>'
[ -f "$SRC" ] || { echo "封面原图不存在: $SRC" >&2; exit 1; }
if [ -n "$TARGET" ] && [ -f "$SRC" ]; then
UP="${SRC%.png}_上传.png"; W="${TARGET%x*}"; H="${TARGET#*x}"
if command -v magick >/dev/null 2>&1; then M=magick
elif command -v convert >/dev/null 2>&1; then M=convert; else M=""; fi
if [ -n "$M" ]; then
"$M" "$SRC" -resize "${W}x${H}^" -gravity center -extent "${W}x${H}" "$UP" # Scale to fill then center crop
elif command -v sips >/dev/null 2>&1; then
cp "$SRC" "$UP"
sw=$(sips -g pixelWidth "$UP" | awk '/pixelWidth/{print $NF}')
sh=$(sips -g pixelHeight "$UP" | awk '/pixelHeight/{print $NF}')
if [ $((sw*H)) -ge $((sh*W)) ]; then sips --resampleHeight "$H" "$UP" >/dev/null
else sips --resampleWidth "$W" "$UP" >/dev/null; fi
sips -c "$H" "$W" "$UP" >/dev/null # sips -c is height first, width second, center crop
else
echo "无 magick/convert/sips,跳过;手动把 $SRC 居中裁剪+缩放到 $TARGET 再上传" >&2
fi
[ -f "$UP" ] && file "$UP"
fiThe book title/pen name have been placed in the central safe area in the prompt, so center cropping will not cut them.
Step 6:质量检查 + 迭代
Step 6: Quality Check + Iteration
| 检查项 | 标准 |
|---|---|
| 文字渲染 | 书名清晰可辨,字体风格匹配题材 |
| 题材匹配 | 视觉风格与书名题材一致 |
| 构图合理 | 主体突出,文字不遮挡核心画面 |
| 平台适配 | 符合目标平台的封面风格调性 |
| 平台尺寸 | 比例与平台一致;缩放到上传尺寸后书名、笔名完整可见、未被裁切 |
不满意时调整方向:更换构图、调整色调、换字体风格、换平台风格。
| Check Item | Standard |
|---|---|
| Text Rendering | Book title is clearly recognizable, font style matches the genre |
| Genre Matching | Visual style is consistent with the book title's genre |
| Reasonable Composition | Main subject is prominent, text does not block core visuals |
| Platform Adaptation | Conforms to the target platform's cover style and tone |
| Platform Dimensions | Ratio matches the platform; after scaling to upload size, book title and author name are fully visible and not cropped |
When unsatisfied, adjust directions: Change composition, adjust color tone, switch font style, change platform style.
参考资料
Reference Materials
| 文件 | 何时加载 |
|---|---|
| references/cover-styles.md | 题材→视觉风格映射、平台风格详情、提示词模板 |
| File | When to Load |
|---|---|
| references/cover-styles.md | Genre→visual style mapping, platform style details, prompt templates |
语言
Language
- 跟随用户的语言回复,用户用什么语言就用什么语言回复
- 中文回复遵循《中文文案排版指北》
- Reply in the user's language; use the same language as the user's input
- Follow Chinese Copywriting Guidelines for Chinese replies