> ## Documentation Index
> Fetch the complete documentation index at: https://docs-model.skyengine.com.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAI 图片生成 / 编辑示例

> 使用 OpenAI 兼容接口（gpt-image-2 / gpt-image-1 系列）生成与编辑图片的完整示例

# OpenAI 图片生成 / 编辑

本页覆盖两种能力：

* **文生图** `POST /v1/images/generations`
* **图生图 / 编辑** `POST /v1/images/edits`

两者都走 OpenAI 兼容协议，目前推荐使用 `gpt-image-2-2026-04-21`（在 Azure Foundry 上 2026-04-21 GA）。旧版 `gpt-image-1` / `gpt-image-1.5` 仍可用但能力弱于 gpt-image-2，`dall-e-3` 已停止维护。

## 图片生成（文生图）

**Content-Type 仅支持 `application/json`**。`multipart/form-data` 会被拒绝。

<Tip>
  **本接口也能做图生图**：在 body 里加 `image` 字段（URL 或 base64 字符串数组）即可，平台会自动等效转发到 `/v1/images/edits`。适合业务方用一个接口统一管理所有图片生成能力（不想区分"文生图 / 图生图"两个 endpoint 时）。仅 `gpt-image-1` / `gpt-image-2` 家族生效。详见下方 [图片编辑 - 方式 C](#方式-c%EF%BC%9Av1-images-generations--image-字段平台扩展)。
</Tip>

### 快速开始

只需替换 `<API-KEY>` 为你的实际 API Key。

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://model-api.skyengine.com.cn/v1/images/generations" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer <API-KEY>" \
    -d '{
      "model": "gpt-image-2-2026-04-21",
      "prompt": "一只可爱的小猫在花园里玩耍，阳光明媚，油画风格",
      "n": 1,
      "size": "1024x1024",
      "quality": "medium"
    }'
  ```

  ```python Python theme={null}
  import requests
  import base64
  from PIL import Image
  from io import BytesIO

  API_KEY = "<API-KEY>"
  BASE_URL = "https://model-api.skyengine.com.cn/v1"

  def generate_image(prompt, size="1024x1024", quality="medium", n=1,
                     model="gpt-image-2-2026-04-21"):
      url = f"{BASE_URL}/images/generations"
      headers = {
          "Content-Type": "application/json",
          "Authorization": f"Bearer {API_KEY}",
      }
      data = {
          "model": model,
          "prompt": prompt,
          "n": n,
          "size": size,        # 1024x1024 / 1536x1024 / 1024x1536
          "quality": quality,  # low / medium / high
          "response_format": "b64_json",  # 或 "url"
      }
      resp = requests.post(url, headers=headers, json=data)
      resp.raise_for_status()
      result = resp.json()

      images = []
      for i, img in enumerate(result["data"]):
          if img.get("b64_json"):
              image = Image.open(BytesIO(base64.b64decode(img["b64_json"])))
              filename = f"generated_{i+1}.png"
              image.save(filename)
              images.append(filename)
              print(f"图片已保存: {filename}")
          elif img.get("url"):
              images.append(img["url"])
              print(f"图片 URL: {img['url']}")
      return images


  if __name__ == "__main__":
      generate_image("一只可爱的小猫在花园里玩耍，阳光明媚，油画风格")
  ```

  ```javascript JavaScript/Node.js theme={null}
  import axios from "axios";
  import fs from "fs";

  const API_KEY = "<API-KEY>";
  const BASE_URL = "https://model-api.skyengine.com.cn/v1";

  async function generateImage(prompt, {
    size = "1024x1024",
    quality = "medium",
    n = 1,
    model = "gpt-image-2-2026-04-21",
  } = {}) {
    const resp = await axios.post(`${BASE_URL}/images/generations`, {
      model, prompt, n, size, quality,
      response_format: "b64_json",
    }, {
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${API_KEY}`,
      },
    });

    return resp.data.data.map((img, i) => {
      if (img.b64_json) {
        const file = `generated_${i + 1}.png`;
        fs.writeFileSync(file, Buffer.from(img.b64_json, "base64"));
        console.log(`图片已保存: ${file}`);
        return file;
      }
      return img.url;
    });
  }

  generateImage("一只可爱的小猫在花园里玩耍，阳光明媚，油画风格");
  ```
</CodeGroup>

## 图片编辑（图生图）

基于一张或多张参考图 + 可选 mask + prompt，生成编辑后的图片。

**两种 Content-Type 都支持**，按需选择：

* `multipart/form-data`：传统 OpenAI 兼容写法，直接上传本地文件
* `application/json`：平台扩展写法，`image` / `mask` 字段传 **URL** 或 **base64 字符串**（业务端接入更方便，不用 form-data 库）

### 方式 A：multipart/form-data

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://model-api.skyengine.com.cn/v1/images/edits" \
    -H "Authorization: Bearer <API-KEY>" \
    -F model="gpt-image-2-2026-04-21" \
    -F image="@original.png" \
    -F mask="@mask.png" \
    -F prompt="把中间的区域换成一朵盛开的樱花" \
    -F n=1 \
    -F size="1024x1024" \
    -F quality="medium"
  ```

  ```python Python theme={null}
  import requests

  API_KEY = "<API-KEY>"
  BASE_URL = "https://model-api.skyengine.com.cn/v1"

  def edit_image(image_path, prompt, mask_path=None,
                 size="1024x1024", quality="medium", n=1,
                 model="gpt-image-2-2026-04-21"):
      url = f"{BASE_URL}/images/edits"
      headers = {"Authorization": f"Bearer {API_KEY}"}

      files = {"image": ("image.png", open(image_path, "rb"), "image/png")}
      if mask_path:
          files["mask"] = ("mask.png", open(mask_path, "rb"), "image/png")
      data = {
          "model": model,
          "prompt": prompt,
          "n": n,
          "size": size,
          "quality": quality,
          "response_format": "url",  # 或 "b64_json"
      }

      resp = requests.post(url, headers=headers, files=files, data=data)
      resp.raise_for_status()
      return resp.json()["data"]


  if __name__ == "__main__":
      result = edit_image("original.png", "把中间的区域换成一朵盛开的樱花", mask_path="mask.png")
      for i, img in enumerate(result):
          print(f"编辑图 {i+1}: {img.get('url') or '[b64_json]'}")
  ```

  ```javascript JavaScript/Node.js theme={null}
  import axios from "axios";
  import FormData from "form-data";
  import fs from "fs";

  const API_KEY = "<API-KEY>";
  const BASE_URL = "https://model-api.skyengine.com.cn/v1";

  async function editImage(imagePath, prompt, {
    maskPath,
    size = "1024x1024",
    quality = "medium",
    n = 1,
    model = "gpt-image-2-2026-04-21",
  } = {}) {
    const form = new FormData();
    form.append("model", model);
    form.append("prompt", prompt);
    form.append("n", String(n));
    form.append("size", size);
    form.append("quality", quality);
    form.append("response_format", "url");
    form.append("image", fs.createReadStream(imagePath));
    if (maskPath) form.append("mask", fs.createReadStream(maskPath));

    const resp = await axios.post(`${BASE_URL}/images/edits`, form, {
      headers: { Authorization: `Bearer ${API_KEY}`, ...form.getHeaders() },
    });
    return resp.data.data;
  }
  ```
</CodeGroup>

### 方式 B：application/json（推荐，接入更简单）

`image` 是**字符串数组**，每个元素可以是 `http(s)://` URL 或 base64 字符串（**不要**带 `data:image/png;base64,` 前缀）。`mask` 是单个字符串，同样规则。平台会自动下载 / 解码，再透传到底层模型。

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://model-api.skyengine.com.cn/v1/images/edits" \
    -H "Authorization: Bearer <API-KEY>" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2-2026-04-21",
      "prompt": "把中间的区域换成一朵盛开的樱花",
      "size": "1024x1024",
      "quality": "medium",
      "n": 1,
      "image": [
        "https://example.com/original.png"
      ],
      "mask": "https://example.com/mask.png"
    }'
  ```

  ```python Python theme={null}
  import base64
  import requests

  API_KEY = "<API-KEY>"
  BASE_URL = "https://model-api.skyengine.com.cn/v1"

  def edit_image_json(image_inputs, prompt, mask=None,
                      size="1024x1024", quality="medium", n=1,
                      model="gpt-image-2-2026-04-21"):
      """
      image_inputs: list[str]，每个元素是 URL 或 base64
      mask:         str，URL 或 base64（可选）
      """
      url = f"{BASE_URL}/images/edits"
      headers = {
          "Authorization": f"Bearer {API_KEY}",
          "Content-Type": "application/json",
      }
      data = {
          "model": model,
          "prompt": prompt,
          "n": n,
          "size": size,
          "quality": quality,
          "response_format": "url",
          "image": image_inputs,
      }
      if mask:
          data["mask"] = mask

      resp = requests.post(url, headers=headers, json=data)
      resp.raise_for_status()
      return resp.json()["data"]


  if __name__ == "__main__":
      # URL 方式
      r1 = edit_image_json(["https://example.com/a.png"], "加上一顶草帽")

      # base64 方式（本地文件读出后编码）
      with open("local.png", "rb") as f:
          b64 = base64.b64encode(f.read()).decode()
      r2 = edit_image_json([b64], "换成油画风格")
  ```

  ```javascript JavaScript/Node.js theme={null}
  import axios from "axios";
  import fs from "fs";

  const API_KEY = "<API-KEY>";
  const BASE_URL = "https://model-api.skyengine.com.cn/v1";

  async function editImageJson(imageInputs, prompt, {
    mask,
    size = "1024x1024",
    quality = "medium",
    n = 1,
    model = "gpt-image-2-2026-04-21",
  } = {}) {
    const body = {
      model, prompt, n, size, quality,
      response_format: "url",
      image: imageInputs,
      ...(mask ? { mask } : {}),
    };
    const resp = await axios.post(`${BASE_URL}/images/edits`, body, {
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        "Content-Type": "application/json",
      },
    });
    return resp.data.data;
  }

  // URL 方式
  await editImageJson(["https://example.com/a.png"], "加上一顶草帽");

  // base64 方式
  const b64 = fs.readFileSync("local.png").toString("base64");
  await editImageJson([b64], "换成油画风格");
  ```
</CodeGroup>

### 方式 C：`/v1/images/generations` + `image` 字段（平台扩展）

和方式 B 效果完全等价，但 endpoint 是 `/v1/images/generations`。用途是**让业务方用同一个 endpoint 覆盖"文生图 + 图生图"两种用法**（参考 `doubao-seedream` 的接口风格）：传 `image` 字段就是图生图，不传就是文生图。平台会在 provider 层自动把带 `image` 的 generations 请求转发到 edits 实现。

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://model-api.skyengine.com.cn/v1/images/generations" \
    -H "Authorization: Bearer <API-KEY>" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-image-2-2026-04-21",
      "prompt": "把苹果变成蓝色",
      "size": "1024x1024",
      "quality": "low",
      "image": [
        "https://example.com/apple.png"
      ]
    }'
  ```

  ```python Python theme={null}
  import requests, base64

  API_KEY = "<API-KEY>"

  # URL 方式
  r = requests.post(
      "https://model-api.skyengine.com.cn/v1/images/generations",
      headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
      json={
          "model": "gpt-image-2-2026-04-21",
          "prompt": "把苹果变成蓝色",
          "image": ["https://example.com/apple.png"],
          "size": "1024x1024",
          "quality": "low",
      },
  )
  print(r.json())

  # base64 方式
  with open("apple.png", "rb") as f:
      b64 = base64.b64encode(f.read()).decode()
  r = requests.post(
      "https://model-api.skyengine.com.cn/v1/images/generations",
      headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
      json={
          "model": "gpt-image-2-2026-04-21",
          "prompt": "把苹果变成蓝色",
          "image": [b64],   # 注意：不要带 "data:image/png;base64," 前缀
          "size": "1024x1024",
          "quality": "low",
      },
  )
  ```
</CodeGroup>

<Warning>
  **方式 C 的限制**：

  * 仅 `gpt-image-1` / `gpt-image-1-mini` / `gpt-image-1.5` / `gpt-image-2` + 各自日期快照生效，其他模型（如 `dall-e-3`）传 `image` 会被上游直接忽略，退化为纯文生图。
  * **不支持 mask**：`/v1/images/generations` 请求体没有 mask 字段。需要用 mask 精修的场景请用方式 A 或 B。
  * 用量计费和方式 B 一致（`input_tokens_details.image_tokens` 会出现），不会因为换了 endpoint 就免费。
</Warning>

## 支持的参数

### 共用参数（generations / edits）

| 参数                   | 类型                 | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| -------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model`              | string             | 模型名。推荐 `gpt-image-2-2026-04-21`。也支持 `gpt-image-1` / `gpt-image-1.5` / `gpt-image-1-mini`                                                                                                                                                                                                                                                                                                                                                                                 |
| `prompt`             | string             | 文字描述，必填。GPT image 系列上限 **32000 字符**（`dall-e-3` 为 4000，`dall-e-2` 为 1000）                                                                                                                                                                                                                                                                                                                                                                                                 |
| `n`                  | integer            | 生成张数，**1 \~ 10**，默认 1（`dall-e-3` 仅支持 `n=1`）                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `size`               | string \| `"auto"` | 生成图片的尺寸，格式为 `宽x高`（WIDTHxHEIGHT）。<br />**gpt-image-2 / gpt-image-2-2026-04-21**：支持任意分辨率，宽和高都必须是 16 的倍数，宽高比需在 `1:3` \~ `3:1` 之间，例如 `1536x864`。超过 `2560x1440` 的分辨率为实验性支持，最大支持到 `3840x2160`。同时还要满足模型当前的像素和单边限制（见下方[尺寸约束](#尺寸约束gpt-image-2)）。<br />**GPT 图像模型标准尺寸**：`1024x1024`（方）、`1536x1024`（横）、`1024x1536`（纵）均受支持；`auto` 仅在允许自动选尺寸的模型上可用。<br />**dall-e-2**：`256x256` / `512x512` / `1024x1024`。<br />**dall-e-3**：`1024x1024` / `1792x1024` / `1024x1792`。<br />不传则走模型默认。 |
| `quality`            | string             | **`low` / `medium` / `high`**。gpt-image-2 **不接受 `auto`**，不传走服务端默认                                                                                                                                                                                                                                                                                                                                                                                                        |
| `output_format`      | string             | 输出图片格式，**GPT image 系列专属**：`png`（默认）/ `jpeg` / `webp`，不传走默认                                                                                                                                                                                                                                                                                                                                                                                                               |
| `output_compression` | integer            | 输出压缩率 `0 ~ 100`，默认 100。**仅 `output_format` 为 `webp` / `jpeg` 时生效**，GPT image 系列专属                                                                                                                                                                                                                                                                                                                                                                                        |
| `moderation`         | string             | 内容审核强度，**GPT image 系列专属**：`auto`（默认）/ `low`                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `response_format`    | string             | `b64_json`（默认）或 `url`。后者会把图转存到云存储并返回签名 URL                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `user`               | string             | 业务方用户标识，便于审计                                                                                                                                                                                                                                                                                                                                                                                                                                                             |

### 图片输入参数（`edits` 必用；`generations` 的方式 C 也支持 `image`）

| 参数      | 类型                                                                   | 说明                                                                                                |
| ------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `image` | file / file\[]（form-data）<br />string / string\[]（JSON，URL 或 base64） | 参考图。JSON 下多图就是数组；form-data 下同名字段重复即可多图。`gpt-image-1/2` 家族在 `/v1/images/generations` 也支持此字段（见方式 C） |
| `mask`  | file（form-data）<br />string（JSON，URL 或 base64）                       | 可选 PNG mask（alpha 通道透明区域表示"编辑此处"），尺寸必须与 `image` 一致。**仅 `/v1/images/edits` 支持**，方式 C 不支持           |

**JSON body 下 base64 字符串约定**：直接放 base64 内容即可，**不要**带 `data:image/png;base64,` 前缀。

### 尺寸约束（gpt-image-2）

`gpt-image-2` / `gpt-image-2-2026-04-21` 支持任意 `宽x高` 分辨率，但必须同时满足以下约束：

* 宽和高都必须是 **16 的倍数**
* 宽高比需在 **`1:3` \~ `3:1`** 之间
* 单边 ≤ **3840px**
* 像素总量在 **655,360 \~ 8,294,400** 之间（即 ≤ 3840×2160）
* 超过 `2560x1440` 的分辨率为**实验性支持**，最大支持到 `3840x2160`
* 常用值：`1024x1024`（方）/ `1536x1024`（横）/ `1024x1536`（纵）/ `1536x864` 等
* 超出约束会被上游 **400** 拒绝

## 响应示例

```json theme={null}
{
  "created": 1776840564,
  "data": [
    {
      "url": "https://model-static.skyengine.com.cn/<uid>/images/20260422/generated_xxx.png?q-sign-algorithm=..."
    }
  ],
  "usage": {
    "input_tokens": 10,
    "output_tokens": 272,
    "total_tokens": 282,
    "input_tokens_details": { "text_tokens": 10, "image_tokens": 0 }
  }
}
```

* 当请求 `response_format=b64_json`（或不传），`data[i]` 里会是 `b64_json` 字段
* 当请求 `response_format=url`，服务端会把图上传到云存储并返回签名 URL
* `usage` 里 `output_tokens` 是按 token 计费的依据（不是按图片张数），参考 OpenAI 官方定价

## 常见问题

1. **quality 不要传 `auto`**：gpt-image-2 的 Azure 部署不接受，会返 HTTP 500。显式传 `low / medium / high`，或整个字段留空走服务端默认。
2. **不支持 `style` 参数**：`vivid / natural` 是 `dall-e-3` 专属；gpt-image-1/2 都不支持。
3. **不支持 `transparent` 背景**（gpt-image-2）：OpenAI 官方文档明确不支持透明背景。
4. **输入图片限制**（edits）：推荐 PNG，单文件 \< 20MB；多图场景时总量也有上限。
5. **耗时预期**：quality=low 约 20-30s，medium 约 60-80s，high 约 200s+。按 token 计费，high 耗费显著更高。
6. **返回的 URL 有签名过期时间**：如果业务侧需要长期保存，建议请求 `response_format=b64_json` 自行落库，或下载 URL 对应图片另存。

## 应用场景

| 场景        | 推荐                          | 提示                        |
| --------- | --------------------------- | ------------------------- |
| 广告 / 社媒配图 | generations, quality=medium | 多次生成选最优                   |
| 产品原型可视化   | generations, size=1024x1024 | 描述要具体（品类 / 风格 / 视角）       |
| 抠图 / 背景替换 | edits + mask                | mask 边缘要干净，alpha=0 为"替换处" |
| 风格转换      | edits（不带 mask）              | prompt 指明目标风格             |
| 多参考图合成    | edits 多 `image`             | 按数组顺序上传，主体图放第一个           |
