# GPT Image 2で透過PNG・WebPを作る：APIの生成・編集と保存方法

> GPT Image 2の背景透過APIをPythonで使う方法。ChatGPTとの対応の違い、PNG・WebPの保存、既存画像の編集、アルファ値の判定を整理し、背景が白く見える原因を切り分けます。

- Source: https://www.aifreeapi.com/ja/posts/gpt-image-2-transparent-background
- Language: ja
- Published: 2026-09-03
- Updated: 2026-09-12
- Publisher: AI Free API (https://www.aifreeapi.com)

GPT Image 2で透過素材を作るには、OpenAIのImages APIで`background="transparent"`と`output_format="png"`または`"webp"`を指定します。2026年9月8日時点で、背景透過は**プレビュー提供**です。JPEGでは透明度を保存できません。[OpenAIの画像出力ガイド](https://developers.openai.com/api/docs/guides/image-generation#customize-image-output)に現在の対応条件が記載されています。

ただし、PNGやWebPという形式名だけでは、背景が透明になったとは判断できません。まずAPIの返却データを復号して保存し、次にアルファ値、最後に別の背景へ重ねたときの輪郭を確認します。以下のAPI例は公式仕様に基づく実装例で、生成品質や成功率を測定した結果ではありません。ファイルの検査や変換は、APIを呼び出さず手元の画像でも実行できます。

## APIの背景透過とChatGPTでの操作は分けて考える

「GPT Image 2は背景透過に対応していない」という古い説明と、現在のAPIの説明では前提が異なります。対応を調べるときは記事の日付に加え、OpenAIのImages API、ChatGPTの画面、外部の画像生成サービスのどれを扱っているかを確認してください。ここで示すパラメータはOpenAIのImages API向けです。

APIが透過出力に対応していても、それだけでChatGPTの特定の画面やダウンロード操作については判断できません。ChatGPTで「背景を透明にして」と頼んだ結果が白く見える場合は、まずダウンロードした画像ファイルを確認します。会話画面のスクリーンショットでは、元の画像の透過情報を調べられません。

画像ビューアーやWebページは、透明な部分を白い下地の上に表示することがあります。白く見えることだけを理由に再生成する前に、後述のアルファ検査を行ってください。ファイルに透過成分があれば表示側の下地を確認し、全面不透明なら生成条件や保存・変換の工程を調べる、という順序で切り分けられます。

## PNGとWebPは出力時に選ぶ

編集用の元データとして保管するならPNG、配信先がWebPを扱えるならWebPを選べます。どちらも透過を扱えますが、受け取り側のソフトや配信処理が対応していることが前提です。

| 指定・確認項目 | 透過PNG | 透過WebP |
| --- | --- | --- |
| `background` | `"transparent"` | `"transparent"` |
| `output_format` | `"png"` | `"webp"` |
| `output_compression` | 省略する | 必要な場合だけ指定する |
| 保存する拡張子 | `.png` | `.webp` |
| ファイルを配信する際のMIME | `image/png` | `image/webp` |

PNGは既定の出力形式ですが、処理を読みやすくするため例では明示します。WebPの圧縮指定については、数値がそのまま容量削減率や料金の割引率になるわけではありません。また、WebPという形式が可逆圧縮に対応していることと、APIの任意の設定が可逆になることは別です。[公式のプロンプトガイド](https://developers.openai.com/cookbook/examples/multimodal/image-gen-models-prompting-guide)と[WebPの形式説明](https://developers.google.com/speed/webp/docs/api)を区別して参照してください。

![透過素材の生成からファイル保存、アルファ値の検査、白・暗色背景での確認までの流れ](https://www.aifreeapi.com/posts/ja/gpt-image-2-transparent-background/img/transparent-assets-one.webp)

## Pythonで生成し、返ってきた形式のまま保存する

Python環境に`openai`と`Pillow`をインストールし、`OPENAI_API_KEY`環境変数を設定して実行します。キーはソースコードに埋め込みません。APIを実行すると利用料金が発生します。

```bash
python -m pip install openai Pillow
```

次を`generate_asset.py`として保存します。`FORMAT`を`"webp"`へ変更すれば、同じ保存処理でWebPを扱えます。

```python
import base64
from io import BytesIO
from pathlib import Path

from openai import OpenAI
from PIL import Image

FORMAT = "png"  # "png" または "webp"
client = OpenAI()

result = client.images.generate(
    model="gpt-image-2",
    prompt=(
        "アプリ内で使う、青い旅行かばんのアイコンを1つ作成してください。"
        "かばん全体を独立した素材として収め、背景は完全に透過してください。"
        "風景、単色の背景、市松模様、枠線、影は追加しないでください。"
        "持ち手と本体の輪郭を明瞭にしてください。"
    ),
    background="transparent",
    output_format=FORMAT,
    size="1024x1024",
    quality="medium",
)

if not result.data or not result.data[0].b64_json:
    raise RuntimeError("応答に画像のbase64データがありません")

raw = base64.b64decode(result.data[0].b64_json, validate=True)
with Image.open(BytesIO(raw)) as image:
    actual_format = image.format
    image.load()

if actual_format != FORMAT.upper():
    raise RuntimeError(f"要求は{FORMAT}、返却内容は{actual_format}です")

output = Path(f"suitcase.{FORMAT}")
output.write_bytes(raw)
print(f"保存しました: {output} ({len(raw)} bytes)")
```

この例は、復号したバイト列が実際にPNGまたはWebPであることをPillowで確認し、そのまま保存します。拡張子だけを変えたり、base64文字列をテキストのまま書き出したりしません。Images APIの応答形式は[公式の生成ガイド](https://developers.openai.com/api/docs/guides/image-generation)で確認できます。

プロンプトでは素材の範囲と不要な背景を伝え、APIパラメータでは背景とファイル形式を指定しています。接地感のある影が必要な素材なら、例の「影は追加しない」を用途に合わせて変更してください。不要な影を除外することと、すべての透過素材から影を消すことは同じではありません。

## 既存画像の背景を外すときは編集APIを使う

商品写真などを渡す場合は、先ほどの`client.images.generate(...)`とその代入部分を、次の処理に置き換えます。下に続くbase64の復号・形式確認・保存はそのまま使えます。入力ファイル`product.png`を用意し、`FORMAT`には保存したい形式を指定してください。

```python
with open("product.png", "rb") as source:
    result = client.images.edit(
        model="gpt-image-2",
        image=source,
        prompt=(
            "商品の背景だけを取り除き、完全な透過背景にしてください。"
            "商品の形状、比率、色、ラベルの文字を維持してください。"
            "白い縁、背景色のにじみ、市松模様、不要な影を追加しないでください。"
        ),
        background="transparent",
        output_format=FORMAT,
        size="1024x1024",
    )
```

編集を追加するときも、透過背景を維持する指示と`background="transparent"`を再指定します。前の画像が透過PNGだったからといって、次の編集も自動で透過を保つと決めつけないでください。

生成モデルへの指示は、ラベルや形状の画素単位での保持を保証しません。商品の印字やロゴを厳密に維持する必要がある場合は、元画像との比較を行い、変化していればマスクによる切り抜きや手作業での修正を選びます。

## アルファ値で「不透明」と「空画像」を見分ける

Pillowで`RGBA`と表示されることは、アルファチャンネルを持つことを意味します。すべての値が255なら全面不透明です。反対に、すべて0なら何も表示されない全透明の画像です。

次を`check_alpha.py`として保存し、APIから受け取ったファイルに実行します。PNGにもWebPにも使えます。

```python
import sys
from pathlib import Path
from PIL import Image

path = Path(sys.argv[1])
with Image.open(path) as source:
    source.load()
    actual_format = source.format
    original_mode = source.mode
    rgba = source.convert("RGBA")

alpha = rgba.getchannel("A")
minimum, maximum = alpha.getextrema()
histogram = alpha.histogram()
total = rgba.width * rgba.height

expected = {".png": "PNG", ".webp": "WEBP"}.get(path.suffix.lower())
print(f"形式={actual_format}, 元のモード={original_mode}, 寸法={rgba.size}")
if expected and expected != actual_format:
    print(f"注意: 拡張子は{expected}ですが、内容は{actual_format}です")
print(f"アルファ最小値={minimum}, 最大値={maximum}")
print(f"完全透明={histogram[0]}/{total}, 完全不透明={histogram[255]}/{total}")
print(f"半透明={sum(histogram[1:255])}/{total}")

if maximum == 0:
    print("全透明です。表示される被写体がありません")
elif minimum == 255:
    print("全面不透明です。透過ピクセルはありません")
else:
    print("透過成分があります。重ね合わせて輪郭を確認してください")

for name, color in [("white", (255, 255, 255)), ("dark", (25, 30, 40))]:
    background = Image.new("RGBA", rgba.size, (*color, 255))
    preview = Image.alpha_composite(background, rgba).convert("RGB")
    preview.save(path.with_name(f"{path.stem}-on-{name}.png"))
```

```bash
python check_alpha.py suitcase.png
```

`convert("RGBA")`は検査のためにモードをそろえる処理で、白背景を除去する処理ではありません。もともと透過情報のないRGB画像は、変換してもアルファ値がすべて255になります。パレット形式のPNGなども含めて同じ手順で調べられます。[PillowのImageリファレンス](https://pillow.readthedocs.io/en/stable/reference/Image.html)に各操作の仕様があります。

判定結果が「透過成分があります」でも、素材として完成したとは限りません。生成された白背景に小さな透明の穴が1つある場合も、この条件に当てはまります。煙やガラスでは半透明だけが存在し、完全透明や完全不透明のピクセルを持たない場合もあります。用途を無視した透過率の合格ラインは設けず、生成した白・暗色背景の確認用画像で被写体を見ます。

確認用画像は背景を合成したRGB画像なので、透過素材の代わりに納品しないでください。白い縁、髪や持ち手の欠け、背景色の残りを確認するためのものです。市松模様がどちらの背景でも同じように残るなら、画像そのものに模様が描かれている可能性があります。

![旅行かばんの画像で透過の有無と輪郭を調べ、WebP変換後も確認する手順](https://www.aifreeapi.com/posts/ja/gpt-image-2-transparent-background/img/transparent-assets-two.webp)

## PNGをWebPへ変換した後も同じ検査を行う

APIで直接WebPを受け取るほか、保存済みPNGからWebPを作る方法もあります。以下はPillowで可逆圧縮を指定する例です。ここでの`lossless=True`は**ローカル変換の設定**で、APIの`output_compression`とは別です。

```python
from PIL import Image

with Image.open("suitcase.png") as source:
    rgba = source.convert("RGBA")
    rgba.save("suitcase.webp", format="WEBP", lossless=True, exact=True)
```

`exact=True`は透明ピクセル内のRGB値を保持する指定です。設定の意味は[PillowのWebP保存オプション](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#webp)で確認できます。この例では寸法を変えていません。ファイルがPNGより小さくなるかは画像によるため、実際のバイト数で比較します。

```bash
python check_alpha.py suitcase.webp
```

WebPへ保存する前に`RGB`へ変換すると、透明度が失われます。JPEGを中間ファイルに使った場合も同様です。サムネイル生成やCDNを通すなら、元ファイルだけでなく、利用者に配信されるファイルをダウンロードして再確認します。HTTPの成功ステータスや`Content-Type`は受け渡しの確認には使えますが、透過ピクセルが存在する証明にはなりません。

## うまくいかないときに確認する順序

| 現象 | 次に確認すること |
| --- | --- |
| リクエストが拒否される | エラー本文と、実際に送ったモデル名・背景指定・出力形式を確認。PNGに圧縮指定を付けていないかも調べる |
| base64がない、画像を開けない | 生の応答を画像として保存していないか、取得フィールドや復号処理が正しいかを確認 |
| `.png`なのに内容がJPEG | API直後のバイト列と、変換・保存処理を比較。拡張子の変更だけで済ませない |
| アルファ最小値が255 | 元の応答にも透過がないかを検査し、背景指定とプロンプトを確認 |
| アルファ最大値が0 | 何も表示されない空画像として扱い、別名で保持した元データと被写体の指示を確認 |
| 画面では白く見えるが、ファイルには透過成分がある | 白・暗色背景の確認用画像を比較。ビューアーの下地か、画像内に白背景が残っているかを見分ける |
| 透過はあるが輪郭が不自然 | 白・暗色の背景へ重ねて確認。素材に応じて編集やマスク修正を行う |
| 編集後、または変換後だけ背景が戻る | 直前と直後のファイルを検査。編集指示の透過維持、RGB/JPEGへの変換を確認 |

中継サービスを使っている場合は、公式と同じパラメータ名を受け付けることだけで、同じ出力になるとは判断できません。実際のモデル識別子、送信パラメータ、返却ファイルの形式、アルファ値を対応づけて確認します。認証情報はログに残さないでください。

API全体の使い分けや接続方法から整理したい場合は、[GPT Image 2 APIの利用方法](/ja/topics/gpt-image)を参照してください。透過素材の確認では、APIから保存した元ファイルと配信用の最終ファイルを残しておくと、どの処理で透明度や輪郭が変わったかを追えます。
