Lazy-load placeholder for an AI image: average color from Sume

Compute the average color of a generated image with Pillow, use it as the background of the image box and avoid a white flash while the real file loads.

5 min readSume
All posts

To avoid a white flash while an AI image loads, compute its average color once when you receive it from Sume, store the hex next to the file and set it as the background-color of the image's box. Resizing the image to one pixel with Pillow's box filter gives the average color in two lines, and the box already has the right shape if you also store the width and height.

This is a cheap placeholder, not a blur-up. It costs a few bytes in your database, needs no extra request and works for any file the Sume Image API returns in data[].url.

What are the placeholder options?

Placeholder options compared, read 2026-10-04
OptionExtra bytesEffort
Average color7 (a hex string)Two lines of Pillow
Tiny blurred thumbnailA few hundredA resize, an encode and an inline data URL
Hash-based blur placeholderAbout 30A library on both ends
None0A flash or layout jump

What is the code?

It downloads the result, prints the hex, width and height and shows the HTML to use.

import io, sys, requests
from PIL import Image

def placeholder(url):
    data = requests.get(url, timeout=60).content
    img = Image.open(io.BytesIO(data)).convert("RGB")
    r, g, b = img.resize((1, 1), Image.BOX).getpixel((0, 0))
    return f"#{r:02x}{g:02x}{b:02x}", img.size

if __name__ == "__main__":
    color, (w, h) = placeholder(sys.argv[1])
    print(
        f'<img src="hero.webp" width="{w}" height="{h}" loading="lazy" '
        f'style="background-color:{color}" alt="">'
    )

Where do I store the color?

Keep it in the same record as the file path, dimensions and the model id that produced the image. Compute it at ingest, not at render time, so the page does no work. Pair it with the width set from the srcset post so the box is the right size before the file arrives.

Does a flat color look bad on busy images?

For a photo with a bright sky and dark ground, the average is a muddy middle tone. If that bothers you, crop to the top strip or split the image into a two-stop linear-gradient from the top and bottom row averages. The extra complexity is small and the result is closer to the final image.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume