Check a generated ad image against your brand hex color in Python

The Image API takes a prompt, not a color parameter. Measure each result against your brand hex with Pillow and flag drift before the image goes in an ad.

4 min readSume
All posts

Name the hex in the prompt, then measure the result: the Image API lists no color or palette parameter, so a brand color reaches the model only as words, and you verify it afterwards. Pillow can pull the five most common colors from an image and report how far the closest one sits from your brand hex.

The distance is a screening number, not a color-science verdict. Lighting, shadows and compression all shift pixels, so set a loose threshold and look at what gets flagged.

Why measure instead of eyeballing?

A batch of 40 images hides drift. One slightly teal blue in a set that should be navy is easy to miss in a grid and obvious in a number. Measuring also gives you a record you can attach to the job id.

What does the check do?

It shrinks the image, reduces it to five colors with median cut, sorts by pixel count and returns the Euclidean distance in RGB from your brand color to the nearest of them.

from PIL import Image

def top_colors(path, k=5):
    im = Image.open(path).convert("RGB")
    im.thumbnail((200, 200))
    q = im.quantize(colors=k, method=Image.Quantize.MEDIANCUT)
    pal = q.getpalette()
    found = sorted(q.getcolors(), reverse=True)
    return [tuple(pal[i * 3:i * 3 + 3]) for _, i in found]

def hex_to_rgb(h):
    h = h.lstrip("#")
    return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))

def drift(path, brand_hex):
    brand = hex_to_rgb(brand_hex)
    return min(
        sum((a - b) ** 2 for a, b in zip(c, brand)) ** 0.5
        for c in top_colors(path)
    )

# Demo with a generated test file; swap in a downloaded ad image.
Image.new("RGB", (64, 64), (30, 80, 170)).save("demo.png")
print(round(drift("demo.png", "#1F4EA8"), 1))

What threshold should I use?

Start near 40 on the 0 to 441 RGB scale, then adjust by looking at ten known good and ten known bad images from your own batches. If your brand color is small, such as a button, crop that region first; the whole-image palette will not see it.

What do I do with a flagged image?

Edit it with a reference image and a prompt that names the color again, or regenerate. If the exact brand color matters on a logo or button, add that element in code afterwards, the way the headline post does, instead of trusting a model to match it.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume