GPT-Image-2.6 Flare

GPT-Image-2.6 Flare is OpenAI's fast image model for generation and editing in interactive workflows. Besides raster images, it generates SVG graphics and animated GIFs from text, and it edits images from marks drawn over them, like a circle around the object to change. A thinking level sets how much it plans before rendering, separate from rendering quality.

Complete technical specification for integration
Ready-to-use code snippets for common workflows
Step-by-step tutorials for advanced use cases
← All GuidesMarkup editing
How to point GPT-Image-2.6 Flare at what to edit with a markup layer: building it, circling one item among look-alikes and marking where a new object goes.
Introduction
An edit instruction has to name its target, and position words name it badly when the frame holds two of the same thing. "The lamp on the left" can mean the camera's left or the left side of the bed. "The fourth can on the lower shelf" asks the model to count before it edits.
inputs.markupImage lets you point at the target instead of describing it. You draw a mark on a transparent layer the size of the photo, a ring around an object or an arrow at an empty spot, and send it with the photo. The prompt refers to the mark ("the lamp inside the red circle") and says what should change, then asks for the mark to be removed.
The prompt never says which side. The ring picks the lamp, so the words only have to describe the brass replacement and ask for the ring to go.
This guide covers the request, building the layer, the rules the API checks, writing the prompt around a mark, picking one item out of a row, marking where a new object goes, and how markup differs from a mask. Edits that need no mark are in editing images.
The request
A markup edit is an edit with one extra input. The photo goes first in inputs.referenceImages and the layer goes in inputs.markupImage.
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.6-flare',
positivePrompt: 'Replace the table lamp inside the red circle with a slim brushed brass table lamp with a white opal glass globe shade, standing on the same bedside table. Keep the other lamp, the bed, both bedside tables, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo.',
inputs: {
referenceImages: [
'https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/source-hero.jpg'
],
markupImage: 'https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/markup-hero.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.6-flare",
"positivePrompt": "Replace the table lamp inside the red circle with a slim brushed brass table lamp with a white opal glass globe shade, standing on the same bedside table. Keep the other lamp, the bed, both bedside tables, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo.",
"inputs": {
"referenceImages": [
"https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/source-hero.jpg"
],
"markupImage": "https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/markup-hero.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": "c4e81f27-9a3b-4d65-b812-5f0d7a2e6c93",
"model": "openai:gpt-image@2.6-flare",
"positivePrompt": "Replace the table lamp inside the red circle with a slim brushed brass table lamp with a white opal glass globe shade, standing on the same bedside table. Keep the other lamp, the bed, both bedside tables, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo.",
"inputs": {
"referenceImages": [
"https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/source-hero.jpg"
],
"markupImage": "https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/markup-hero.png"
},
"width": 1536,
"height": 1024
}
]'runware run openai:gpt-image@2.6-flare \
positivePrompt="Replace the table lamp inside the red circle with a slim brushed brass table lamp with a white opal glass globe shade, standing on the same bedside table. Keep the other lamp, the bed, both bedside tables, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo." \
inputs.referenceImages.0=https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/source-hero.jpg \
inputs.markupImage=https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/markup-hero.png \
width=1536 \
height=1024{
"taskType": "imageInference",
"taskUUID": "c4e81f27-9a3b-4d65-b812-5f0d7a2e6c93",
"model": "openai:gpt-image@2.6-flare",
"positivePrompt": "Replace the table lamp inside the red circle with a slim brushed brass table lamp with a white opal glass globe shade, standing on the same bedside table. Keep the other lamp, the bed, both bedside tables, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo.",
"inputs": {
"referenceImages": [
"https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/source-hero.jpg"
],
"markupImage": "https://assets.runware.ai/guides/openai-gpt-image-2-6-flare/markup-editing/markup-hero.png"
},
"width": 1536,
"height": 1024
}Response
[
{
"taskType": "imageInference",
"taskUUID": "c4e81f27-9a3b-4d65-b812-5f0d7a2e6c93",
"imageUUID": "6a2f9d04-8b17-4e3c-a5d9-1c7e0b4f2a68",
"imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/6a2f9d04-8b17-4e3c-a5d9-1c7e0b4f2a68.jpg"
}
]The request carries the clean photo and a layer that is transparent everywhere except the ring. The ringed photo at the top of this page is a preview for people, and it is not part of the request.

A hospitality photograph of a boutique hotel double room: a neatly made bed with crisp white linen and a folded sage green throw across the foot, a pale oak headboard against a warm white wall, and two matching pale oak bedside tables, one on each side of the bed. On each bedside table stands an identical white ceramic table lamp with a cream linen drum shade, both switched off. Soft daylight from a window out of frame on the left. Straight-on view at bed height, 35mm lens, the bed centered with both bedside tables and both lamps fully in frame. Photoreal hotel interior photography, warm neutral palette, no people, no text.

width and height repeat the photo's 1536 × 1024, which brings the result back at the size of the source. Both are optional, and without them the model picks the output size.
With several reference images, the marks apply to the first one and the rest serve as references. The photo you drew on always goes at the front of the array.
Building the markup layer
The layer is a PNG with an alpha channel, the exact pixel size of the photo, holding nothing but the marks. ImageMagick draws one onto a transparent canvas, and the same draw command run on the photo gives you the preview:
magick -size 1536x1024 xc:none \
-fill none -stroke "#ff1f1f" -strokewidth 8 \
-draw "ellipse 1290,430 154,225 0,360" \
PNG32:markup.png
magick photo.jpg \
-fill none -stroke "#ff1f1f" -strokewidth 8 \
-draw "ellipse 1290,430 154,225 0,360" \
preview.jpgxc:none is the transparent canvas. PNG32: writes a full RGBA file, where ImageMagick would otherwise pick an indexed format for an image that is almost entirely empty.
In an app, the user draws on a canvas laid over the photo. Size the canvas from the photo's pixels, the naturalWidth and naturalHeight of the <img>, not from the size it is displayed at: a photo shown 768 pixels wide still needs a 1536-pixel layer. Then export it as a PNG:
const canvas = document.createElement('canvas')
canvas.width = photo.naturalWidth
canvas.height = photo.naturalHeight
const context = canvas.getContext('2d')
context.strokeStyle = '#ff1f1f'
context.lineWidth = 8
context.beginPath()
context.ellipse(1290, 430, 154, 225, 0, 0, Math.PI * 2)
context.stroke()
const markupImage = canvas.toDataURL('image/png')A new canvas starts fully transparent, so the export holds the strokes and nothing else. The data URI goes into inputs.markupImage as it is.
Validation rules
Each of these is checked on every markup request, and a request that breaks one is rejected:
- A layer of a different size. Its width and height must equal the first reference's. For a photo with an EXIF rotation flag, the size that counts is the one after rotation.
- A layer with no transparent pixels. A fully opaque PNG is rejected, so neither the flattened preview nor a black and white mask can stand in for the layer.
- A layer in another format. It has to be a PNG.
- A first reference over 16,777,216 pixels. That is 4096 × 4096, or any shape with the same area. The cap applies to the image the marks are drawn on, and a larger second reference is accepted. The layer has the same pixel cap and a 50 MB file limit.
- A layer without a reference. Markup needs
inputs.referenceImages.SVGandGIFoutput take no reference images, so a markup edit returnsJPG,PNGorWEBP. - A layer with a mask.
inputs.markupImageandinputs.maskImagecannot be sent together.
Writing the prompt
The layer says where. The prompt still says what, and every markup prompt in this guide does four things:
Refer to the mark, not to a position. "The table lamp inside the red circle" holds wherever the ring lands, so one sentence template serves every photo your users mark.
Describe the change in full. The ring says nothing about the replacement. Everything the new lamp should be, from the brushed brass to the globe shade, comes from the words.
List what stays, starting with the look-alike. "The other lamp" matches the target exactly before the edit, and the preserve clause is where you say it stays that way.
Ask for the mark to be removed. The ring is drawn over the photo, and the prompt is where you say it is not part of the finished image.
Picking one of several
In a row of identical products a position phrase gets long: in words, the target on the shelf below is "the fourth can from the left on the lower shelf". With markup the prompt never names a position. The user taps a can and your code rings it, and the prompt says "the can inside the red circle" wherever it sits.
Recolor the can inside the red circle to matte lemon yellow with the wave mark in white. Keep its shape, its size, its position and the light on it. Keep the other nine cans white, and keep the shelves, the wall, the framing and the lighting exactly as they are. Remove the red circle from the finished photo.The preserve clause names the look-alikes by count and color, "the other nine cans white", so the recolor has one target and nine cans to leave alone. Draw the ring with clear space between it and the neighboring cans, so it encloses one object. For a planogram mockup, that shows a new flavor in one facing without reshooting the shelf.
Pointing at an empty spot
An addition has nothing to circle. Point at the spot instead, with an arrow whose tip lands where the new object should stand. The office below gets a plant in its empty corner:
Add a tall potted olive tree in a matte white ceramic floor planter, standing on the floor exactly where the tip of the red arrow points, its crown reaching about two thirds of the way up the wall, with a soft contact shadow that matches the daylight from the window. Keep the desk, the chair, the window, the wall, the floor, the framing and the lighting exactly as they are. Remove the red arrow from the finished photo.The prompt refers to the arrow the way the shelf prompt refers to the ring: "exactly where the tip of the red arrow points". An arrow marks a position and carries no size, so the prompt sets the scale against the room, "about two thirds of the way up the wall", and asks for a contact shadow that matches the window light. For a listing photo, that stages an empty corner without another shoot.
Markup and masks
inputs.maskImage also aims an edit at part of the first reference, and a request takes one or the other. The two describe the target differently. A mask covers the whole frame in black and white, with white where the edit goes. A markup layer is a drawing on transparency that the model reads together with the prompt, so the prompt can name the mark itself, as in "the lamp inside the red circle" or "where the red arrow points".
The housekeeping is shared: both are PNG files at the first reference's exact size, and both need a reference image to apply to.
Tips
-
Keep the photo clean. The marks go in
inputs.markupImage, and the reference stays the untouched photo. -
Size the layer from the photo's pixels. Its width and height must match the first reference after rotation, whatever size the photo is displayed at.
-
Draw in a color the photo does not contain. The prompt names the mark by its color, so "the red circle" should match one thing in the frame.
-
Refer to the mark, not a position. "Inside the red circle" and "where the red arrow points" work wherever the mark lands.
-
Name the look-alikes in the preserve clause. "The other lamp" and "the other nine cans" say which objects stay as they are.
-
Ask for the marks to be removed. Every prompt in this guide ends with that sentence.
-
Give an addition its size in words. An arrow marks a spot and carries no scale.





