You would use the image edits
endpoint, but would specify the gpt-image-1
API model. This requires a different set of form-data parameters than dalle-e-2
, essentially treating it like a different API.
It can accept multiple images, and uses discussion instead of mask, because it can only regenerate the entire image.
An organization requires personal government ID verification and selfie video of the person to use this model.
Here is an example procedural non-async Python script to make a highest-quality request with the type of description needed for synthesis, also using the more costly input_fidelity
parameter. For the three input images demonstrated, the total would be about $0.44 per API call.
"""
Edit images with /v1/images/edits (model gpt-image-1) via httpx.
"""
import os
import base64
from pathlib import Path
import logging
import httpx # non-built-in, may already be installed by `openai` module
logging.basicConfig(level=logging.INFO)
# user inputs
PROMPT = """
The first image is me in a pink dress.
The second image is another model wearing a light paisley dress and top.
The third image is a satin cover-up top.
Produce a new image where I am wearing the dress from the second image and the top from the third image.
"""
INPUT_PATHS = [
"images/input-woman.jpg", # file name, or with directories, relative or absolute
"images/input-dress.webp",
"images/input-top.jpg",
] # add more paths as needed
OUTPUT_FILE = "new-ai-image.png"
params = {
"model": "gpt-image-1",
"prompt": PROMPT.strip(), # text prompt
"quality": "high", # "high" | "medium" | "low"
"size": "auto", # "1024x1024" | "1536x1024" | "1024x1536" | "auto"
"output_format": "png", # "png" | "jpg" | "webp"
# "output_compression": 95, # lossy jpg/webp only (0‑100)
"background": "opaque", # "opaque" | "transparent"
"input_fidelity": "high", # extra cost for better copying
"stream": "false", # "true" streams chunks
#"user": "myCustomer",
}
url = "https://api.openai.com/v1/images/edits"
def get_auth_headers() -> dict:
api_key = os.getenv("OPENAI_API_KEY")
if not api_key:
raise RuntimeError("OPENAI_API_KEY env var is missing")
return {"Authorization": f"Bearer {api_key}"}
# build multipart parts
multipart_parts = []
for p in map(Path, INPUT_PATHS):
ext = p.suffix.lower().lstrip(".")
mime = {
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"webp": "image/webp",
}.get(ext, "image/png") # default to image/png
multipart_parts.append(("image[]", (p.name, p.open("rb"), mime)))
multipart_parts.extend((k, (None, str(v))) for k, v in params.items())
try:
with httpx.Client(timeout=240.0) as client:
resp = client.post(url, files=multipart_parts, headers=get_auth_headers())
resp.raise_for_status()
except httpx.HTTPStatusError as e:
logging.error("OpenAI API error [%s]: %s", e.response.status_code, e.response.text)
raise
except httpx.RequestError as e:
logging.error("Request error: %s", e)
raise
# decode image
b64 = resp.json()["data"][0]["b64_json"]
img_bytes = base64.b64decode(b64)
# find unused output name, increments name suffix to prevent overwrite
out_path = Path(OUTPUT_FILE)
out_path.parent.mkdir(parents=True, exist_ok=True)
if out_path.exists():
stem, suffix = out_path.stem, out_path.suffix or ".png"
idx = 2
while (candidate := out_path.with_name(f"{stem}{idx}{suffix}")).exists():
idx += 1
out_path = candidate
out_path.write_bytes(img_bytes)
print(f"Image written to {out_path.resolve()}")