---
title: "生成与编辑图片"
description: "用 pirouter 从一句话生成图片，再上传图片让模型修改：遮罩、多张图合成、流式预览，以及一次请求按哪些 token 计费。"
canonical: "https://pirouter.ai/zh/docs/images"
last-updated: "2026-10-16"
lang: "zh"
source: "content/docs/zh/(start)/images.mdx"
---

# 生成与编辑图片

用 pirouter 从一句话生成图片，再上传图片让模型修改：遮罩、多张图合成、流式预览，以及一次请求按哪些 token 计费。

pirouter 提供两个图像端点，都用 OpenAI 的 Images 协议：

| 端点                            | 做什么             | 请求体                   |
| ----------------------------- | --------------- | --------------------- |
| `POST /v1/images/generations` | 从一段文字生成图片       | JSON                  |
| `POST /v1/images/edits`       | 上传一张或多张图片，按文字修改 | `multipart/form-data` |

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

## 哪些模型能用

| 模型                                   | 生成 | 编辑 |
| ------------------------------------ | -- | -- |
| `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` | 是  | 否  |

模型提供哪些端点，以 `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",
    "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",
    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 \
  -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",
    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/fallbacks.md)到别的模型。

整个请求体最大 32 MiB，超过返回 `413`，不转发也不计费。

### 只改一块区域

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

```bash
curl https://api.pirouter.ai/v1/images/edits \
  -H "Authorization: Bearer $PIROUTER_API_KEY" \
  -F model=openai/gpt-image-2 \
  -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",
    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',
  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) |

## 流式拿到预览

两个端点都接受 `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/errors.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` 是图像输出。生成请求没有图像输入。

上面把风筝改成蓝色的那次请求，用量是文本输入 17、图像输入 1,024、图像输出 196 个 token。按 `openai/gpt-image-2` 的标价（文本输入 $5、图像输入 $8、图像输出 $30，每百万 token）是 $0.014157。实测时这个模型有 40% 的限时折扣，账本实际扣了 $0.008494。

两点容易多花钱：

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

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

## 下一步

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