GPT-IMAGE-1 从文本到海报的完整实现:提示词、布局与后处理

文章导读
用 GPT-IMAGE-1 做海报的一条可行路径是:先生成一张干净、没有文字的底图,再用 Pillow 在后处理阶段叠加标题和规范排版。这样做的原因是生成模型对中文长句、精确字号和边距的控制不稳定,与其让它硬画文字,不如把文字层交给确定性的代码处理。
📋 目录
  1. 从文案拆分海报层次
  2. 编写生成海报底图的提示词
  3. 用Pillow叠加标题文字
  4. 统一输出尺寸与导出格式
  5. 批量处理多句文案
A A

用 GPT-IMAGE-1 做海报的一条可行路径是:先生成一张干净、没有文字的底图,再用 Pillow 在后处理阶段叠加标题和规范排版。这样做的原因是生成模型对中文长句、精确字号和边距的控制不稳定,与其让它硬画文字,不如把文字层交给确定性的代码处理。

适用场景:文案已确定、需要固定尺寸和可复用模板的海报。操作动作:第一步写提示词生成留白充足的底图,第二步用 Pillow 做文字换行、居中和导出。验证方式:将生成图和脚本输出叠加后检查文字是否完整、是否在安全边距内。风险边界:图片生成结果存在随机性,主体遮挡预留空间时需要重新抽卡或局部重绘;中文字体文件需要单独准备,系统默认字体通常不含完整字形。

从文案拆分海报层次

动手写提示词之前,先把文案分成三层:主标题、副标题、装饰性元素。主标题通常不超过 12 个字,是画面里最大的文字,对应正片叠底的视觉重心;副标题可以是一句话或一组短句,承担补充信息;装饰性元素指日期、地点、口号等小字,不作为阅读主体。

这三层在画面里要有明确的分配:主标题占据画面上部或中部的留白区,副标题放在主标题下方,装饰元素靠边放置。底图生成时只需要为主标题和副标题预留空间,装饰小字可以让 Pillow 在后期放进固定角落,不需要在提示词里描述。

判断一张底图是否可用,看两个点:主体是否完整且不压住预留文字区;画面整体是否有足够的单色或渐变区域作为文字背景。如果背景过花,Pillow 叠加文字后会出现可读性问题。

编写生成海报底图的提示词

提示词的任务不是生成海报成品,而是生成“没有文字的背景图”。核心是强调留白、纯色区域和主体位置,并且尽量排除文字出现的可能。

推荐的结构是:主体 + 环境 + 构图 + 留白要求 + 禁止文字。

Poster background, minimalist product photography of a coffee cup on a wooden table, soft warm light, large empty space in upper half for text, solid light beige background gradient, clean composition, no text, no typography, no letters, no watermark

如果你的场景需要中文提示词,也可以写成:

海报底图,极简风格,一杯咖啡放在木桌上,柔和暖光,画面上半部留白,浅米色渐变背景,干净构图,没有文字,没有字母,没有水印

注意“no text”这类否定词对生成模型只是弱约束,返回图仍可能出现乱码文字。生成后需要人工检查,如果出现不明文字,优先抽卡重试,而不是直接进入叠加步骤。

生成尺寸建议直接设为最终海报的画布比例,例如 A 系列纸张的宽高比,减少后期裁剪带来的构图损失。

用Pillow叠加标题文字

Pillow 负责把文案渲染到底图上。首先需要加载中文字体文件,Windows 通常使用 simhei.ttf 或 msyh.ttc,macOS 使用 PingFang.ttc。如果没有字体文件,可以在系统字体目录里找一个可用的。

GPT-IMAGE-1 从文本到海报的完整实现:提示词、布局与后处理
from PIL import Image, ImageDraw, ImageFont

img = Image.open("background.png").convert("RGB")
draw = ImageDraw.Draw(img)
font_title = ImageFont.truetype("simhei.ttf", 96)
font_sub = ImageFont.truetype("simhei.ttf", 48)

title = "城市咖啡漫游指南"
subtitle = "2026 年春季限定"

# 计算标题居中
bbox = draw.textbbox((0, 0), title, font=font_title)
tw = bbox[2] - bbox[0]
th = bbox[3] - bbox[1]
x = (img.width - tw) / 2
y = 180
draw.text((x, y), title, font=font_title, fill=(40, 40, 40))

# 副标题居中在标题下方
bbox2 = draw.textbbox((0, 0), subtitle, font=font_sub)
sw = bbox2[2] - bbox2[0]
sh = bbox2[3] - bbox2[1]
draw.text(((img.width - sw) / 2, y + th + 40), subtitle, font=font_sub, fill=(80, 80, 80))

img.save("poster.png")

如果文案超过一行,需要先按最大宽度换行,再逐行居中绘制。简单换行可以按字符数切,精确做法是逐个字符累计宽度。

def draw_centered_multiline(draw, text, font, max_width, start_y, fill):
    lines = []
    line = ""
    for ch in text:
        test = line + ch
        w = draw.textbbox((0, 0), test, font=font)[2]
        if w <= max_width or not line:
            line = test
        else:
            lines.append(line)
            line = ch
    if line:
        lines.append(line)

    line_height = font.getbbox("中")[3] + 10
    y = start_y
    for ln in lines:
        w = draw.textbbox((0, 0), ln, font=font)[2]
        draw.text(((draw.textbbox((0, 0), "", font=font)[0] + 0) + (max_width - w) / 2, y), ln, font=font, fill=fill)
        draw.text((0, y), ln, font=font, fill=fill)
        y += line_height

注意:不同 Pillow 版本的 textbbox 行为略有差异,建议先在本地跑一次小样,确认文字起点没有偏移。

统一输出尺寸与导出格式

海报的最终用途决定输出尺寸和格式。先确定目标画布,比如 A4 打印需要 2480×3508 像素(300dpi),屏幕展示可以按 1080×1920 输出。底图生成后,如果尺寸不匹配,不要拉伸,而是用中心裁剪或补边。

target_w, target_h = 2480, 3508
bg = Image.open("background.png")
# 中心裁剪到目标比例
ratio = target_w / target_h
if bg.width / bg.height > ratio:
    new_w = int(bg.height * ratio)
    left = (bg.width - new_w) // 2
    bg = bg.crop((left, 0, left + new_w, bg.height))
else:
    new_h = int(bg.width / ratio)
    top = (bg.height - new_h) // 2
    bg = bg.crop((0, top, bg.width, top + new_h))
bg = bg.resize((target_w, target_h), Image.LANCZOS).convert("RGB")

导出一张最终海报时,PNG 适合屏幕和印刷排版,PDF 适合直接送印。Pillow 保存 PDF 时要注意文件名后缀 .pdf,并设置分辨率。

final.save("poster.pdf", "PDF", resolution=300)
# 或保存 PNG
final.save("poster.png", "PNG")

如果交付给印刷厂,建议先确认对方接受的色彩空间和出血要求。Pillow 默认 RGB,印刷通常需要 CMYK,但 Pillow 的 CMYK 转换并不精确,最好在导出前用专业工具或由印刷方处理。

批量处理多句文案

把上面的文字叠加逻辑封装成函数,再循环读取文案列表,就能一次生成多张海报。文案列表可以是纯文本文件,每行一组标题和副标题,用逗号或制表符分隔。

def make_poster(bg_path, title, subtitle, out_path):
    img = Image.open(bg_path).convert("RGB")
    draw = ImageDraw.Draw(img)
    # ... 省略换行和居中逻辑 ...
    img.save(out_path)

with open("copy_list.txt", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        title, subtitle = line.split("\t")
        make_poster("background.png", title, subtitle, f"poster_{title[:4]}.png")

批量操作时需要注意文件命名冲突和字体缓存。如果一次生成几十张,建议输出到一个独立目录,并在循环中打印进度,方便定位失败任务。遇到空段落或换行符异常时,先做数据清洗,避免脚本中断。

这个流程的核心是把“生成底图”和“排版文字”分开,前者用 GPT-IMAGE-1 的可控性较差但视觉丰富,后者用 Pillow 完全可控。只要底图留白足够、文字内容固定,批量海报的生产效率就能稳定下来。