-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathidenticon_generator.py
90 lines (74 loc) · 2.62 KB
/
identicon_generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# /usr/bin/python3
#
# Identicon Generator - Generate Github-like, horizontally symmetric Identicons.
# Written by davidhcefx, 2019.4.11
from math import ceil
import hashlib
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.colors as mcolors
from matplotlib.collections import PatchCollection
def generate(idcode: str, size: int) -> tuple:
"""
@param size Output table size, 5 ~ 20
@return Table and its color
"""
h = hashlib.sha512(idcode.encode('utf8')).hexdigest() + \
hashlib.sha512((idcode + 'SEED:3.1416').encode('utf8')).hexdigest()
hashbin = '{:0>1024}'.format(bin(int(h, 16))[2:])
table = [[0] * size for i in range(size)]
# The Encodings:
# bit 0-7 => hue
# bit 8-15 => sat
# bit 16-23 => val (bright)
# every 3rd bit => dots starting from upper-left to lower-right
idx = 24
for i in range(size):
for j in range(ceil(size / 2)):
table[i][j] = table[i][size-1 - j] = int(hashbin[idx])
idx += 3
# The following ranges were decided empirically so that the color looks best:
# hue: 0 ~ 1
# sat: 45 ~ 100
# val: 45 ~ 80, depending on sat
# vrange: 25 -> 30(sat=60) -> 15
# vbase: 45 -> 50(sat=70) -> 60(sat=85) -> 65
hue = int(hashbin[0:8], 2) / 256
sat = int(hashbin[8:16], 2) / 256 * 55 + 45
if sat < 60:
vrange = (sat - 45) / 15 * 5 + 25
else:
vrange = (100 - sat) / 40 * 15 + 15
if sat < 70:
vbase = (sat - 45) / 25 * 5 + 45
elif sat > 85:
vbase = (sat - 85) / 15 * 5 + 60
else:
vbase = (sat - 70) / 15 * 10 + 50
val = int(hashbin[16:24], 2) / 256 * vrange + vbase
color = mcolors.hsv_to_rgb((hue, sat / 100, val / 100))
return table, color
if __name__ == '__main__':
s = input('Icon size: [5-20, default=5] ')
size = int(s) if s != '' else 5
if size not in range(5, 21):
size = 5
table, color = generate(input('ID code: '), size)
# draw Identicon
patches = []
colors = []
for i in range(size):
for j in range(size):
print(' O ' if table[i][j] == 1 else ' ', end='')
patches.append(mpatches.Rectangle((j, size - i - 1), 1, 1))
colors.append(color if table[i][j] == 1 else (1, 1, 1))
print('')
print('(R,G,B) = (%.2f, %.2f, %.2f)' % tuple(color))
fig, ax = plt.subplots()
collection = PatchCollection(patches, cmap=plt.cm.hsv)
collection.set_facecolor(colors)
ax.add_collection(collection)
plt.axis('equal')
plt.axis('off')
plt.tight_layout()
plt.show()