Last active
July 9, 2021 07:51
-
-
Save Syncrossus/51e259d1adcf99b4f68737a602efeae6 to your computer and use it in GitHub Desktop.
A simple identicon creation utility module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" This module contains a simple identicon creation utility function. | |
Original color palette : coolors.co/659bd8-ff776d-ffd793-9eefae-c99dba | |
""" | |
import hashlib | |
import random | |
import png # requires pypng (version 0.0.19 recommended) | |
import sys | |
palette = {0: (255, 255, 255), | |
1: (101, 155, 216), | |
2: (255, 119, 109), | |
3: (255, 215, 147), | |
4: (158, 239, 174), | |
5: (201, 157, 186)} | |
def create_identicon(username, filename, avatar_size=5, img_size_per_cell=100): | |
""" Creates and writes an identicon to disk | |
Arguments: | |
- (str) username: username for which the identicon should | |
be created (is used as seed) | |
- (str) filename: file to which the image should be written | |
- (int) avatar_size: avatars will be squares composed of smaller | |
squares of which there are `avatar_size` in | |
width and height | |
- (int) img_size_per_cell: number of pixels for the width and | |
height of each square in the avatar | |
""" | |
# hashing username to use as seed | |
username_hash = hashlib.md5(username.encode("utf-8")) | |
random.seed(username_hash.hexdigest()) | |
# selecting random color among the 5 defined colors | |
color = random.randint(1, 5) | |
# the avatar should be symmetrical so we create the left | |
# half of the avatar as a binary matrix. The 1s will be | |
# colored in and the 0s will be white | |
avatar_base_width = (avatar_size + 2) // 2 + avatar_size % 2 | |
# creating first blank row to give a little padding space | |
avatar_base = [[0 for _ in range(avatar_base_width)]] | |
# creating actual avatar | |
avatar_base += [[0] + # blank left column for padding | |
[random.randint(0, 1) | |
for _ in range(avatar_base_width - 1)] | |
for _ in range(avatar_size)] | |
# creating last blank row (padding space) | |
avatar_base += [[0 for _ in range(avatar_base_width)]] | |
# creating full-width binary version of avatar | |
avatar_bin = [[row[i] if i < avatar_base_width | |
else row[avatar_size + 1 - i] # copying symmetrically | |
for i in range(avatar_size + 2)] | |
for row in avatar_base] | |
# creating actual RGB avatar | |
# color is in [1;5]. If pixel is 0, color*pixel = 0 and palette[0] = white | |
# If pixel is 1, color*pixel = color and palette[color] = some color | |
avatar = [[palette[color * pixel] for pixel in row] for row in avatar_bin] | |
avatar = _resize_avatar(avatar, avatar_size, img_size_per_cell) | |
# Uncomment the following section if using pypng version >= 0.0.20 | |
# from itertools import chain | |
# avatar = [list(chain(*row)) for row in avatar] | |
png.from_array(avatar, 'RGB').save(filename) | |
def _resize_avatar(avatar, avatar_size, img_size_per_cell): | |
""" Resizes avatars in a nearest-neighbor fashion copying rows and columns | |
Arguments: | |
- (list<list<(int, int, int)>>) avatar: | |
the avatar to resize | |
- (int) avatar_size: avatars will be squares composed of smaller | |
squares of which there are `avatar_size` in | |
width and height | |
- (int) img_size_per_cell: number of pixels for the width and | |
height of each square in the avatar | |
""" | |
img_size = img_size_per_cell * (avatar_size + 2) | |
return [[avatar[i // img_size_per_cell][j // img_size_per_cell] | |
for j in range(img_size)] | |
for i in range(img_size)] | |
if __name__ == '__main__': | |
cmd_args = sys.argv[1:] | |
if len(cmd_args) == 3: | |
usr, avatar_size, fname = cmd_args[0], int(cmd_args[1]), cmd_args[2] | |
else: | |
usr = input('Username : ') | |
fname = input('Filename : ') | |
avatar_size = int(input('Avatar size : ')) | |
create_identicon(usr, fname, avatar_size) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code is released under the .