Skip to content

Commit

Permalink
visual art: Add a script for user identicons.
Browse files Browse the repository at this point in the history
  • Loading branch information
Privisus authored and tommyip committed Dec 24, 2017
1 parent 23b7b18 commit 002d65a
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 0 deletions.
Binary file added generate-avatars/Privisus/Alice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added generate-avatars/Privisus/Bob.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added generate-avatars/Privisus/Marry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added generate-avatars/Privisus/Privisus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions generate-avatars/Privisus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Approach

I decided it would be a good idea to approach this problem
mathematically. Boy I was in for a journey.

Then I thought about "periodic" things in math, I figured that a sine, cosine, and tangent would be fine to work with.

I also used PyPNG because it is small and relatively trivial to use and
understand.

(Note: PyPNG can be obtained via `curl -LO https://raw.github.com/drj11/pypng/master/code/png.py`)

# Process

I tried to experiment a little bit in Demos to see if it has a potential.
Something like this showed up:

![Desmos plot 1](https://lambda.sx/T2V.png "Desmos plot, first three enabled")

![Desmos plot 2](https://lambda.sx/KS3.png "Desmos plot, last three enabled")

Okay, looks promising, so I applied them into the program with few tweaks
here and there.

# Results

Results can be checked with the following command:

`avatar-1.png`: `python generate-identicons.py Alice`
`avatar-2.png`: `python generate-identicons.py Bob`
`avatar-3.png`: `python generate-identicons.py Marry`
`avatar-4.png`: `python generate-identicons.py Zulip`
`avatar-5.png`: `python generate-identicons.py Privisus
[email protected]`

Binary file added generate-avatars/Privisus/Zulip.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
140 changes: 140 additions & 0 deletions generate-avatars/Privisus/generate-identicons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
'''Generates a unique 50px * 50px .png file from user name
Usage: generate-identicons.py username <useremail>
Keyword arguments:
username -- User's username in string
useremail (optional) -- User's email
Returns: void
'''

import sys
import hashlib
import png
from math import sin, cos, tan

#Return the sum of the list with this pattern: + * - //
def unique_sum(val_list):
sum = 0
for k, ascii_value in enumerate(val_list):
if k % 4 == 0:
sum += ascii_value
elif k % 4 == 1:
sum *= ascii_value
elif k % 4 == 2:
sum -= ascii_value
elif k % 4 == 3:
sum //= ascii_value

return sum

#create sha-1 instance
sha1 = hashlib.sha1()

#create encoded, utf-8 string from the second argument passed by the user
username_encoded = sys.argv[1].encode('utf-8')

#check if the user supplied more than or equal to three arguments
if len(sys.argv) >= 3:
#if it does, set the encoded user-email
useremail_encoded = sys.argv[2].encode('utf-8')
else:
#if not, use the default encoded user-email
useremail_encoded = "DEFAULT".encode('utf-8')

#create sha-1 of username
sha1.update(username_encoded)
username_sha1 = sha1.hexdigest()

#create sha-1 of useremail
sha1.update(useremail_encoded) #dependent on the username
useremail_sha1 = sha1.hexdigest()

#convert each character in each string to ASCII value,
#and summing it with this pattern: + * - //

username_val_list = [ord(character) for character in username_sha1]
useremail_val_list = [ord(character) for character in useremail_sha1]

username_sum = unique_sum(username_val_list)
useremail_sum = unique_sum(useremail_val_list)

#figure out the trig values for the half of the icon
if useremail_sum % 3 == 0:
trig_values = [sin((useremail_sum**2+1)*x+useremail_sum) for x in range(0,2500//4)]
elif useremail_sum % 3 == 1:
trig_values = [cos((useremail_sum**2+1)*x+useremail_sum) for x in range(0,2500//4)]
elif useremail_sum % 3 == 2:
trig_values = [tan((useremail_sum**2+1)*x+useremail_sum) for x in range(0,2500//4)]

grid_locations = []

#This can be simplified with list comprehension, but I decided to left it this way for readability
for trig_value in trig_values:
q1 = round(255 * sin(username_sum * (useremail_sum * trig_value)))
q2 = round(255 * sin(useremail_sum))

if q1 == 0:
q1 = 1

if q2 == 0:
q2 = 1

k = round(q1) % round(q2)

if k >= 25 and k < 100:
k = 100

if k >= 100 and k < 200:
k = 200

if k > 200:
k = 100

grid_locations.append(k)

#check if the list is generally dull, if it is, contrast it
if sum(grid_locations) < 25*25*100:
average_light = 255 * sum(grid_locations) // (25*25*100)

grid_fix_dull = []

for color in grid_locations:
if color < average_light:
grid_fix_dull.append(255-average_light)
else:
grid_fix_dull.append((color*2) % 256)

grid_locations = grid_fix_dull

if sum(grid_locations) < 25*25*100:
grid_locations = [255-color for color in grid_locations]

#split the list into chunk of 25 ints, which will be mirrored in the next steps
grid_squared = [grid_locations[x:x+25] for x in range(0, len(grid_locations),25)]

grid_rgb = []

color_decide = (username_sum+useremail_sum) % 3

for row in grid_squared:
rgb_row = []
for light in row:
if color_decide == 0:
rgb_row.extend([light, light//2, light//3])
elif color_decide == 1:
rgb_row.extend([light//2, light , light//3])
elif color_decide == 2:
rgb_row.extend([light//2, light//3, light])
grid_rgb.append(rgb_row)

#for each list, add a mirror list so it is symetrical with the respect to y axis
grid_rgb = [grid+grid[::-1] for grid in grid_rgb]

#for each list, add a mirror list so it is symetrical with the respect to x axis
grid_rgb = grid_rgb + grid_rgb[::-1]

#put the image and save it
png.from_array(grid_rgb, 'RGB').save(sys.argv[1] + ".png")

0 comments on commit 002d65a

Please sign in to comment.