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

# 图像编辑

> FocusAPI 图像编辑接入指南：使用 GPT 图像、Gemini 图片模型和兼容图像模型完成图片改图、局部修改、参考图重绘，并说明 curl、Python SDK、参数和多轮编辑。

图像编辑是 **图片 + 文本指令 → 新图片**。它和 [图像生成](/models/image-generation) 的区别是：编辑任务必须提供 `image` 输入，模型需要在原图或参考图基础上修改。

适合场景：

* 换背景、改颜色、改风格
* 保留主体，重绘细节
* 局部修改和蒙版编辑
* 用参考图生成同风格素材

<Warning>
  图像编辑的输入格式、是否支持 `mask`、可上传图片数量、输出尺寸，都会随模型版本变化。上线前请以控制台 **模型广场** 为准。
</Warning>

## GPT 图像编辑

GPT 图像编辑通常使用 OpenAI Images Edit 兼容方式。请求重点是 `image` 和 `prompt`。

<CodeGroup>
  ```bash cURL theme={null}
  curl https://www.focusapi.cn/v1/images/edits \
    -H "Authorization: Bearer sk-your-api-key" \
    -F model="gpt-image-1" \
    -F image="@/path/to/source.png" \
    -F prompt="保留主体不变，把背景改成纯白色，并增强产品边缘光" \
    -F size="1024x1024" \
    -F quality="medium"
  ```

  ```python OpenAI SDK theme={null}
  import base64
  from urllib.request import urlopen
  from openai import OpenAI

  client = OpenAI(
      base_url="https://www.focusapi.cn/v1",
      api_key="sk-your-api-key",
  )

  edited = client.images.edit(
      model="gpt-image-1",
      image=open("/path/to/source.png", "rb"),
      prompt="保留主体不变，把背景改成纯白色，并增强产品边缘光",
      size="1024x1024",
      quality="medium",
      response_format="b64_json",
  )

  item = edited.data[0]
  save_path = "edited.png"

  if item.b64_json:
      with open(save_path, "wb") as f:
          f.write(base64.b64decode(item.b64_json))
  elif item.url:
      with open(save_path, "wb") as f:
          f.write(urlopen(item.url).read())

  print(f"图片已保存到 {save_path}")
  ```
</CodeGroup>

### GPT 图像编辑参数

<Tabs>
  <Tab title="gpt-image-1">
    | 参数                | 说明           | 可选值                                         |
    | ----------------- | ------------ | ------------------------------------------- |
    | `model`           | 支持编辑的图像模型 ID | `gpt-image-1`，或模型广场展示的兼容模型                  |
    | `image`           | 原图输入         | `png`、`jpg`、`webp` 等格式以模型支持为准               |
    | `prompt`          | 编辑指令         | 文本，建议明确“保留什么、修改什么”                          |
    | `mask`            | 局部编辑蒙版       | 可选，是否支持以模型广场为准                              |
    | `size`            | 输出尺寸         | `1024x1024`、`1024x1536`、`1536x1024`，以模型支持为准 |
    | `quality`         | 输出质量         | `auto`、`low`、`medium`、`high`                |
    | `n`               | 生成张数         | 通常从 `1` 开始；批量上限以模型广场为准                      |
    | `response_format` | 返回格式         | `url`、`b64_json`，以模型支持为准                    |
  </Tab>

  <Tab title="兼容编辑模型">
    | 参数           | 说明            | 可选值          |
    | ------------ | ------------- | ------------ |
    | `model`      | 模型广场中的完整模型 ID | 以模型广场为准      |
    | `image`      | 原图、参考图或首图     | 格式和数量以模型广场为准 |
    | `prompt`     | 编辑指令          | 文本           |
    | `mask`       | 局部编辑蒙版        | 可选           |
    | `extra_body` | 厂商特殊参数        | 以模型广场和错误提示为准 |
  </Tab>
</Tabs>

## Gemini 图片编辑

Gemini 图片编辑通常用 GenAI 多模态内容：`contents` 里同时传文本指令和图片输入，并要求返回 `TEXT` + `IMAGE`。

<CodeGroup>
  ```bash cURL theme={null}
  curl https://www.focusapi.cn/v1beta/models/gemini-3.1-flash-image-preview:generateContent \
    -H "x-goog-api-key: sk-your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "contents": [
        {
          "parts": [
            { "text": "保留主体不变，把背景改成纯白色，并增强产品边缘光" },
            {
              "inline_data": {
                "mime_type": "image/png",
                "data": "base64-image-data"
              }
            }
          ]
        }
      ],
      "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {
          "aspectRatio": "1:1",
          "imageSize": "1K"
        }
      }
    }'
  ```

  ```python Gemini GenAI SDK theme={null}
  import base64
  import os
  import re

  from google import genai
  from google.genai import types

  client = genai.Client(
      api_key="sk-your-api-key",
      http_options=types.HttpOptions(base_url="https://www.focusapi.cn"),
  )

  with open("/path/to/source.png", "rb") as f:
      source_image = f.read()

  response = client.models.generate_content(
      model="gemini-3.1-flash-image-preview",
      contents=[
          "保留主体不变，把背景改成纯白色，并增强产品边缘光",
          types.Part.from_bytes(data=source_image, mime_type="image/png"),
      ],
      config=types.GenerateContentConfig(
          response_modalities=["IMAGE"],
          image_config=types.ImageConfig(
              aspect_ratio="1:1",
              image_size="1K",
          ),
      ),
  )

  save_path = "edited.png"
  saved = False

  for part in response.parts:
      if image := part.as_image():
          image.save(save_path)
          saved = True
          print(f"图片已保存到 {save_path}")
          break
      if part.text:
          match = re.search(r"data:image/[^;]+;base64,([A-Za-z0-9+/=]+)", part.text)
          if match:
              with open(save_path, "wb") as f:
                  f.write(base64.b64decode(match.group(1)))
              saved = True
              print(f"图片已保存到 {save_path}")
              break

  if not saved:
      raise RuntimeError("响应里没有图片，请检查 model 与 response_modalities")
  ```
</CodeGroup>

<Note>
  Gemini 编辑与生图一样：优先用 `response.parts` + `part.as_image()` 保存（需 `pip install pillow`）。若网关把图片塞进 `part.text` 的 `data:image/...;base64,...`，需正则提取后解码。不要直接 `write(part.inline_data.data)` 或先 `print(part.text)`。
</Note>

### Gemini 图片编辑参数

<Tabs>
  <Tab title="Gemini 图片编辑">
    | 参数                          | 说明                      | 可选值                               |
    | --------------------------- | ----------------------- | --------------------------------- |
    | `model`                     | 支持图片输出/编辑的 Gemini 模型 ID | 以模型广场为准                           |
    | `contents`                  | 文本指令和图片输入               | 文本 + `types.Part.from_bytes(...)` |
    | `response_modalities`       | 期望返回的模态                 | `["TEXT", "IMAGE"]`               |
    | `image_config.aspect_ratio` | 输出比例                    | `1:1`、`3:2`、`2:3`、`9:16`、`16:9`   |
    | `image_config.image_size`   | 输出分辨率档位                 | `1K`、`2K`，以模型支持为准                 |
  </Tab>
</Tabs>

## 多轮图像编辑

图像编辑天然适合多轮：先做大方向修改，再逐步微调。不同官方 SDK 的多轮方式不同。

<CodeGroup>
  ```python OpenAI 连续编辑 theme={null}
  import base64
  from openai import OpenAI

  client = OpenAI(
      base_url="https://www.focusapi.cn/v1",
      api_key="sk-your-api-key",
  )

  first = client.images.edit(
      model="gpt-image-1",
      image=open("/path/to/source.png", "rb"),
      prompt="保留人物姿势，把背景换成办公室，整体写实风格。",
      size="1024x1024",
      quality="medium",
  )

  first_image = first.data[0].b64_json
  with open("first.png", "wb") as f:
      f.write(base64.b64decode(first_image))

  second = client.images.edit(
      model="gpt-image-1",
      image=open("first.png", "rb"),
      prompt="保持上一张图的构图，只把衣服改成深蓝色。",
      size="1024x1024",
      quality="medium",
      response_format="b64_json",
  )

  with open("second.png", "wb") as f:
      f.write(base64.b64decode(second.data[0].b64_json))
  print("图片已保存到 second.png")
  ```

  ```python OpenAI Responses 多轮 theme={null}
  import base64
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://www.focusapi.cn/v1",
      api_key="sk-your-api-key",
  )

  def save_image_from_response(response, save_path):
      for item in response.output:
          if item.type == "image_generation_call" and item.result:
              os.makedirs(os.path.dirname(save_path) or ".", exist_ok=True)
              with open(save_path, "wb") as f:
                  f.write(base64.b64decode(item.result))
              print(f"图片已保存到 {save_path}")
              return True
      return False

  with open("/path/to/source.png", "rb") as f:
      source_b64 = base64.b64encode(f.read()).decode("utf-8")

  first = client.responses.create(
      model="gpt-4.1-mini",
      input=[
          {
              "role": "user",
              "content": [
                  {
                      "type": "input_text",
                      "text": "根据这张产品图生成一个白底电商主图。",
                  },
                  {
                      "type": "input_image",
                      "image_url": f"data:image/png;base64,{source_b64}",
                  },
              ],
          }
      ],
      tools=[{"type": "image_generation", "model": "gpt-image-1", "action": "edit"}],
  )

  save_image_from_response(first, "output/edit-v1.png")

  second = client.responses.create(
      model="gpt-4.1-mini",
      previous_response_id=first.id,
      input="保持上一张图的产品角度不变，把阴影调得更自然。",
      tools=[{"type": "image_generation", "model": "gpt-image-1", "action": "edit"}],
  )

  save_image_from_response(second, "output/edit-v2.png")
  ```

  ```python Gemini GenAI Chat theme={null}
  import base64
  import re

  from google import genai
  from google.genai import types

  client = genai.Client(
      api_key="sk-your-api-key",
      http_options=types.HttpOptions(base_url="https://www.focusapi.cn"),
  )

  with open("/path/to/source.png", "rb") as f:
      source_image = f.read()

  chat = client.chats.create(
      model="gemini-3.1-flash-image-preview",
      config=types.GenerateContentConfig(
          response_modalities=["IMAGE"],
          image_config=types.ImageConfig(aspect_ratio="1:1", image_size="1K"),
      ),
  )

  chat.send_message([
      "保留人物姿势，把背景换成办公室，整体写实风格。",
      types.Part.from_bytes(data=source_image, mime_type="image/png"),
  ])

  second = chat.send_message(
      "保持上一张图的构图，只把衣服改成深蓝色。"
  )

  save_path = "edited-round-2.png"
  saved = False

  for part in second.parts:
      if image := part.as_image():
          image.save(save_path)
          saved = True
          print(f"图片已保存到 {save_path}")
          break
      if part.text:
          match = re.search(r"data:image/[^;]+;base64,([A-Za-z0-9+/=]+)", part.text)
          if match:
              with open(save_path, "wb") as f:
                  f.write(base64.b64decode(match.group(1)))
              saved = True
              print(f"图片已保存到 {save_path}")
              break

  if not saved:
      raise RuntimeError("响应里没有图片")
  ```
</CodeGroup>

<Note>
  OpenAI `images.edit` 返回 `b64_json` 字符串，需 `base64.b64decode` 后保存。Responses 多轮从 `image_generation_call.result` 取 base64。Gemini 编辑与生图相同，图片可能在 `inline_data`（用 `as_image()`）或 `text` 的 data URL 里，不要只依赖 `part.inline_data.data`。
</Note>

## 提示词建议

* 第一轮：“保留人物姿势，把背景换成办公室，整体写实风格。”
* 第二轮：“保持上一张图的构图，只把衣服改成深蓝色。”
* 第三轮：“继续保持人物和衣服不变，把光线调成清晨自然光。”

## 相关能力

<CardGroup cols={2}>
  <Card title="图像生成" href="/models/image-generation">
    从文本提示词生成新图片。
  </Card>

  <Card title="图片分析" href="/models/image-analysis">
    让模型理解已有图片、截图、票据和图表。
  </Card>
</CardGroup>
