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.

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?
| Option | Extra bytes | Effort |
|---|---|---|
| Average color | 7 (a hex string) | Two lines of Pillow |
| Tiny blurred thumbnail | A few hundred | A resize, an encode and an inline data URL |
| Hash-based blur placeholder | About 30 | A library on both ends |
| None | 0 | A 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
- Prompt length limits across Firefly and Sume
Adobe Firefly now takes longer prompts for Image and Video on the web. Sume documents a 5000-character cap for music and no stated cap elsewhere.
- AI image prompt regression test: check size, ratio and alpha in CI
Before you swap or upgrade an image model, run a fixed prompt set through Sume and assert pixel size, aspect ratio and alpha with Pillow. Python test included.
- AI music longer or shorter than the video: prompt, loop, trim or join
A generated track rarely matches the video length. Four ways on Sume: put the length in the prompt, loop the soundtrack, set an in-point, or join takes.
- AI video API: seed and size return 400 on Sume; what to send instead
No Sume video model accepts seed, and size returns 400 unsupported_parameter. Use resolution and aspect_ratio, and keep the prompt and frames to redo a take.
Written by Sume