Skip to main content
Lesson 4 of 12 · Image Generation via API: GPT Image

Control quality, style, and resolution

Lesson 4 of 12 Updated November 2, 2026 Developer
On this page
  1. Control quality, style, and resolution
  2. Quality levels
  3. Available resolutions
  4. Control style through your prompt
  5. Utility function for generation
  6. Choose the right combination

Updated November 2, 2026 — Image models. gpt-image-1, the model this course was originally written for, was deprecated on October 23, 2026. Additionally, gpt-image-1.5, gpt-image-1-mini, and chatgpt-image-latest will be retired on December 1, 2026. Examples now use gpt-image-2.5-sunburst, which offers the highest precision for editing; gpt-image-2.5-flare is faster for standard generation. Both models now support xhigh and max quality levels. GPT Image models always return images in base64 format: the response_format parameter used by older DALL·E models is no longer accepted and has been removed from the code. Source: Image generation (OpenAI).

Control quality, style, and resolution

GPT Image provides several levers to adjust your output, but they don’t all work the same way. Quality and resolution are explicit API parameters that affect cost and generation time. Style, however, is controlled entirely through your prompt. Understanding this distinction prevents you from hunting for non-existent options and helps you optimize the quality-to-cost ratio for every generation.

Quality levels

The quality parameter directly impacts detail level and generation time. The best way to see the difference is to test it on a demanding subject—like a still life with Rembrandt lighting, where gradients and textures are critical—rather than on a flat graphic where differences would be invisible.

import base64
from openai import OpenAI

client = OpenAI()

qualities = ["low", "medium", "high"]

for q in qualities:
    response = client.images.generate(
        model="gpt-image-2.5-sunburst",
        prompt="Still life with exotic fruits on a marble table, Rembrandt lighting",
        size="1024x1024",
        quality=q
    )
    with open(f"quality_{q}.png", "wb") as f:
        f.write(base64.b64decode(response.data[0].b64_json))
    print(f"Quality {q}: quality_{q}.png")
QualityDetailsTimeCostRecommended Use
lowBasicFastEconomicalDrafts, tests, prototyping
mediumGoodModerateIntermediateSocial media, presentations
highMaximumSlowerPremiumPrint, advertising, portfolios

Available resolutions

Three aspect ratios are available, each tailored to specific use cases: square 1024×1024 for social media and avatars, portrait 1024×1536 for stories, posters, and mobile screens, and landscape 1536×1024 for banners, headers, and presentations. Always generate directly in your target format. Cropping afterward wastes pixels you’ve paid for and disrupts the composition the model built for that specific frame.

import base64
from openai import OpenAI

client = OpenAI()

resolutions = {
    "1024x1024": "Square — ideal for social media and avatars",
    "1024x1536": "Portrait — stories, posters, mobile",
    "1536x1024": "Landscape — banners, headers, presentations",
}

for size, description in resolutions.items():
    response = client.images.generate(
        model="gpt-image-2.5-sunburst",
        prompt="Panoramic view of a futuristic city at dusk, neon lights and skyscrapers",
        size=size,
        quality="medium"
    )
    with open(f"city_{size}.png", "wb") as f:
        f.write(base64.b64decode(response.data[0].b64_json))
    print(f"{size} ({description}) → city_{size}.png")

Control style through your prompt

Style isn’t an explicit API parameter; you control it entirely through your prompt. The most reliable technique is to specify a precise medium with its own vocabulary. “Professional photography, Nikon D850, f/2.8” doesn’t just request a photo—it demands specific depth of field and optical rendering. “Retro 16-bit pixel art, limited palette” imposes a resolution constraint the model will respect. The loop below applies five different mediums to the same subject, making the differences immediately visible.

import base64
mediums = [
    "professional photography, Nikon D850, f/2.8",
    "oil painting on canvas, impressionist style",
    "flat design vector illustration, pastel colors",
    "architectural technical drawing, cross-section view",
    "retro 16-bit pixel art, limited palette",
]

for medium in mediums:
    prompt = f"A typical Parisian café with outdoor seating, {medium}"
    response = client.images.generate(
        model="gpt-image-2.5-sunburst",
        prompt=prompt,
        size="1024x1024",
        quality="medium"
    )
    filename = f"cafe_{mediums.index(medium) + 1}.png"
    with open(filename, "wb") as f:
        f.write(base64.b64decode(response.data[0].b64_json))
    print(f"{medium[:40]}... → {filename}")

Lighting is your second lever, and often the most powerful: it can radically transform the same scene. A portrait of a ceramic artisan in her workshop becomes a sober documentary shot under three-point studio lighting, an advertising image in golden hour light, or a movie poster in Caravaggio-style chiaroscuro. The subject hasn’t changed a word; only the atmosphere has shifted.

import base64
lightings = [
    "three-point studio lighting, neutral white background",
    "natural golden hour light",
    "cyberpunk neon lighting, pink and blue",
    "dramatic Caravaggio-style chiaroscuro",
    "diffuse rainy day light, gray tones",
]

for lighting in lightings:
    prompt = f"Portrait of a ceramic artisan in her workshop, {lighting}"
    response = client.images.generate(
        model="gpt-image-2.5-sunburst",
        prompt=prompt,
        size="1024x1536",
        quality="high"
    )
    filename = f"artisan_{lightings.index(lighting) + 1}.png"
    with open(filename, "wb") as f:
        f.write(base64.b64decode(response.data[0].b64_json))
    print(f"Lighting: {lighting} → {filename}")

Utility function for generation

Repeating the same six lines for every call quickly becomes tedious and error-prone. Wrap your default preferences in a reusable function that also handles disk storage and file suffixing when you request multiple images.

from openai import OpenAI
import base64
from pathlib import Path

client = OpenAI()

def generate_image(
    prompt: str,
    output_path: str,
    size: str = "1024x1024",
    quality: str = "medium",
    n: int = 1
) -> list[str]:
    """
    Generates one or more images and saves them locally.
    Returns a list of created file paths.
    """
    response = client.images.generate(
        model="gpt-image-2.5-sunburst",
        prompt=prompt,
        n=n,
        size=size,
        quality=quality,
    )

    paths = []
    for i, image in enumerate(response.data):
        if n > 1:
            path = Path(output_path).stem + f"_{i+1}" + Path(output_path).suffix
        else:
            path = output_path

        data = base64.b64decode(image.b64_json)
        with open(path, "wb") as f:
            f.write(data)
        paths.append(path)
        print(f"Saved: {path}")

    return paths


# Usage
generate_image(
    prompt="Premium packaging for matcha tea, minimalist Japanese design",
    output_path="matcha_packaging.png",
    size="1024x1024",
    quality="high"
)

Choose the right combination

You decide both parameters together, based on your target medium. The table below summarizes the most common scenarios.

ContextResolutionQuality
Rapid prototyping1024×1024low
Instagram / LinkedIn post1024×1024medium
Vertical story / Reel1024×1536medium
Web banner / header1536×1024medium
A3+ print poster1024×1536high
Creative portfolio / book1024×1024high
Batch prompt testing1024×1024low

In production, don’t manually copy this table into every script. Translate it into configuration logic and let your code choose based on the declared context. You get a single source of truth, and if you later decide your social posts should use high quality, one line change is all it takes.

def generate_for_context(prompt: str, context: str, output: str):
    """Automatically adapts quality and resolution to the context."""
    configs = {
        "prototype": {"size": "1024x1024", "quality": "low"},
        "social_media": {"size": "1024x1024", "quality": "medium"},
        "story": {"size": "1024x1536", "quality": "medium"},
        "banner": {"size": "1536x1024", "quality": "medium"},
        "print": {"size": "1024x1536", "quality": "high"},
    }

    config = configs.get(context, configs["social_media"])

    return generate_image(
        prompt=prompt,
        output_path=output,
        **config
    )


# Generate the same image for different media
generate_for_context(
    "Corsen AI logo on dark background, premium tech style",
    "social_media",
    "logo_social.png"
)

To build your own judgment on these settings, generate the full matrix yourself: write a script that takes a single prompt and produces all nine quality × resolution combinations, saves each file with an explicit name like image_low_1024x1024.png, and displays a summary table. You’ll soon know by eye when medium is enough.