---
title: "生成与编辑图像"
description: "pirouter 用 OpenAI Images 协议的生成与编辑两个端点、以及 Gemini 协议的 generateContent 生成图像，按文本输入、图像输入、图像输出三类 token 计费。"
canonical: "https://pirouter.ai/zh/docs/guides/images"
last-updated: "2026-10-17"
lang: "zh"
source: "content/docs/zh/guides/images.mdx"
---

# 生成与编辑图像

pirouter 用 OpenAI Images 协议的生成与编辑两个端点、以及 Gemini 协议的 generateContent 生成图像，按文本输入、图像输入、图像输出三类 token 计费。

从一句提示词生成图像，用 OpenAI Images 协议的生成端点；要修改已有图像，用编辑端点；Gemini 图像模型也可以用 Gemini 协议的 `generateContent` 直接出图。三个入口如下：

| 端点                                            | 做什么                        | 请求体                   |
| --------------------------------------------- | -------------------------- | --------------------- |
| `POST /v1/images/generations`                 | 从一段文字生成图像（OpenAI 协议）       | JSON                  |
| `POST /v1/images/edits`                       | 上传一张或多张图像，按文字修改（OpenAI 协议） | `multipart/form-data` |
| `POST /v1beta/models/{model}:generateContent` | 对图像模型调用，回复里带图像（Gemini 协议）  | JSON                  |

下面用同一只风筝走一遍：先生成一只红风筝，再把它改成蓝色。

## 哪些模型能用

| 模型                                   | 生成 | 编辑 | Gemini 协议 |
| ------------------------------------ | -- | -- | --------- |
| `openai/gpt-image-2`                 | 是  | 是  | 否         |
| `openai/gpt-image-2.5-flare`         | 是  | 是  | 否         |
| `openai/gpt-image-2.5-sunburst`      | 是  | 是  | 否         |
| `google/gemini-3-pro-image`          | 是  | 否  | 是         |
| `google/gemini-3.1-flash-image`      | 是  | 否  | 是         |
| `google/gemini-3.1-flash-lite-image` | 是  | 否  | 是         |
| `google/gemini-nano-banana-2.1`      | 是  | 否  | 是         |

模型提供哪些端点，以 `GET /v1/models/{vendor}/{model}/endpoints` 返回的 `supported_endpoints` 为准，见[模型与协议](https://pirouter.ai/zh/docs/models.md)。用不提供该端点的模型调用，返回 `422`，`message` 会列出这个模型能用的端点。

## 生成一张图像

cURL:

```bash
curl https://api.pirouter.ai/v1/images/generations \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-image-2.5-sunburst",
    "prompt": "A flat vector icon of a red paper kite on a plain white background",
    "size": "1024x1024",
    "quality": "low"
  }'
```

Python:

```python
import base64
import os

from openai import OpenAI

client = OpenAI(base_url="https://api.pirouter.ai/v1", api_key=os.environ["PIROUTER_API_KEY"])
result = client.images.generate(
    model="openai/gpt-image-2.5-sunburst",
    prompt="A flat vector icon of a red paper kite on a plain white background",
    size="1024x1024",
    quality="low",
)
open("kite.png", "wb").write(base64.b64decode(result.data[0].b64_json))
```

图像以 base64 放在 `data[0].b64_json` 里，解码后就是 PNG 文件。不支持 `response_format: "url"`，带上会返回 `400 unknown_parameter`。

## 修改这张图像

把上一步的 `kite.png` 作为 `image[]` 上传，`prompt` 写要怎么改：

cURL:

```bash
curl https://api.pirouter.ai/v1/images/edits \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -F model=openai/gpt-image-2.5-sunburst \
  -F "prompt=Make the kite blue; keep the background and composition unchanged" \
  -F "image[]=@kite.png" \
  -F size=1024x1024 \
  -F quality=low
```

Python:

```python
result = client.images.edit(
    model="openai/gpt-image-2.5-sunburst",
    image=[open("kite.png", "rb")],
    prompt="Make the kite blue; keep the background and composition unchanged",
    size="1024x1024",
    quality="low",
)
open("kite-blue.png", "wb").write(base64.b64decode(result.data[0].b64_json))
```

| 原图                                        | 修改后                                        |
| ----------------------------------------- | ------------------------------------------ |
| ![白底上的一只红色纸风筝](/docs/images/kite-red.jpg) | ![同一只风筝，改成了蓝色](/docs/images/kite-blue.jpg) |

响应和生成一样，新图像在 `data[0].b64_json` 里。除了 `model` 和 `stream`，其余表单字段（`size`、`quality`、`n`、`output_format` 等）原样交给模型。

`provider`、`models`、`route`、`fallbacks` 这几个路由字段在改图端点上不生效，会被去掉后再转发，所以改图请求不会[回退](https://pirouter.ai/zh/docs/guides/fallbacks.md)到别的模型。

整个请求体最大 32 MiB，超过返回 `413`，不转发也不计费，见[失败的请求](https://pirouter.ai/zh/docs/guides/billing.md#失败的请求)。

### 只改一块区域

再上传一个 `mask`：和原图同尺寸的 PNG，透明的地方是允许修改的区域。

```bash
curl https://api.pirouter.ai/v1/images/edits \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -F model=openai/gpt-image-2.5-sunburst \
  -F "prompt=Add a small bright yellow sun in the masked area of the sky; keep everything else unchanged" \
  -F "image[]=@kite.png" \
  -F "mask=@mask.png"
```

### 把几张图像合成一张

`image[]` 可以重复多次。下面用官方 SDK 把风筝和一张海景合成一张海报：

Python:

```python
result = client.images.edit(
    model="openai/gpt-image-2.5-sunburst",
    image=[open("kite.png", "rb"), open("sea.png", "rb")],
    prompt="Combine the two pictures into one poster: the kite flying over the watercolor sea",
    size="1024x1024",
    quality="low",
)
```

TypeScript:

```ts
import fs from 'node:fs'
import OpenAI, { toFile } from 'openai'

const client = new OpenAI({ baseURL: 'https://api.pirouter.ai/v1', apiKey: process.env.PIROUTER_API_KEY })
const images = await Promise.all(
  ['kite.png', 'sea.png'].map((path) => toFile(fs.createReadStream(path), path, { type: 'image/png' })),
)
const result = await client.images.edit({
  model: 'openai/gpt-image-2.5-sunburst',
  image: images,
  prompt: 'Combine the two pictures into one poster: the kite flying over the watercolor sea',
  size: '1024x1024',
  quality: 'low',
})
```

| 第二张输入                              | 合成结果                                          |
| ---------------------------------- | --------------------------------------------- |
| ![一片水彩风格的大海](/docs/images/sea.jpg) | ![水彩海面上空飞着风筝](/docs/images/kite-over-sea.jpg) |

## 用 Gemini 协议生成

Gemini 协议没有单独的图像端点：对图像模型调用 `generateContent`，在 `generationConfig.responseModalities` 里写上 `IMAGE`，回复里就带图像。鉴权和其他 Gemini 请求一样用 `Authorization: Bearer`，网关不读 `x-goog-api-key`。

```bash
curl "https://api.pirouter.ai/v1beta/models/google/gemini-nano-banana-2.1:generateContent" \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{ "role": "user", "parts": [{ "text": "A flat vector icon of a red paper kite on a plain white background" }] }],
    "generationConfig": { "responseModalities": ["TEXT", "IMAGE"] }
  }'
```

图像以 base64 放在 `candidates[0].content.parts[]` 的 `inlineData` 里，`mimeType` 说明格式。`responseModalities` 写了 `TEXT` 也不保证有文字部分，下面这次就只有图像。返回示例（`data` 已截断）：

```json
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          { "inlineData": { "mimeType": "image/png", "data": "iVBORw0KGgoAAAANSUhEUgAA..." } }
        ]
      },
      "finishReason": "STOP"
    }
  ],
  "modelVersion": "google/gemini-nano-banana-2.1",
  "usageMetadata": {
    "promptTokenCount": 14,
    "promptTokensDetails": [{ "modality": "TEXT", "tokenCount": 14 }],
    "candidatesTokenCount": 1120,
    "candidatesTokensDetails": [{ "modality": "IMAGE", "tokenCount": 1120 }],
    "thoughtsTokenCount": 1144,
    "totalTokenCount": 2278
  }
}
```

计费按 `usageMetadata` 分模态计：`candidatesTokensDetails` 里 `modality` 为 `IMAGE` 的 token 按图像输出单价计，其余按文本输出单价计；请求里带图像时，`promptTokensDetails` 的 `IMAGE` 部分按图像输入单价计。`thoughtsTokenCount` 是模型的思考 token，不含在 `candidatesTokenCount` 里，按推理输出单价另计。回复里每一个 `inlineData` 记为一张图像。

## 流式拿到预览

两个端点都接受 `stream: true`（改图端点写成表单字段 `-F stream=true`），再用 `partial_images` 指定要几张预览图。响应变成 SSE 事件流：

| 端点 | 事件顺序                                                                 |
| -- | -------------------------------------------------------------------- |
| 生成 | `image_generation.partial_image` → `image_generation.completed`      |
| 编辑 | `image_edit.partial_image` → `image_edit.completed` → `data: [DONE]` |

`completed` 事件带最终图像和 `usage`。生成端点的流没有 `data: [DONE]`，以 `completed` 事件作为结束。模型不一定发满 `partial_images` 张预览，也可能一张都不发，直接给 `completed`。

高质量的大图可能要一分多钟才出结果。超过 90 秒还没有开始返回时，网关会先回 `200` 并发送保活内容，避免连接被中间设备断开，见[长请求](https://pirouter.ai/zh/docs/guides/timeouts.md#长请求)。

## 怎么计费

一次图像请求按三类 token 计费，单价见各模型的价格：

| 计费项  | 内容                       | `pricing` 字段   |
| ---- | ------------------------ | -------------- |
| 文本输入 | `prompt` 的 token         | `prompt`       |
| 图像输入 | 上传的图像和遮罩，按 image token 计 | `image_token`  |
| 图像输出 | 生成的图像，流式的预览图也计入          | `image_output` |

用量在响应的 `usage` 里：`input_tokens_details` 分出 `text_tokens` 和 `image_tokens`，`output_tokens_details.image_tokens` 是图像输出。生成请求没有图像输入。

上面把风筝改成蓝色的那次请求，用量是文本输入 27、图像输入 1,024、图像输出 196 个 token。按 `openai/gpt-image-2.5-sunburst` 的标价（文本输入 $5、图像输入 $8、图像输出 $30，每百万 token）是 $0.014207。模型有限时折扣时按折扣后的价格结算，见[限时折扣](https://pirouter.ai/zh/docs/guides/billing.md#限时折扣)。

两点容易多花钱：

- `n` 大于 1 时，输入也按张数重复计。`n=2` 的改图请求，文本和图像输入都是 `n=1` 时的两倍。
- 流式请求的预览图计入图像输出。同样的改图带一张预览，图像输出从 196 变成 273 个 token。

缺图像、缺 `prompt` 的请求返回 `400`，不计费；其他失败情况见[失败的请求](https://pirouter.ai/zh/docs/guides/billing.md#失败的请求)。

## 下一步

- [生成图像 API](https://pirouter.ai/zh/docs/api/images.md): 生成端点的完整参数与返回。
- [编辑图像 API](https://pirouter.ai/zh/docs/api/image-edits.md): 改图端点的完整参数与返回。
