Nova Canvas maskPrompt: edit by naming the region, and the Sume way

Nova Canvas accepts a maskPrompt in place of a maskImage. Sume edits work from the prompt alone on most models. How to word the region and test the result.

4 min readSume
All posts

The fastest way to edit part of a photo is to skip drawing a mask. Amazon Nova Canvas lets you pass a maskPrompt, a text description of the area to change, instead of a maskImage. You can send one or the other, not both (Amazon docs, read 2026-10-06).

Sume has no maskPrompt, and does not need one

On Sume the prompt is the only text field, so the region goes into it. Models such as Ideogram 4.5 take the first reference as the image to edit, and an edit with no aspect_ratio keeps the source shape. For the two GPT Image 2.5 variants you can add mask_url when wording is not precise enough.

A wording that works for region edits

Name the object, say what replaces it, and say what stays. Treat the last part as part of the instruction, not an afterthought.

  • Name: "the left sleeve of the jacket", not "the sleeve".
  • Replace: "with the same fabric in navy".
  • Keep: "Do not change the face, hands, background or lighting."
  • One change per call. Chained edits are cheaper to debug than a long list.

Test the wording

Run the same prompt on two models and count changed pixels against the source. The loop below prints a coarse score and the billed cost per model.

import io, os, requests
import numpy as np
from PIL import Image

SRC = "https://example.com/jacket.jpg"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
src = Image.open(io.BytesIO(requests.get(SRC).content)).convert("RGB")
for model in ["ideogram/ideogram-v4.5", "google/nano-banana-2"]:
    r = requests.post("https://api.sume.com/v1/images", headers=H, timeout=90, json={
        "model": model,
        "prompt": "Make the left sleeve navy. Do not change anything else.",
        "input_references": [{"type": "image_url", "image_url": {"url": SRC}}]})
    if r.status_code != 200:
        print(model, r.status_code); continue
    out = Image.open(io.BytesIO(requests.get(r.json()["data"][0]["url"]).content)).convert("RGB")
    if out.size != src.size:
        out = out.resize(src.size)
    d = np.abs(np.asarray(out, float) - np.asarray(src, float)).mean()
    print(model, round(d, 2), r.json()["usage"]["cost"])

Sources

Related posts

More in Comparisons

All Comparisons posts

Written by Sume