In this article, I will show and tell you how to generate avatars as on Github.
First, you need to understand how the github avatar works. At first glance, it’s just a random set of colored squares (hereinafter referred to as blocks) in a good order on a gray background.
Each avatar has 12 by 12 blocks.
Looking at the following picture, I think you understand that the images are symmetrical, so we will generate a matrix of blocks 6 by 12, and then reflect and concatenate two matrices, we get a matrix of 12 by 12.
Well, it looks like it’s time to code. I’ll be doing this in python.
from PIL import ImageDraw, Image import numpy as np import hashlib
background_color = '#f2f1f2' s = 'test1'
We get a set of pseudo-random bytes. I will use the hash function to get images from a specific string, so the result will be more interesting.
bytes = hashlib.md5(s.encode('utf-8')).digest()
Getting the color from the hash
main_color = bytes[:3] main_color = tuple(channel // 2 + 128 for channel in main_color) # rgb
The generated matrix filling the blocks, take the following bytes. Since the matrix is 6 by 12, and we have one bit of information for each block, we will need:
# матрица блоков 6 на 12 need_color = np.array([bit == '1' for byte in bytes[3:3+9] for bit in bin(byte)[2:].zfill(8)]).reshape(6, 12) # получаем матрицу 12 на 12 сконкатенировав оригинальную и отраженную матрицу need_color = np.concatenate((need_color, need_color[::-1]), axis=0)
Drawing images using the fill matrix
img_size = (avatar_size, avatar_size) block_size = avatar_size // 12 # размер квадрата img = Image.new('RGB', img_size, background_color) draw = ImageDraw.Draw(img) for x in range(avatar_size): for y in range(avatar_size): need_to_paint = need_color[x // block_size, y // block_size] if need_to_paint: draw.point((x, y), main_color)
Let’s display what happened
Hmmm, something’s not right. Oh, Yes, I forgot, the most extreme blocks are always not colored.
Fix this by adding a frame of empty blocks.
for i in range(12): need_color[0, i] = 0 need_color[11, i] = 0 need_color[i, 0] = 0 need_color[i, 11] = 0
Voila! Now let’s take a look at the generated avatars for other nicknames.
And finally, especially for Habr.
That’s all. Thanks to those who finished reading, and those who want to experiment, I send to my repository with all the code.