Adding a Favicon

After more than 15 years of running this blog it is time to add a favicon. Of course I could start Gimp and create one or I could even use some of the Webeditors out there, but I want to do this in Python. It doesn't have to be beautiful. My usecase here is: I want to find my blog in all the open Browser tabs I have.

I decided on using Pillow in a Jupyter Notebook to generate a background color gradient and the letter M.

The code I used for the gradient:

from PIL import Image

def gradient_image(col1: str, col2: str, width: int, angle: int) -> Image:
    base_image = Image.new("RGB", (width, width), col1)
    top_image = Image.new("RGB", (width, width), col2)
    mask = Image.new("L", (width * 2, width * 2))

    # generate a mask to blend the top image over the base image
    data = []
    for y in range(width * 2):
        data.extend(width * [int(90 * (y / width))])

    mask.putdata(data)
    # rotate mask to get a rotated gradient and crop to image size
    mask = mask.rotate(angle).crop((0, 0, width, width))
    base_image.paste(top_image, (0, 0), mask)
    return base_image

This generates two images with col1 and col2 and generates a mask with transparency gradients. Then it rotates the mask (only angles between 0 and 90 are allowed) and applies the mask with the top image on top of the base image. The gradient for the angles 0 to 90 in 10 degree steps look like this:

img1

And the code to add the "M" on top:

from PIL import Image, ImageFont, ImageDraw

# image with blue/yellow gradient
im = gradient_image("lightblue", "yellow", 32, 42)
# the font
font = ImageFont.truetype("/usr/share/fonts/gnu-free/FreeMono.otf", 40)
# add black non transparent M to image
draw = ImageDraw.Draw(im)
draw.text((4, -4), "M", font=font, fill=(0, 0, 0, 255))
# save as icon
im.save("favicon.ico")

The resulting Icon:

img2

is good enough for my usecase. :)