GPT-Image-2.5 Flare

GPT-Image-2.5 Flare is OpenAI's fastest model for high-quality image generation and editing, delivering higher-quality images than GPT Image 2 at 50% lower latency. It improves natural lighting, texture detail, reference-subject preservation, localized editing, and consistency across iterative edits, while handling complex layouts and transparent backgrounds. It is designed for creator content, product experiences, visual search, rapid prototyping, and high-volume generation.

Complete technical specification for integration
Ready-to-use code snippets for common workflows
Step-by-step tutorials for advanced use cases
← All GuidesMasked editing
How to confine an edit to a painted region with GPT-Image-2.5 Flare: what white and black mean, and why the mask is guidance rather than a hard boundary.
Introduction
Words run out when a frame holds two of the same thing. "Change the bottle" is a complete sentence and an incomplete instruction when there are two bottles on the shelf, and no amount of rephrasing tells the model which one without describing a position it may or may not agree with.
A mask says which one by pointing. You send the source, a black and white image the same size as it, and the instruction. White marks what may change and black marks what is preserved, so the ambiguity is settled before the model reads a word.



Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged.
The instruction never says "left". The mask does.
This guide covers the request, what the mask actually controls, how to make one, and the cases where words do the job better.
The request
A mask goes in inputs.maskImage, alongside the source in inputs.referenceImages.
import { createClient } from '@runware/sdk'
const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()
const [result] = await client.run({
model: 'openai:gpt-image@2.5-flare',
positivePrompt: 'Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged.',
inputs: {
referenceImages: [
'https://im.runware.ai/image/os/a14d18/ws/2/ii/3e8b1d5f-9a20-4c74-8156-2f7a0c9e4b63.jpg'
],
maskImage: 'https://im.runware.ai/image/os/a14d18/ws/2/ii/8c1a4f7d-2b93-4e06-b548-6a9d3f0c1e75.png'
},
width: 1536,
height: 1024
})import asyncio
import os
from runware import Runware
async def main():
async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
results = await client.run({
"model": "openai:gpt-image@2.5-flare",
"positivePrompt": "Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged.",
"inputs": {
"referenceImages": [
"https://im.runware.ai/image/os/a14d18/ws/2/ii/3e8b1d5f-9a20-4c74-8156-2f7a0c9e4b63.jpg"
],
"maskImage": "https://im.runware.ai/image/os/a14d18/ws/2/ii/8c1a4f7d-2b93-4e06-b548-6a9d3f0c1e75.png"
},
"width": 1536,
"height": 1024
})
asyncio.run(main())curl https://api.runware.ai/v1 \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"taskType": "imageInference",
"taskUUID": "7f2c5a8e-1b46-4930-a75d-8e3f1c6b2d04",
"model": "openai:gpt-image@2.5-flare",
"positivePrompt": "Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged.",
"inputs": {
"referenceImages": [
"https://im.runware.ai/image/os/a14d18/ws/2/ii/3e8b1d5f-9a20-4c74-8156-2f7a0c9e4b63.jpg"
],
"maskImage": "https://im.runware.ai/image/os/a14d18/ws/2/ii/8c1a4f7d-2b93-4e06-b548-6a9d3f0c1e75.png"
},
"width": 1536,
"height": 1024
}
]'runware run openai:gpt-image@2.5-flare \
positivePrompt="Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged." \
inputs.referenceImages.0=https://im.runware.ai/image/os/a14d18/ws/2/ii/3e8b1d5f-9a20-4c74-8156-2f7a0c9e4b63.jpg \
inputs.maskImage=https://im.runware.ai/image/os/a14d18/ws/2/ii/8c1a4f7d-2b93-4e06-b548-6a9d3f0c1e75.png \
width=1536 \
height=1024{
"taskType": "imageInference",
"taskUUID": "7f2c5a8e-1b46-4930-a75d-8e3f1c6b2d04",
"model": "openai:gpt-image@2.5-flare",
"positivePrompt": "Change the bottle to a warm terracotta with a matte finish. Keep its shape, its cap, its label placement and the light on it unchanged.",
"inputs": {
"referenceImages": [
"https://im.runware.ai/image/os/a14d18/ws/2/ii/3e8b1d5f-9a20-4c74-8156-2f7a0c9e4b63.jpg"
],
"maskImage": "https://im.runware.ai/image/os/a14d18/ws/2/ii/8c1a4f7d-2b93-4e06-b548-6a9d3f0c1e75.png"
},
"width": 1536,
"height": 1024
}Response
[
{
"taskType": "imageInference",
"taskUUID": "7f2c5a8e-1b46-4930-a75d-8e3f1c6b2d04",
"imageUUID": "0d6e2b9f-5c81-4a37-9e04-3b7d1f8a5c26",
"imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/0d6e2b9f-5c81-4a37-9e04-3b7d1f8a5c26.jpg"
}
]Three rules govern the pair:
- A mask needs a source.
inputs.maskImagesent withoutinputs.referenceImagesis a validation error, because a mask on its own has nothing to point at. - The mask matches the source's dimensions. A 1536 × 1024 source takes a 1536 × 1024 mask, and
widthandheighton the request stay on the same numbers. - With several reference images, the mask applies to the first. There is no way to aim it at the second or third, so the image you are editing goes at the front of the array.
The mask is guidance, not a boundary
This is the part that surprises people. The mask tells the model where to concentrate, and the model works out what to do with the contents rather than filling the shape you drew. Paint a rough rectangle over an object and you get the object edited, not a repainted rectangle. The same latitude runs the other way, so pixels just outside the white region are not guaranteed to survive byte for byte.
The rail below has three shirts on it. The mask is a plain block over the middle one, wide enough to catch some wall and a little of its neighbours, and the instruction asks for a colour change.



Change the shirt to a deep burgundy. Keep its cut, its collar, its buttons and the way it hangs on the hanger unchanged.
The wall caught inside the rectangle stayed a wall, and the shirt inside it became burgundy. The model read the mask as an area to attend to and worked out for itself which pixels in it were the shirt. That latitude is why a rough mask is usually good enough, and it is also why the edges of a masked edit can move: the same judgment that spares the wall can decide a neighbouring shirt's shadow should change too.
Do not use a mask as a legal or brand guarantee. If a logo, a price or a licensed element sits next to the region you are editing, the safe pattern is to edit, then composite the protected element back over the result yourself. The mask makes the edit local, not sealed.
Two habits follow from that. Leave a margin between the white region and anything that must not move, since a mask drawn hard against a neighbour invites the model to negotiate the shared edge. And still write the preserve clause, because the instruction and the mask are read together rather than as alternatives.
Making a mask
A mask is a black image with white where the edit goes. Paint one below to see the shape a model receives.
Drop an image here or browse
For anything repeatable, generate the mask instead of painting it. A separate masking task returns a mask for a subject it can segment, which is the whole job for people.
import { createClient } from '@runware/sdk'
const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()
const [result] = await client.run({
model: 'runware:35@5',
inputs: {
image: 'https://im.runware.ai/image/os/a14d18/ws/2/ii/5b8e2c9a-1d47-4f60-8375-9c2e0a6b4d18.jpg'
},
settings: {
maskPadding: 12
}
})import asyncio
import os
from runware import Runware
async def main():
async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
results = await client.run({
"model": "runware:35@5",
"inputs": {
"image": "https://im.runware.ai/image/os/a14d18/ws/2/ii/5b8e2c9a-1d47-4f60-8375-9c2e0a6b4d18.jpg"
},
"settings": {
"maskPadding": 12
}
})
asyncio.run(main())curl https://api.runware.ai/v1 \
-H "Authorization: Bearer $RUNWARE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"taskType": "imageMasking",
"taskUUID": "2a9d6f3b-8e15-4c70-b283-5f1a7d4e0c96",
"model": "runware:35@5",
"inputs": {
"image": "https://im.runware.ai/image/os/a14d18/ws/2/ii/5b8e2c9a-1d47-4f60-8375-9c2e0a6b4d18.jpg"
},
"settings": {
"maskPadding": 12
}
}
]'runware run runware:35@5 \
inputs.image=https://im.runware.ai/image/os/a14d18/ws/2/ii/5b8e2c9a-1d47-4f60-8375-9c2e0a6b4d18.jpg \
settings.maskPadding=12{
"taskType": "imageMasking",
"taskUUID": "2a9d6f3b-8e15-4c70-b283-5f1a7d4e0c96",
"model": "runware:35@5",
"inputs": {
"image": "https://im.runware.ai/image/os/a14d18/ws/2/ii/5b8e2c9a-1d47-4f60-8375-9c2e0a6b4d18.jpg"
},
"settings": {
"maskPadding": 12
}
}The mask that comes back goes straight into inputs.maskImage on the next call. settings.maskPadding grows the white region outward, which matters for hair and soft edges that a tight segmentation clips.



Change her clothing to a tailored charcoal suit over a white shirt. Keep her face, her hair, her pose, her hands and the studio wall unchanged.
The segmentation covers the whole person, so the instruction has to do the narrowing inside it: the clothing changes, and the face and hair are named as things that stay. A mask and an instruction divide the work, one choosing the region and the other choosing what happens in it.
When a mask earns its place
Reach for one in three situations, and skip it otherwise.
Two of the same thing are in frame. Two bottles on a shelf, or a row of identical windows. Words cannot pick one out reliably, and a mask picks it out exactly.
The region has no name. A patch of wall, an area of sky, the empty third of a frame where a headline will sit. Anything you would have to describe by its coordinates is faster to paint.
The edit is small and the frame is busy. A large detailed scene gives the model a lot to reconsider, and a mask keeps its attention on the part you care about.
When words are enough
An unmasked instruction is the better tool more often than you would expect, and reaching for a mask by reflex costs you quality.
Whole-object changes want context. A material change on the only kettle in the frame is unambiguous already, and the model does a better job when it can see how light moves across the whole object rather than only inside a shape you drew.
A change with knock-on effects needs room. Switching a lamp on changes the wall behind it, the table under it and the shadows across the room. Mask the lamp and you have told the model not to touch the things the edit is supposed to change.
The subject is the only one of its kind. One person in the frame, or one product on the table. The instruction is already specific, and the mask only adds a boundary to negotiate. Those cases belong in editing images.
Tips
-
Put the image you are editing first. With several references, the mask applies to the first entry and there is no way to redirect it.
-
Match the dimensions exactly. The mask, the source, and
widthandheighton the request all carry the same numbers. -
Leave a margin around anything protected. A mask drawn hard against a neighbour invites the model to resolve the shared edge in its own favour.
-
Write the preserve clause anyway. The mask chooses the region, the instruction chooses what happens inside it, and neither replaces the other.
-
Pad a segmentation mask. Hair, fur and soft edges fall outside a tight silhouette, and
settings.maskPaddingis cheaper than repainting. -
Composite anything that has to be exact. A mask localises an edit, it does not seal a region.