# gpt-image-2 画像生成と編集

QCode.cc は **OpenAI 完全互換**の `gpt-image-2` API を提供し、2 つのエンドポイントをカバーします：

- **画像生成** `POST /v1/images/generations` — JSON リクエスト、テキストのみから画像を生成
- **画像編集** `POST /v1/images/edits` — multipart で 1–8 枚の元画像をアップロード（オプションで mask）、prompt に従って再描画 / 編集 / 合成（2026 年 5 月リリース）

`gpt-image-2` は OpenAI が 2026 年 4 月に公開した最新の画像モデルで、**画像内の文字レンダリングは現存の公開モデルで最強**（英語・中国語の文字を画像内に安定して描画可能）です。

QCode.cc 接続の特徴：

- **OpenAI SDK そのまま**：`base_url` だけ変更、リクエスト / レスポンス形式は 100% 互換（multipart edits エンドポイントを含む）
- **マルチリージョン**：HK / 日本 / 米国 / 欧州 — ネットワーク環境に応じて選択
- **API キー統一**：既存の QCode.cc `cr_` キーを再利用、Claude Code / Codex / Gemini CLI と同一クォータ
- **使用状況の統一表示**：画像コールと対話コールが顧客ダッシュボードに統合表示、専用の使用状況ページも提供
- **両エンドポイントでクォータ共有**：`generations` と `edits` で API キーごとの 1 日 100 枚上限と 2 並列上限を共有

主な用途：ポスター生成、挿絵、製品画像、UI モックアップ、SNS 素材、**画像編集（部分修正 / 複数画像合成 / 背景差し替え / 高忠実度修復）**。

---

## クイックスタート

### 画像生成（generations）

3 行の Python で最初の画像を：

```python
from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,  # 1 枚あたり 30–120 秒、180 秒以上を指定
)

result = client.images.generate(
    model="gpt-image-2",
    prompt="A cyberpunk Tokyo street at night, neon reflecting in rain puddles",
    size="1024x1024",
    quality="low",
    n=1,
)

with open("output.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))
```

### 画像編集（edits）

既存の画像 + prompt をアップロード、オプションで mask による部分再描画：

```python
from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.edit(
    model="gpt-image-2",
    image=open("cat.png", "rb"),
    mask=open("mask.png", "rb"),          # オプション：PNG alpha、透明部分が再描画領域
    prompt="put a tiny crown on the cat",
    size="1024x1024",
    quality="high",
)

with open("edited.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))
```

> ⚠️ **timeout は必ず 180 秒以上を明示的に指定**：OpenAI SDK のデフォルト timeout は短く、`gpt-image-2` の推論時間は従来の text-to-image より大幅に長いです（下記 [生成時間とタイムアウト設定](#生成時間とタイムアウト設定) を参照）。

---

## 接続エンドポイント

`gpt-image-2` サービス（`generations` + `edits` 共通）は QCode.cc のすべての接続ドメインで利用可能で、`{base}` に `/qcode-img/v1` を付け足すだけです：

| ユーザー所在地 | 推奨 base_url | プロトコル | 備考 |
|---|---|---|---|
| 中国本土（HTTPS 必須）| `https://api.qcode.cc/qcode-img/v1` | HTTPS | グローバル CDN 経由、medium / high で 524 になる場合あり（[CDN 100 秒制限](#cdn-100-秒制限524-エラー) 参照） |
| 香港 / 東南アジア | `https://asia.qcode.cc/qcode-img/v1` | HTTPS | 香港 PoP |
| 欧州 | `https://eu.qcode.cc/qcode-img/v1` | HTTPS | フランクフルト PoP |
| 北米 | `https://us.qcode.cc/qcode-img/v1` | HTTPS | ロサンゼルス PoP |

すべてのエンドポイントは同じ請求体系にルーティングされ、使用量とクォータは統一されます。完全なエンドポイント仕様は [エンドポイントと API パス](/ja/docs/getting-started/endpoints-and-api-paths) を参照。

> `qcode-img` は画像生成・編集専用のパスプレフィックスで、Anthropic プロトコルの `/api`、OpenAI プロトコルの `/openai/v1`、Gemini プロトコルの `/gemini` と並列の位置付けです。

---

## API リファレンス

### 共通リクエストヘッダ

| Header | 必須 | 値 |
|---|---|---|
| `Authorization` | ✓ | `Bearer cr_xxxxxxxxxxxxxxxx`（QCode.cc API キー）|
| `Content-Type` | ✓ | `application/json`（generations）<br/>`multipart/form-data`（edits）|

### 生成エンドポイント `/v1/images/generations`

**エンドポイント**：`POST {base_url}/images/generations`
**Content-Type**：`application/json`

リクエストボディ：

```json
{
  "model": "gpt-image-2",
  "prompt": "A small ceramic vase with sunflower, photorealistic",
  "size": "1024x1024",
  "quality": "low",
  "n": 1
}
```

フィールド：

| フィールド | 型 | 必須 | デフォルト | 値 |
|---|---|---|---|---|
| `model` | string | ✓ | — | `gpt-image-2` 固定 |
| `prompt` | string | ✓ | — | 画像の説明文、**多言語対応**（中英含む）|
| `size` | string | ✗ | `1024x1024` | `1024x1024`（正方形）/ `1024x1536`（縦）/ `1536x1024`（横）|
| `quality` | string | ✗ | `medium` | `low` / `medium` / `high` |
| `n` | integer | ✗ | 1 | 1 リクエストの生成数（1 – 4）；**4 超は 400 を返します**（サイレント切り捨てではありません）|

### 編集エンドポイント `/v1/images/edits`

**エンドポイント**：`POST {base_url}/images/edits`
**Content-Type**：`multipart/form-data`（ファイルアップロードは form-data 必須、JSON 不可）

フィールド：

| フィールド | 型 | 必須 | デフォルト | 値 / 説明 |
|---|---|---|---|---|
| `model` | string | ✓ | — | `gpt-image-2` 固定 |
| `image` | file（× N）| ✓ | — | 元画像（PNG / JPEG / WebP）；**1 – 8 枚の複数画像合成に対応**（複数枚は同一フィールド名を繰り返す：`-F image=@a.png -F image=@b.png`）|
| `mask` | file | ✗ | — | PNG alpha マスク；**透明部分**が再描画領域；mask の解像度は `image` と一致する必要あり（自動スケール）；単一画像編集にのみ有効 |
| `prompt` | string | ✓ | — | 編集指示（多言語）|
| `size` | string | ✗ | `auto` | `auto` / `1024x1024` / `1024x1536` / `1536x1024` / `2048x2048`。**出力解像度はモデルが自適応的に決定します（現在の実測は約 1254×1254）。`size` は意図のヒントとして扱われます**；不正な値は 422 を返します |
| `quality` | string | ✗ | `auto` | `auto` / `low` / `medium` / `high` |
| `n` | integer | ✗ | 1 | 1 リクエストの生成数（1 – 4）；**4 超は 400 を返します**（サイレント切り捨てではありません）|
| `background` | string | ✗ | `auto` | `auto` / `opaque`。**gpt-image-2 は `transparent` 非対応**（モデルは alpha チャンネルを生成できず、指定すると 400 を返します）|
| `output_format` | string | ✗ | `png` | `png` / `jpeg` / `webp` |
| `output_compression` | integer | ✗ | — | `0 – 100`、JPEG / WebP に有効（PNG では無視）；**範囲外は 400 を返します** |
| `input_fidelity` | string | ✗ | — | **廃止**：gpt-image-2 は常に高忠実度で入力画像を処理します。指定しても無視され、上流には転送されません |
| `response_format` | string | ✗ | `b64_json` | `b64_json` のみ受け付けます（`url` を指定すると 400 を返します）|
| `user` | string | ✗ | — | エンドユーザー ID のパススルー（上流の不正検出に使用）|

**アップロードサイズ上限**：単一ファイル ≤ 25 MB；複数ファイル合計 ≤ 200 MB（超えた場合は `413 image_too_large`）。

### レスポンス（両エンドポイント共通）

```json
{
  "created": 1777135432,
  "data": [
    {
      "b64_json": "iVBORw0KGgo...(base64 PNG/JPEG/WebP, 1-3 MB)",
      "revised_prompt": "A small ceramic vase with sunflower..."
    }
  ]
}
```

- `b64_json`：画像の base64 エンコードデータ、フロントエンドで `<img src="data:image/<format>;base64,...">` として直接レンダー可
- `revised_prompt`：モデルが元の prompt を改善したバージョン（ユーザーへの参考表示はオプション）

### エラーレスポンス

エラーは OpenAI 標準スキーマに準拠：

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "image_daily_limit",
    "message": "Daily image generation count limit reached..."
  }
}
```

| HTTP | code | 意味 |
|---|---|---|
| 401 | `invalid_api_key` | API キーが無効または無効化済み |
| 401 | `key_expired` | API キーの有効期限切れ |
| 413 | `image_too_large` | 単一ファイル > 25 MB、または合計 > 200 MB |
| 422 | `unsupported_size` | size がサポート外（有効な値は各エンドポイントのパラメータ表を参照）|
| 429 | `crs_daily_exhausted` | アカウントの 1 日予算上限到達 |
| 429 | `crs_total_exhausted` | アカウントの累計予算上限到達 |
| 429 | `image_daily_limit` | API キーごとの 1 日 100 枚上限到達（generations + edits 共有、引き上げ可）|
| 429 | `concurrency_exhausted` | API キーごとの 2 並列上限到達（引き上げ可）|
| 503 | `service_overloaded` | サービス全体の負荷が高い、後で再試行 |
| 503 | `image_provider_unavailable` | 上流が一時的に利用不可、後で再試行 |

---

## コードサンプル

### Python（OpenAI SDK、推奨）

**画像生成：**

```python
from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.generate(
    model="gpt-image-2",
    prompt="A cyberpunk Tokyo street at night, neon reflecting in rain puddles",
    size="1024x1024",
    quality="low",
    n=1,
)

img_bytes = base64.b64decode(result.data[0].b64_json)
with open("output.png", "wb") as f:
    f.write(img_bytes)
print("output.png を保存しました")
```

**画像編集（単一画像 + mask 部分再描画）：**

```python
from openai import OpenAI
import base64

client = OpenAI(
    base_url="https://api.qcode.cc/qcode-img/v1",
    api_key="cr_YOUR_QCODE_API_KEY",
    timeout=180.0,
)

result = client.images.edit(
    model="gpt-image-2",
    image=open("cat.png", "rb"),
    mask=open("mask.png", "rb"),
    prompt="put a tiny crown on the cat",
    size="1024x1024",
    quality="high",
    extra_body={"output_format": "png"},
)

img = base64.b64decode(result.data[0].b64_json)
with open("edited.png", "wb") as f:
    f.write(img)
```

**画像編集（複数画像合成、2 – 8 枚）：**

```python
result = client.images.edit(
    model="gpt-image-2",
    image=[
        open("scene.png", "rb"),       # 1 枚目：シーン背景
        open("product.png", "rb"),     # 2 枚目：配置する商品
    ],
    prompt="Place the product naturally into the scene, match the lighting and shadows.",
    size="1536x1024",
    quality="high",
)
```

### curl

**画像生成：**

```bash
curl https://api.qcode.cc/qcode-img/v1/images/generations \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "A cyberpunk Tokyo street at night",
    "size": "1024x1024",
    "quality": "low",
    "n": 1
  }' \
  | jq -r ".data[0].b64_json" | base64 -d > output.png
```

**画像編集：**

```bash
curl https://api.qcode.cc/qcode-img/v1/images/edits \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@cat.png" \
  -F "mask=@mask.png" \
  -F "prompt=put a tiny crown on the cat" \
  -F "size=1024x1024" \
  -F "quality=high" \
  -F "output_format=png" \
  | jq -r ".data[0].b64_json" | base64 -d > edited.png
```

**複数画像合成（`-F image=@` を繰り返すだけ）：**

```bash
curl https://api.qcode.cc/qcode-img/v1/images/edits \
  -H "Authorization: Bearer cr_YOUR_QCODE_API_KEY" \
  -F "model=gpt-image-2" \
  -F "image=@scene.png" \
  -F "image=@product.png" \
  -F "prompt=Place the product naturally into the scene" \
  -F "size=1536x1024" \
  -F "quality=high"
```

### JavaScript / Node.js / ブラウザ

**画像生成：**

```javascript
const r = await fetch("https://api.qcode.cc/qcode-img/v1/images/generations", {
  method: "POST",
  headers: {
    "Authorization": "Bearer cr_YOUR_QCODE_API_KEY",
    "Content-Type":  "application/json",
  },
  body: JSON.stringify({
    model: "gpt-image-2",
    prompt: "A cyberpunk Tokyo street at night",
    size: "1024x1024",
    quality: "low",
    n: 1,
  }),
});
const json = await r.json();
const dataUrl = "data:image/png;base64," + json.data[0].b64_json;
document.querySelector("img").src = dataUrl;
```

**画像編集（ブラウザ FormData）：**

```javascript
const fd = new FormData();
fd.append("model", "gpt-image-2");
fd.append("image", imageFile);              // <input type="file"> からの File オブジェクト
fd.append("mask", maskFile);                // オプション
fd.append("prompt", "put a tiny crown on the cat");
fd.append("size", "1024x1024");
fd.append("quality", "high");
fd.append("output_format", "png");

const r = await fetch("https://api.qcode.cc/qcode-img/v1/images/edits", {
  method: "POST",
  headers: { "Authorization": "Bearer cr_YOUR_QCODE_API_KEY" },
  // Content-Type は手動で設定しないでください — FormData が boundary 付き multipart/form-data を自動設定します
  body: fd,
});
const json = await r.json();
const dataUrl = "data:image/png;base64," + json.data[0].b64_json;
document.querySelector("img").src = dataUrl;
```

---

## クォータ規則

### デフォルト上限

| 項目 | デフォルト値 | 説明 |
|---|---|---|
| **1 日の画像数** | 100 枚 / 日 / キー | 北京時間 0 時にリセット；**generations と edits で共有** |
| **並列数** | 同時 2 件 | 超過時は 429 `concurrency_exhausted`；両エンドポイントで共有 |
| **アップロードサイズ**（edits のみ）| 単一ファイル 25 MB / 合計 200 MB | 超過時は 413 `image_too_large` |
| **アカウント予算** | QCode.cc アカウントの `dailyCostLimit` / `totalCostLimit` を共有 | 超過時は 429 `crs_daily_exhausted` |

デフォルトのクォータは大多数のユーザーに十分です。引き上げが必要な場合はサポートまでお問い合わせください。

### 使用状況の確認

- **顧客ダッシュボード**：チャットと画像コールを統合表示（最終使用時刻、当日コスト、累計コスト、モデル分布）
- **セルフサービスページ**：[https://api.qcode.cc/qcode-img/usage](https://api.qcode.cc/qcode-img/usage) — API キーを入力して直近 30 日の使用状況、詳細コール一覧、ECharts のトレンドグラフを確認（API キーはブラウザのローカルにのみ保存、サーバーには送信されません）

---

## 課金規則

### 基本料金（1 枚あたり）

`generations` と `edits` は同じ料金表を共有：

| size | low | medium | high |
|---|---|---|---|
| **1024×1024** | $0.08 (floor) | $0.08 (floor) | $0.211 |
| **1024×1536** | $0.08 (floor) | $0.08 (floor) | $0.165 |
| **1536×1024** | $0.08 (floor) | $0.08 (floor) | $0.165 |
| **2048×2048** | $0.08 (floor) | $0.08 (floor) | $0.285 |

### 最低単発料金 $0.08

- 実コストが $0.08 未満の場合は **$0.08** で課金（`low` / `medium` は大半がこの floor）
- 実コストが $0.08 以上の場合は実際の金額で課金（上乗せなし）
- **edits エンドポイントは上流が返す実際のトークン使用量に基づいて課金**され、$0.08 未満の場合は $0.08 で課金されます

### 複数枚と複数入力画像

- `n > 1` は**出力**枚数に線形比例。例：`n=2` + `1024×1024` high = 2 × $0.211 = $0.422
- `edits` の複数入力（`image=[…N]`）は、**入力枚数ではなく**出力枚数 `n` で課金
- `mask` は課金に影響しません

### 失敗は課金されません

4xx / 5xx の失敗リクエストは**課金されません**；クライアント切断（接続クローズ）も課金されません。

### 通貨

費用は USD で計算され、アカウント決済は QCode.cc メインアカウントの通貨ポリシー（人民元 / 米ドル）に従います。

---

## 生成時間とタイムアウト設定

`gpt-image-2` は推論ベースのモデルで、**従来の text-to-image（DALL·E 3 / SDXL）より大幅に時間がかかります**：

| quality | 典型時間 | 複雑 prompt の極端値 |
|---|---|---|
| `low` | 20 – 35 秒 | ~50 秒 |
| `medium` | 50 – 90 秒 | ~120 秒 |
| `high` | 70 – 120 秒 | ~150 秒 |

edits の実測値（成功した編集リクエスト）：**p50 ≈ 43 秒、p95 ≈ 91 秒、約 3% のリクエストが 100 秒を超えます**。CDN（100 秒ハードリミット）経由の長いリクエストは低確率で 524 になるため、編集では `quality=low` / `medium` を推奨します。

**実践的なアドバイス**：

- OpenAI Python SDK のデフォルト timeout は短すぎるため、**`timeout=180.0` 以上を必ず明示的に指定**
- ブラウザの `fetch` にはデフォルト timeout がありませんが、`AbortController` で設定する場合は最低 180 秒を確保
- 中国本土から medium / high を使う場合は `asia.qcode.cc` を推奨（CDN 100 秒制限なし）

---

## CDN 100 秒制限（524 エラー）

`api.qcode.cc / asia.qcode.cc / eu.qcode.cc / us.qcode.cc` 経由の HTTPS リクエストはグローバル CDN（CloudFlare）を通過します。**CDN は単一リクエストの応答待ちが 100 秒を超えると強制的に `524` を返します**。

| quality | CDN 100 秒で安全か |
|---|---|
| `low` | ✅ 安全（< 35 秒）|
| `medium` | ⚠️ ときどき上限に接触（100 秒に近い）|
| `high` | ❌ 頻繁に 524 |

**対策（medium / high の場合に推奨）**：

1. **`qcode-img` 直結エントリを利用**：`https://api.qcode.cc/qcode-img/v1`（CDN 経由なし、100 秒制限なし）
2. または、たまの 524 を許容してクライアント側で自動リトライ

---

## Prompt 作成のポイント

### 画像生成（generations）

- **多言語対応**：中国語、英語、混在いずれも可
- **詳細度が高いほど良い**：環境、構図、ライティング、スタイル、レンズ距離 / 焦点距離 / アングル等
- **ブランド名・著名人を避ける**：モデルが拒否したり、ぼやけた結果を返したりすることがあります（OpenAI コンテンツポリシー）
- **画像内の文字レンダリング**：`gpt-image-2` は文字レンダリング能力が非常に高く、画像内に英語・中国語のタイトル・短いフレーズ・ポスター文字を埋め込めます（prompt に直接書くだけ、特殊な記法不要）

例：

```
A vintage poster in Bauhaus style, bold black text "MORNING COFFEE" centered,
warm orange and cream color palette, geometric shapes, slightly textured paper background
```

### 画像編集（edits）

- **mask は「どこを」、prompt は「何に」**：透明部分が再描画領域、不透明部分は元画像を保持。mask の解像度は `image` と一致する必要があります（自動スケール）。
- **複数画像入力では prompt で各画像の役割を明示**：例 "First image is the scene, second image is the product to place into it" — `gpt-image-2` は順序通りに入力を解釈します。
- **`input_fidelity` の指定は不要**：gpt-image-2 は常に高忠実度で入力画像を処理し、顔・ロゴ・文字・商品ディテールを自動的に保持します（このパラメータは廃止済みで、指定しても無視されます）。
- **mask なしの場合**：画像全体が prompt に従って再描画されます（意味的構造は保持されますが、すべての領域が変わる可能性あり）。

例：

```
# 部分修復：猫に小さな冠を追加、他は元のまま
prompt = "Put a tiny golden crown on the cat's head. Keep everything else unchanged."
mask = (頭部分のみが透明な alpha PNG)
```

---

## OpenAI 公式 API との違い

| 項目 | OpenAI 公式 | QCode.cc |
|---|---|---|
| SDK 互換性 | — | ✅ 100% 互換、`base_url` のみ変更 |
| 課金 | トークン単位 | 上記料金表、1 枚 $0.08 floor |
| `/v1/images/generations`（画像生成）| ✅ | ✅ |
| `/v1/images/edits`（画像編集）| ✅ | ✅ **稼働中**（2026 年 5 月初回リリース、2026-07-29 復旧・強化：上流の実 usage に基づく課金）：1–8 枚の複数画像合成、mask 部分再描画 |
| `stream + partial_images`（増分返却）| ✅ | ⏳ 未対応；**`stream` / `partial_images` を指定すると 400 を返します** |
| `/v1/images/variations`（純バリエーション生成）| ✅（旧 DALL·E エンドポイント）| ⏳ 未対応（`edits` + 空 prompt で代替可）|

---

## オンライン Playground

[https://api.qcode.cc/qcode-img/](https://api.qcode.cc/qcode-img/) — ブラウザですぐ試用：

- **画像生成 + 画像編集** 両モードを GUI で操作（画像アップロード、mask 描画、background / output_format の選択など）
- API キー + Prompt を入力して即時生成
- 中英 UI 切替
- デフォルト `low` 品質（CDN 524 回避）
- 完全な API ドキュメントを内包（curl / Python / JavaScript の 3 タブ + パラメータ表 + エラーコード表）
- 生成画像を PNG / JPEG / WebP でワンクリックダウンロード

---

## 関連ドキュメント

- [エンドポイントと API パス](/ja/docs/getting-started/endpoints-and-api-paths) — QCode.cc のすべての接続ドメイン、プロトコルパス、curl 自己診断方法
- [課金説明](/ja/docs/reference/billing) — プラン、クォータ、費用規則