Imagen 4 Fast has no 4:5: generate 3:4 and crop to 1080x1350 in Pillow

Imagen 4 Fast and Grok skip 4:5 on Sume. Request 3:4, then crop to 1080x1350 with ImageOps.fit and a top-biased centering so heads and product tops survive.

5 min readSume
All posts

Request aspect_ratio: "3:4" from Imagen 4 Fast, then crop the result to 1080x1350 with ImageOps.fit and centering=(0.5, 0.0). 3:4 is 0.75 wide-to-tall and 4:5 is 0.8, so the crop removes about 6 percent of the height, and the top bias takes that sliver from the bottom edge where it usually costs the least.

Why this comes up

Sume's image catalog lists the native aspect ratios of each model rather than a collapsed subset. The Imagen entries are 1:1, 16:9, 9:16, 4:3, and 3:4. There is no 4:5, so request one of the listed ratios. Nano Banana 2 and Seedream do list 4:5, so for those you can ask for the ratio directly.

Imagen 4 Fast is one of the cheaper models: $0.02 list, so $0.025 billed per image. If the cost matters and the ratio does not exist, a small crop is the practical answer.

The crop

ImageOps.fit(image, size, method, bleed, centering) resizes and crops to the exact size. centering is a pair of fractions: (0.5, 0.5) crops evenly, and (0.5, 0.0) keeps the top edge and removes everything from the bottom. Use Image.LANCZOS for the downscale.

import os, io, requests
from PIL import Image
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
def gen(**body):
    r = requests.post("https://api.sume.com/v1/images", json=body, headers=H, timeout=60)
    r.raise_for_status()
    if r.status_code == 202:
        raise SystemExit("queued, read /v1/jobs/{id}/result: " + r.text)
    return r.json()
def fetch(u):
    return Image.open(io.BytesIO(requests.get(u, timeout=60).content))
from PIL import ImageOps
out = gen(model="google/imagen-4-fast", aspect_ratio="3:4",
          prompt="Portrait of a barista holding a latte, cafe window behind, warm light")
img = fetch(out["data"][0]["url"]).convert("RGB")
feed = ImageOps.fit(img, (1080, 1350), Image.LANCZOS, centering=(0.5, 0.0))
feed.save("feed_4x5.jpg", quality=92)
print(img.size, "->", feed.size, "cost", out["usage"]["cost"])

What gets cut

The numbers below follow from the ratios. A 3:4 source of 768 by 1024 pixels cropped to 4:5 keeps the full width and trims the height.

3:4 source to 4:5 crop, arithmetic read 2026-10-05
SourceTarget ratioKept widthKept heightRemoved
768x1024 (3:4)4:5 (0.8)76896064 px of height, 6.25 percent
1536x2048 (3:4)4:5 (0.8)15361920128 px of height, 6.25 percent

When to prefer another route

  • If the subject's feet or a caption sit at the bottom edge, use centering=(0.5, 0.5) or generate a looser prompt with air at the bottom.
  • If you need the exact ratio with no crop, pick a model that lists 4:5 and read the catalog with GET /v1/images/models.
  • A 6 percent crop is invisible on a portrait. A 1:1 to 4:5 crop removes 20 percent of the width and is not.

Related steps

The same crop-after-generation idea powers the 4:5 feed image recipe and the 9:16 story resize. To pick a model by its listed ratios in code, use the capability filter. Prompt for headroom above the subject, since the top-biased crop protects the top and spends the bottom.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume