Generating background colours

Choosing the right colours can often make all the difference when adding finishing touches to a visualization. Finding colours that work together can be difficult, even more so when we need to find colours for hundreds of elements. So let's see how we can generate some colours with code!

Generating background colours

Check out this featured highlight and read on to learn more!

Colour makes everything better.

Choosing the right colours can often make all the difference when adding finishing touches to a visualization. Finding colours that work together can be difficult, even more so when we need to find colours for hundreds of elements.

The common solution is to generate the colours randomly or use some existing colour palette. However, we may aim for colours that match their corresponding elements, ultimately leading to a more cohesive design.

So let's see how we can generate some colours with code! There are many ways to generate colours, but we'll be looking at how to extract the dominant colour from an image.

We'll consider one of my earlier Pokémon-themed visualizations made with PlotAPI.

In this visualization, I needed colours for bars that represent each of the 800+ Pokémon. Let's see how I did it, and go a little further by trying some gradients too.

Downloading the images

I've mirrored the images with the following pattern.

https://datacrayon.com/images/data-is-beautiful/pokemon_thumbs/{pokedex_id}.png

So we can substitute in a Pokédex ID of 025 to get an image of Pikachu.

All the images are of the PNG file format and have transparent backgrounds, so there's plenty of space available to fill with a nice background colour.

We're going to need to retrieve these images if we want to operate on them. We'll use the urllib package for this.

import urllib.request

image_root = "https://datacrayon.com/images/data-is-beautiful/pokemon_thumbs/"

urllib.request.urlretrieve(f"{image_root}025.png", "img_025.png");

Great! We now have Pikachu's image saved locally with the filename img_025.png.

Extracting the dominant colour

We're going to use the Python implementation of the helpful color-thief package. You can install with the following.

pip install colorthief

Let's use it to extract the dominant colour from the image of Pikachu that we just saved locally.

from colorthief import ColorThief

color_thief = ColorThief('./img_025.png')
dominant_color = color_thief.get_color(quality=1)

print(dominant_color)
(222, 193, 115)

We now have the RGB for our dominant colour, but we may want to convert it to a hexadecimal colour string too.

hex_color = f"#{dominant_color[0]:02x}{dominant_color[1]:02x}{dominant_color[2]:02x}"

print(hex_color)
#dec173

You could do the same with hex_color = '#%02x%02x%02x' % dominant_color, but I prefer using f-strings in my own work.

Playing with colours

Let's use our newly extracted colour as a background for our image.

<div style="height:100px; width:100px; 
            background-color:#dec173;">
    <img style="height:100px; width:100px;" src="img_025.png">
</div>

It's looking great already, but let's try a few variations!

In this next one, let's specify an rgba colour so that we can change the opacity to 0.5.

<div style="height:100px; width:100px; 
            background-color:rgba(222, 193, 115, 0.5);">
    <img style="height:100px; width:100px;" src="img_025.png">
</div>

How about using CSS filters to darken the background colour?

<div style="height:100px; width:100px; position:relative;">
    <div style="position:absolute; height:100px; width:100px; 
                background-color:#dec173; filter:brightness(75%);"></div>
    <img style="position:absolute; height:100px; width:100px;"
         src="img_025.png">
</div>

Let's have one last play with filters!

Automating the process

Let's start automating the process. The first thing we'll do is define a function that expects a pokedex_id and returns the image and background as a HTML string.