Did the edit stay in its region? A pixel-diff check for GPT Image 2.5

After a GPT Image 2.5 edit, measure how much changed outside the area you meant to change. A Pillow script that diffs the result against the original.

5 min readSume
All posts

To check that a GPT Image 2.5 edit changed only the area you meant, download the result, resize it to the original's size, black out the region you edited in both pictures, and measure what still differs. A mean difference near zero outside the box means the rest held; a high value means the model touched more than you asked.

Both OpenAI's Image prompting guide and fal's GPT Image 2.5 guide (read 2026-10-02) warn that repeated edits can still change details you meant to keep, and say to inspect each result. Sume's Image API page lists mask_url for GPT Image 2.5 edits but does not publish a pixel-exact guarantee, so a measurement is worth running.

Why measure instead of looking?

A slight shift in a background texture or a tone change in skin is easy to miss by eye and easy to catch with a number. The check is cheap: it runs locally and costs nothing on Sume. It is also useful as a gate in a batch, where you cannot look at every image.

What does the script do?

You give it the original file, the result URL and the box you meant to edit as left, top, right, bottom in the original's pixels. The script resizes the result to the original's size, masks the box out of the difference and reports the mean change per channel. Run pip install pillow requests. The threshold is yours to choose; start by running it on a result you consider good and a result you consider bad.

import io, sys, requests
from PIL import Image, ImageChops, ImageDraw, ImageStat

orig_path, result_url = sys.argv[1], sys.argv[2]
box = tuple(int(v) for v in sys.argv[3:7])  # left top right bottom

orig = Image.open(orig_path).convert("RGB")
res = Image.open(io.BytesIO(requests.get(result_url, timeout=60).content))
res = res.convert("RGB").resize(orig.size)

diff = ImageChops.difference(orig, res)
ImageDraw.Draw(diff).rectangle(box, fill=(0, 0, 0))  # ignore edited area
mean = ImageStat.Stat(diff).mean
print("mean change outside the box (0-255) R,G,B:",
      [round(v, 2) for v in mean])
print("changed pixels bbox:", diff.getbbox())

How do I read the output?

The table is a rule of thumb. The numbers depend on the output size, the resize filter and the image, so calibrate on your own samples.

Reading the outside-the-box difference (rule of thumb, read 2026-10-02)
Mean changeLikely meaningAction
Close to 0The rest heldShip, after a visual check
Small but not zeroResize, compression or tiny tone shiftCompare the two on screen
Large in a bandThe edit spread past the boxTighten the prompt or add a mask_url
Large everywhereThe model re-rendered the sceneRestate must-not-move and retry

What are the limits of this check?

If the model changed the output's shape, the resize hides a crop, so request aspect_ratio: "auto" on edits, as the Image API docs advise. A pixel diff also cannot judge a face; use it with the identity constraint in the same-face prompt block and your own eyes. Sume does not run this comparison for you. A failed generation is not billed, but a completed one with a leaky edit is, so measure before you pay for a second pass.

How do I pick the box?

Draw it a little larger than the object you changed, because a soft edit blends past the outline. If you also send a mask_url, make the box cover the same area as the mask. Keep a small log of the measured value per image; a rising trend across a batch is a sign that your prompt is leaving too much room for the model.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume