---
title: Masked editing — GPT-Image-2.5 Flare | Runware Docs
url: https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing
description: "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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#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.

![Two identical navy shampoo bottles standing side by side on a pale shelf against a plain white wall](https://runware.ai/docs/assets/source-bottles.Ca4crKAj_1uO2aj.jpg)

*Source*

![A black frame with a white block covering the position of the left bottle](https://runware.ai/docs/assets/mask-left.CuHXKz4t_ZLssT1.jpg)

*Mask*

![The same two bottles with the left one now warm terracotta and the right one still navy](https://runware.ai/docs/assets/output-masked.CzjtCGj-_Z20Htod.jpg)

*Result*

> **Prompt**: 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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#the-request)

A mask goes in `inputs.maskImage`, alongside the source in `inputs.referenceImages`.

**TypeScript**:

```typescript
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
})
```

**Python**:

```python
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**:

```bash
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
    }
  ]'
```

**CLI**:

```bash
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
```

**JSON**:

```json
{
  "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
}
```

Three rules govern the pair:

- **A mask needs a source.** `inputs.maskImage` sent without `inputs.referenceImages` is 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 `width` and `height` on 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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#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.

![Three shirts hanging on a retail rail against a pale wall, all in the same pale blue cotton](https://runware.ai/docs/assets/source-rail.233cQqkv_QtUzG.jpg)

*Source, three shirts*

![A black frame with a white rectangle covering the middle shirt along with some wall and the inner edges of the shirts either side of it](https://runware.ai/docs/assets/mask-middle.7FsI6uT__1lrR4z.jpg)

*A rough block over the middle shirt*

![The three shirts with the middle one changed to deep burgundy, the wall inside the masked rectangle unchanged and the neighbouring shirts still pale blue](https://runware.ai/docs/assets/output-bleed.DHWk-6UU_Z1s8yBv.jpg)

*The shirt changes, not the rectangle*

> **Prompt**: 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.

> [!WARNING]
> 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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#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.

Interactive component not available in Markdown.

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.

**TypeScript**:

```typescript
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
  }
})
```

**Python**:

```python
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**:

```bash
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
      }
    }
  ]'
```

**CLI**:

```bash
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
```

**JSON**:

```json
{
  "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.

![A woman standing against a plain grey studio wall in a cream knitted jumper and dark trousers, facing the camera](https://runware.ai/docs/assets/source-portrait.uPHVhAnE_ZzKi3A.jpg)

*Source*

![A black frame with a white silhouette following the woman's outline](https://runware.ai/docs/assets/mask-person.CDuQBOG3_Z13H8Ba.jpg)

*Segmentation mask*

![The same woman in the same pose against the same grey wall, now wearing a tailored charcoal suit over a white shirt](https://runware.ai/docs/assets/output-person.BXbXpIGq_Z1l2nyP.jpg)

*Result*

> **Prompt**: 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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#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](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/editing-images).

### [Tips](https://runware.ai/docs/models/openai-gpt-image-2-5-flare/guides/masked-editing#tips)

1. **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.
    
2. **Match the dimensions exactly.** The mask, the source, and `width` and `height` on the request all carry the same numbers.
    
3. **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.
    
4. **Write the preserve clause anyway.** The mask chooses the region, the instruction chooses what happens inside it, and neither replaces the other.
    
5. **Pad a segmentation mask.** Hair, fur and soft edges fall outside a tight silhouette, and `settings.maskPadding` is cheaper than repainting.
    
6. **Composite anything that has to be exact.** A mask localises an edit, it does not seal a region.