1080x1350 sent as aspect_ratio: what Ideogram, Grok, Imagen get
Send pixels instead of a ratio and Sume snaps to the nearest native ratio. Tested table for 1080x1350, 1200x628 and 1500x500 across four model families.
What happens if you send aspect_ratio: "1080x1350" to an image model that only accepts ratios? On Sume the pixels are snapped to the nearest ratio the model lists, and the result is not always the one you wanted: the same 1080x1350 becomes 4:5 on Ideogram and Nano Banana 2, but 2:3 on Grok and 1:1 on Imagen 4 Fast, because 4:5 is not in the Grok or Imagen catalogs.
That is a sensible fallback rather than an error, but it means a social-media size can quietly change shape when you swap models. The table below shows what each family returns for four common sizes. The values come from running the request normalizer and the snapping function on origin/main, so they describe current behaviour; the catalogs can change, so re-check with GET /v1/images/models before you rely on them.
What each row snaps to
Rows that take only ratios (Ideogram, Grok, Imagen) snap an exact-pixel string in aspect_ratio or image_size to the closest native ratio. Nano Banana 2 does the same mapping but also records the pixels you asked for, which is covered in the Nano Banana exact-pixels post. The sizes below are an Instagram portrait, a link-card image, a vertical story and an ultrawide strip.
The ultrawide row shows the limit of the approach: a 3:1 strip is native on Ideogram, only roughly approximated by 20:9 on Grok, and mapped to 16:9 on Imagen.
| Requested size | Ideogram 4.5 | Grok Imagine Image | Imagen 4 Fast | Nano Banana 2 |
|---|---|---|---|---|
| 1080x1350 | 4:5 | 2:3 | 1:1 | 4:5 |
| 1200x628 | 2:1 | 2:1 | 16:9 | 16:9 |
| 1080x1920 | 9:16 | 9:16 | 9:16 | 9:16 |
| 1500x500 | 3:1 | 20:9 | 16:9 | 21:9 |
Why 4:5 never becomes 4:3
A common worry is that an Instagram portrait could be mistaken for a 4:3 landscape. It cannot: Sume picks the closest native ratio, so 1080x1350 (0.8) lands on 4:5 where that exists and on the nearest tall ratio where it does not. The Image API docs also state it plainly: 4:5 is the Instagram portrait, not 4:3 (Sume Image API docs).
Where there is no 4:5, you get a different tall shape, and you finish the job in your own pipeline. If an exact pixel box matters, generate at the closest ratio and crop or resize after.
Guard against a silent reshape
If a size must come out in a particular shape, check the returned image rather than trusting the request. The script below sends the pixel size, then compares the ratio of the image you got to the ratio you asked for and warns when they differ by more than two percent. It uses only the standard library plus requests, and reads the dimensions from the PNG header so it needs no imaging package.
It assumes the default PNG output. For output_format values other than PNG, read the size with your imaging library of choice instead.
import os, struct, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
want_w, want_h = 1080, 1350
r = requests.post("https://api.sume.com/v1/images", headers=H, timeout=120, json={
"model": "x-ai/grok-image",
"prompt": "a ceramic mug on a pale blue table, soft window light",
"aspect_ratio": f"{want_w}x{want_h}"})
r.raise_for_status()
if r.status_code == 202:
raise SystemExit("queued: poll the job status_url instead")
url = r.json()["data"][0]["url"]
png = requests.get(url, timeout=60).content
w, h = struct.unpack(">II", png[16:24])
got, want = w / h, want_w / want_h
print(f"asked {want_w}x{want_h} ({want:.3f}), got {w}x{h} ({got:.3f})")
if abs(got - want) / want > 0.02:
print("shape changed: crop or resize in your own pipeline")Related posts
More in Developers
- Pre-flight tool access: tools_list on Sume's MCP
Notion added a tool that reveals connection-scoped capabilities before requests. Sume's MCP does the same job with tools_list, tools_schema and mcp_health.
- Push or poll for a finished render: listen, webhook or jobs_wait
MCP 2026-07-28 adds subscriptions/listen. For a render that takes minutes, compare a listen stream, a signed webhook and jobs_wait, with a Python verifier.
- Pydantic AI slot leak vs Sume queue_full: tell them apart
Pydantic AI v2.53.0 fixed a streamed-request concurrency slot leak. A client limiter is not Sume's workspace queue_full 429, and each needs its own handling.
- Pydantic AI Workspace sandboxes: fetch Sume artifacts
Pydantic AI's Workspace abstraction runs tools locally or in sandboxes. Inside a sandbox, fetch Sume artifact URLs, and give Sume inputs as public HTTPS URLs.
Written by Sume