Nano Banana exact pixels: target_pixels, then resize yourself

Nano Banana renders at a native ratio, not your pixels. Sume maps 1080x1350 to 4:5 and records target_pixels on the job; finish with a resize or crop.

5 min readSume
All posts

Can Nano Banana output an exact pixel size such as 1080x1350 through Sume? Not directly. Nano Banana renders at a native aspect ratio plus a resolution tier, so Sume maps your pixel string to the closest native ratio (4:5 for 1080x1350), generates at that ratio, and stores the size you asked for as target_pixels in the job's request metadata. The final resize is a documented post-step that the caller does.

The Image API docs say this for Nano Banana Pro: it sends aspect_ratio: "4:5" (native roughly 928x1152 at 1K), and exact 1080x1350 is a post-step via the job's target_pixels (Sume Image API docs). The same mapping applies to Nano Banana 2 on origin/main, which this post checked by running the request normalizer.

What the request becomes

Send the pixels in image_size (or in aspect_ratio) as a WIDTHxHEIGHT string, or as a {width, height} object. For Nano Banana 2, a 1080x1350 request is normalised to aspect_ratio: "4:5", and the metadata keeps target_pixels: {width: 1080, height: 1350}. Nothing is resized on Sume's side, which is why the output dimensions are the provider's, not yours.

Do not put the pixels in size: that field is a tier shorthand, and a value like 1024x1024 is rejected with 400 unsupported_parameter. The error text tells you to use a tier (512, 1K, 2K, 4K, 720p, 1080p) or to set image_size or aspect_ratio instead.

Pixel strings sent to google/nano-banana-2 and the ratio Sume maps them to, from the request normalizer on origin/main (read 2026-10-04)
Requested sizeNative ratio senttarget_pixels recorded
1080x13504:51080 x 1350
1080x19209:161080 x 1920
1200x62816:91200 x 628
1500x50021:91500 x 500

Finish the size in your pipeline

When the native ratio equals your target ratio (4:5 to 1080x1350, 9:16 to 1080x1920), a straight resize is enough. When it does not (1200x628 is about 1.91 and the native choice is 16:9, which is 1.78), resize to cover and centre-crop. The code below handles both cases with one function and needs Pillow (pip install pillow).

Choose the tier so the source is at least as large as the target on both edges. At 1K the native 4:5 frame is about 928x1152, so 1080x1350 would be an upscale; request resolution: "2K" when you need a downscale instead.

from PIL import Image, ImageOps

def fit_exact(path: str, width: int, height: int, out: str) -> tuple[int, int]:
    """Resize to cover the target box, then centre-crop to exactly width x height."""
    img = Image.open(path).convert("RGB")
    fitted = ImageOps.fit(img, (width, height), method=Image.LANCZOS, centering=(0.5, 0.5))
    fitted.save(out, "PNG")
    return fitted.size

if __name__ == "__main__":
    # demo with a synthetic 928x1152 frame, the native 4:5 size at 1K
    Image.new("RGB", (928, 1152), "#3a6ea5").save("native.png")
    print(fit_exact("native.png", 1080, 1350, "final.png"))

Where the pixels live

target_pixels is part of the job request metadata, so it is there when you read the job back through the standard job endpoints (Jobs and results). You can also keep the target in your own code, which is simpler: you already know what size you asked for.

For a story-sized example with a full walkthrough see 9:16 story image from Sume, then resize.

Related posts

More in Developers

All Developers posts

Written by Sume