# 图改图 (Image-to-Image)

> 给一张原图 + 一句指令拿回改过的图 —— gpt-image-2 / Seedream / Nano-Banana 在 /v1/images/generations 与 /v1/images/edits 上的完整用法与示例

来源：https://model.dflop.top/docs/guides/image-editing

「图改图」= 给模型**一张或多张参考图** + 一句编辑指令,拿回改过的新图(换色、替换元素、风格迁移、多图融合)。本平台有**两个端点**可用,底下是同一条管线:

| 端点 | 传参形态 | 什么时候用它 |
|---|---|---|
| `POST /v1/images/generations` | JSON,参考图放 `image` 数组 | 手写 HTTP 请求最省事;**不传 `image` 就是文生图**,同一个端点两用 |
| `POST /v1/images/edits` | JSON **或** `multipart/form-data` | 想直接用 OpenAI SDK 的 `client.images.edit(image=...)`;或想直接上传本地文件字节,不做 base64 |

两个端点的**模型、计费、渠道阶梯、`Idempotency-Key` 幂等、错误形状完全一致** —— `/v1/images/edits` 只是把 multipart 归一化成同一个 JSON 信封再往下走。唯一的行为差别:在 `/v1/images/edits` 上不带参考图会直接 **400**(那里缺参考图是调用方的 bug,不会静默降级成文生图);在 `/v1/images/generations` 上不带 `image` 则正常按文生图处理。

> **旧文档更正(2026-08-02)**:本页此前写着「`gpt-image-2` 只能文生图,平台没有 `/v1/images/edits`」。**该结论已作废** —— 根因是我们当时只探测了上游的 `/images/generations` 一条端点(参考图只在上游的 edits 面被解析),把自己的配置缺失记成了模型的能力上限。现在 `gpt-image-2` 的图改图已在生产验证并上线,两个端点都可用。

---

## 方案一:gpt-image-2(推荐)

`gpt-image-2` 同时吃**公网 URL** 和 **base64 data URI**,两个端点都能进,$0.059/张,**参考图不额外计费**(带 1 张和带 10 张同价)。

### 请求(`/v1/images/generations`)

```json
{
  "model": "gpt-image-2",
  "prompt": "把沙发改成蓝色,其余保持不变。画面比例:3:2(横构图)",
  "image": ["https://your-host.com/original.png"]
}
```

| 字段 | 必填 | 说明 |
|---|---|---|
| `model` | ✓ | `gpt-image-2` |
| `prompt` | ✓ | 编辑指令。**想控制画幅比例,写进这里**(见下方「尺寸与比例」) |
| `image` | ✓(图改图) | 参考图:字符串或数组;每项是公网 https URL 或 `data:image/png;base64,...`。不传 = 文生图 |
| `image_urls` | | `image` 的等价写法(数组),两者会被合并,顺序保留 |
| `n` | | 张数,默认 1,上限 10。提交按 `单价 × n` 预扣,**结算按实际返回张数** |
| `size` | | 会原样透传,但**上游对 gpt-image-2 不遵守它**(见下) |

### curl

```bash
curl https://api.dflop.top/v1/images/generations \
  -H "Authorization: Bearer $PLATFORM_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 300 \
  -d '{
    "model": "gpt-image-2",
    "prompt": "把沙发改成蓝色,其余保持不变。画面比例:3:2(横构图)",
    "image": ["https://your-host.com/original.png"]
  }'
```

响应是 OpenAI Images 形状,`data[].url` 就是改后的图(实测原样返回):

```json
{
  "created": 1765432100,
  "expires_at": 1765518500,
  "data": [
    {
      "url": "https://r2.dflop.top/gateway/images/ephemeral/ab2f1e08-....png",
      "revised_prompt": "..."
    }
  ],
  "usage": {
    "input_tokens": 1103,
    "input_tokens_details": { "image_tokens": 1024, "text_tokens": 79 },
    "output_tokens": 229,
    "total_tokens": 1332
  }
}
```

> `usage.input_tokens_details.image_tokens > 0` 说明参考图**确实被消费**了。这是判断「改图有没有真生效」最可靠的机器判据 —— 它 `0` 而图又变了,那是模型按 prompt 重画,不是在改你的图。实测:一张 768×768 参考图 = 1024,一张 1254×1254 = 1521。(参考图 ≥8 张时上游的用量统计会塌成 0,那是它的统计 bug,不代表丢图。)
>
> ⚠️ `data[]` 里**没有 `size` 字段**(与 Seedream 不同),要知道实际尺寸得自己解码图片。

### 用 OpenAI 官方 SDK(`/v1/images/edits`,直接传本地文件)

不用自己拼 base64 —— SDK 的 `images.edit()` 发的就是 multipart,本平台原生收:

```python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["PLATFORM_API_KEY"],
    base_url="https://api.dflop.top/v1",
    timeout=300.0,                      # gpt-image-2 实测 30–215 秒,别用默认超时
)

result = client.images.edit(
    model="gpt-image-2",
    image=open("original.png", "rb"),   # 多张就传 [open(a,"rb"), open(b,"rb")]
    prompt="把沙发改成蓝色,其余保持不变。画面比例:3:2(横构图)",
)
print(result.data[0].url)
```

```typescript
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.PLATFORM_API_KEY,
  baseURL: "https://api.dflop.top/v1",
  timeout: 300_000,
});

const result = await client.images.edit({
  model: "gpt-image-2",
  image: fs.createReadStream("original.png"),
  prompt: "把沙发改成蓝色,其余保持不变。画面比例:3:2(横构图)",
});
console.log(result.data[0].url);
```

纯 curl 走 multipart 也一样(字段名 `image`,多张用 `image[]`):

```bash
curl https://api.dflop.top/v1/images/edits \
  -H "Authorization: Bearer $PLATFORM_API_KEY" \
  --max-time 300 \
  -F "model=gpt-image-2" \
  -F "prompt=把沙发改成蓝色,其余保持不变" \
  -F "image[]=@original.png" \
  -F "image[]=@style-reference.png"
```

### 图床不公开?用 data URI

参考图给的是 URL 时,**去拉这张图的是上游的服务器,不是我们的网关** —— 你能打开、我们能打开,都不代表上游能打开。国内对象存储、内网地址、需要鉴权或挡爬虫的图床、短时效签名链接,典型报错是上游 400 `Unable to download content from the provided URL`。

这种情况**改传字节**(data URI 或上面的 multipart),不要在 URL 上纠缠:

```bash
B64=$(base64 -i original.png | tr -d '\n')
curl https://api.dflop.top/v1/images/edits \
  -H "Authorization: Bearer $PLATFORM_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 300 \
  -d "{
    \"model\": \"gpt-image-2\",
    \"prompt\": \"把沙发改成蓝色,其余保持不变\",
    \"image\": [\"data:image/png;base64,$B64\"]
  }"
```

### 尺寸与比例:`size` 对 gpt-image-2 无效,请写进 prompt

上游**不遵守** `gpt-image-2` 的 `size` 字段(传 `1536x1024` 可能拿回 902×1744 的竖图)。实测有效的做法是把比例写进 `prompt`,命中率极高:

```text
把沙发改成蓝色,其余保持不变。画面比例:16:9(横构图)
```

- 提示词里的比例会**压过** `size` 字段,两者冲突时以提示词为准
- 常用写法:`1:1(方图)` / `3:4(竖构图)` / `16:9(横构图)` / `9:16(竖构图)`
- 别在提示词里写 `8K` / `4K` 这类分辨率词 —— 它们不会提高实际像素,只会干扰构图
- 其它模型(Seedream / Nano)的 `size` 是正常生效的,这条只针对 `gpt-image-2`

### 多张参考图

`image` 数组按**书写顺序**送上游,顺序是契约的一部分(「第一张的人物 + 第二张的背景」这类组合指令依赖它)。实测 40 张仍能精确读到最后一张的内容,所以真正的上限不是张数,而是**请求体大小**:

- 网关请求体上限 **95 MB**;base64 编码会让字节数涨约 33%
- 真实手机照片约 3 MB/张,换算下来实际大约 **20 张**就到顶
- 计费与参考图张数**无关**:1 张和 40 张都是 $0.059/张出图价

### 计费与耗时

| 项 | 值 |
|---|---|
| 单价 | **$0.059/张**(参考图不额外计费) |
| 实测耗时 | **约 30–215 秒**(2026-08-04 三次改图实测 33s / 48s / 70s,历史峰值到 215s)—— 客户端超时请设 **≥ 300 秒** |
| 网关预算 | 单跳 240s,渠道阶梯合计 280s |
| 返回图片 | `data[].url`;`gpt-image-2` 实测返回**本平台托管的临时链接**(`https://r2.dflop.top/gateway/images/ephemeral/<uuid>.png`,**24 小时后自动清理**,响应体 `expires_at` 给出精确过期时刻)。别把它当永久图床,拿到后请转存自己的存储;过期前在 [logs.dflop.top](https://logs.dflop.top) 的回执里也能看到缩略图与链接 |

⚠️ 客户端超时设小(常见的 60s / 120s 默认值)会在网关仍在正常等待时把请求掐断:**费用照产生,图你拿不到**。

> **本页示例的实测状态(2026-08-04)**:三种传法 —— generations + data URI、edits + multipart 文件、generations + 公网 URL(用 `image_urls` 拼写)—— 全部 HTTP 200、`image_tokens > 0`,且输出保留了参考图里**提示词从未提及**的元素(只有被点名的那个物体变了色),即参考图是真被读进去编辑的,不是照提示词重画。把上一次的产出 URL 当输入再改一次(链式改图)同样可用。

---

## 方案二:Seedream / Nano-Banana

同一个 `/v1/images/generations` 端点,同样把参考图放进 `image` 数组。适合要**批量出图**(`n` 多张)或想要更低单价的场景。

### 支持图改图的模型

| Model ID | 显示名 | 价格 (每张) | 参考图传法 |
|---|---|---|---|
| `doubao-seedream-4-0-250828` | Seedream 4.0 | $0.029 | URL 或 data-URI,size ≥ 960×960 |
| `doubao-seedream-4-5-251128` | Seedream 4.5 | $0.037 | URL 或 data-URI,**size 须 ≥ 1920×1920** |
| `doubao-seedream-5-0-260128` | Seedream 5.0 | $0.032 | URL 或 data-URI,**size 须 ≥ 1920×1920** |
| `doubao-seedream-5-0-pro-260628` | Seedream 5.0 Pro | 输出 ≤236万像素 $0.044、超过 $0.088 + **输入参考图 $0.003/张** | URL 或 data-URI,size ≥ 960×960 即可 |
| `nano-banana` | Nano Banana | $0.039 | **仅公网 URL**(不接受 data-URI) |
| `nano-banana-pro` | Nano Banana Pro | $0.134 | **仅公网 URL**(不接受 data-URI) |
| `nano-banana-2` | Nano Banana 2 | $0.04 | URL 或 data-URI |

> 各模型对参考图的入参格式略有差异,**统一传公网可访问的 https URL 最稳妥**(所有模型都支持)。data-URI 仅 Seedream 全系、`nano-banana-2` 与 `gpt-image-2` 接受。

### 请求

```json
{
  "model": "doubao-seedream-4-5-251128",
  "prompt": "把沙发改成蓝色,其余保持不变",
  "image": ["https://your-host.com/original.png"],
  "size": "2048x2048"
}
```

| 字段 | 必填 | 说明 |
|---|---|---|
| `model` | ✓ | 上表任一支持图改图的 Model ID |
| `prompt` | ✓ | 编辑指令(描述你想改成什么样) |
| `image` | ✓(图改图) | 参考图数组,**1–10 张**;不传即退化为文生图 |
| `size` | | `"宽x高"`,透传上游;Seedream 4.5/5.0 须 ≥ 1920×1920 |
| `n` | | 张数,默认 1,上限 10 |

`image` 也可写作 `image_urls`(等价)。多张参考图时,上游把第一张作为主编辑对象,其余作为风格 / 元素参考。

### curl

```bash
curl https://api.dflop.top/v1/images/generations \
  -H "Authorization: Bearer $PLATFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedream-4-5-251128",
    "prompt": "把沙发改成蓝色,其余保持不变",
    "image": ["https://your-host.com/original.png"],
    "size": "2048x2048"
  }'
```

### 响应

与文生图一致的 OpenAI Images 形状,`data[].url` 即改后的图:

```json
{
  "model": "doubao-seedream-4-5-251128",
  "created": 1765432100,
  "data": [{ "url": "https://...", "size": "2048x2048" }],
  "usage": { "generated_images": 1 }
}
```

---

## 方案三:GPT-5.x 聊天 + image_generation 工具

如果你要的是「模型先**理解**图的内容,再决定怎么改」,用 `gpt-5.x` 聊天模型的内置 `image_generation` 工具 —— 把参考图作为多模态消息传入。这条按 token 计费,适合需要语义理解的复杂改图。

### 请求

```bash
curl https://api.dflop.top/v1/chat/completions \
  -H "Authorization: Bearer $PLATFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.5",
    "stream": true,
    "tools": [{ "type": "image_generation" }],
    "messages": [{
      "role": "user",
      "content": [
        { "type": "text", "text": "把这张图里的沙发改成蓝色,其余不动" },
        { "type": "image_url", "image_url": { "url": "https://your-host.com/original.png" } }
      ]
    }]
  }'
```

| 要点 | 说明 |
|---|---|
| 模型 | `gpt-5.5` / `gpt-5.6-*`(支持 `image_generation` 工具的聊天模型) |
| `stream` | **必须 `true`** —— 带 `image_generation` 工具的轮次强制走流式 |
| `tools` | 须显式带 `[{ "type": "image_generation" }]` |
| 参考图 | 放进 `content` 数组的 `image_url` 块;`url` 支持 https URL 或 `data:image/...;base64,` data-URI |
| 尺寸 | 可选:写进工具 spec `{"type":"image_generation","size":"1024x1536"}`,支持 `1024x1024` / `1024x1536` / `1536x1024` / `auto` |

### 返回

改后的图**内联在流式返回的正文里**,以 markdown 图片语法出现:

```
data: {"choices":[{"delta":{"content":"![](https://...生成图...)"}}]}
```

从累积的 `delta.content` 里正则抽取 `![](url)` 即可拿到图片链接。

> 该路径按 **token** 计费(不是按张):`image_generation` 工具一轮约 2300 输入 token 的固定开销,带参考图再叠加参考图的 vision token(约翻倍),输出 token 很小。

---

## 三条路径怎么选

| 维度 | 方案一(gpt-image-2) | 方案二(Seedream / Nano) | 方案三(GPT-5.x + 工具) |
|---|---|---|---|
| 端点 | `/v1/images/generations` 或 `/v1/images/edits` | `/v1/images/generations` | `/v1/chat/completions` |
| 调用形态 | 一次同步返回 | 一次同步返回 | 流式(SSE) |
| 计费 | $0.059/张,参考图不额外计费 | 按张($0.029–$0.134) | 按 token |
| 一次出图数 | 可 `n` 多张(≤10) | 可 `n` 多张(≤10) | 恒 1 张 |
| 参考图 | URL / data-URI / 文件上传,数十张(受体积限) | URL(部分支持 data-URI),1–10 张 | 多模态数组,多张 |
| 尺寸控制 | **只能靠 prompt 写比例** | `size` 正常生效 | 工具 spec 的 `size` |
| 耗时 | 30–215 秒 | 通常 5–20 秒 | 取决于轮次 |
| 适合场景 | GPT 风格改图、多图融合、直接传本地文件 | 快速批量改图、要精确尺寸 | 需理解图语义的精细编辑 |

一般改图需求(换色、替换元素、风格迁移):要 GPT 的画风与多图融合能力选**方案一**;要精确尺寸、要快、要批量选**方案二**。

---

## 限制

- 返回的图片 URL 一律是**临时链接**:`gpt-image-2` 实测走本平台托管的 `r2.dflop.top/gateway/images/ephemeral/…`(**24 小时后清理**,`expires_at` 是精确时刻),Seedream / Nano 等通常是上游预签名链接(**约 24 小时过期**)。两种都别当永久图床,拿到后尽快下载转存。
- 参考图给 URL 时,**该 URL 必须能被上游服务器公网访问**;拉不到会返回上游 400,改传 data URI 或 multipart 文件。
- 请求体上限 **95 MB**(base64 会让体积涨约 33%)。
- `gpt-image-2` 的 `size` 字段上游不遵守,比例请写进 prompt。
- `/v1/images/edits` 不带参考图会 **400**,错误文案是 `` `image` is required on /v1/images/edits ``(不计费),按提示改用 `/v1/images/generations` 做文生图即可。
- 出图慢(尤其 `gpt-image-2` 的 30–215 秒),**客户端超时请设 ≥ 300 秒**。
- 重试怕重复扣费就带 `Idempotency-Key`(两个端点都支持,同键重发拿回第一次的响应且不二次计费),见 [图像 / 视频 / 音乐 API](../reference/media-apis.md)。
- 若你的 Key 配置了 `allowed_models` 白名单,需先把要用的图改图模型加入白名单,否则返回 403。
- 完整的图像 / 视频 / 音乐端点说明见 [图像 / 视频 / 音乐 API](../reference/media-apis.md)。
