Browse Source

Initial commit

master
Johann Schmitz 1 year ago
parent
commit
c223002836
Signed by: Johann Schmitz <johann@j-schmitz.net> GPG Key ID: A084064277C501ED
3 changed files with 295 additions and 0 deletions
  1. 227
    0
      pydenticon5/__init__.py
  2. 1
    0
      requirements.txt
  3. 67
    0
      test.py

+ 227
- 0
pydenticon5/__init__.py View File

@@ -0,0 +1,227 @@
# -*- coding: utf-8 -*-
import math

from PIL import Image, ImageDraw


class Pydenticon5(object):

def _get_sprite(self, shape, size):

if shape == 0: # triangle
coords = [ (0.5, 1), (1, 0), (1, 1) ]
elif shape == 1: # parallelogram
coords = [ (0.5, 0), (1, 0), (0.5, 1), (0, 1) ]
elif shape == 2: # mouse ears
coords = [ (0.5, 0), (1, 0), (1, 1), (0.5, 1), (1, 0.5) ]
elif shape == 3: # ribbon
coords = [ (0, 0.5), (0.5, 0), (1, 0.5), (0.5, 1), (0.5, 0.5)]
elif shape == 4: # sails
coords = [ (0, 0.5), (1, 0), (1, 1), (0, 1), (1, 0.5)]
elif shape == 5: # fins
coords = [ (1, 0), (1, 1), (0.5, 1), (1, 0.5), (0.5, 0.5)]
elif shape == 6: # beak
coords = [ (0, 0), (1, 0), (1, 0.5), (0, 0), (0.5, 1), (0, 1)]
elif shape == 7: # chevron
coords = [ (0, 0), (0.5, 0), (1, 0.5), (0.5, 1), (0, 1), (0.5, 0.5)]
elif shape == 8: # fish
coords = [ (0.5, 0), (0.5, 0.5), (1, 0.5), (1, 1), (0.5, 1), (0.5, 0.5), (0, 0.5)]
elif shape == 9: # kite
coords = [ (0, 0), (1, 0), (0.5, 0.5), (1, 0.5), (0.5, 1), (0.5, 0.5), (0, 1)]
elif shape == 10: # trough
coords = [ (0, 0.5), (0.5, 1), (1, 0.5), (0.5, 0), (1, 0), (1, 1), (0, 1)]
elif shape == 11: # rays
coords = [ (0.5, 0), (1, 0), (1, 1), (0.5, 1), (1, 0.75), (0.5, 0.5), (1, 0.25)]
elif shape == 12: # double rhombus
coords = [ (0, 0.5), (0.5, 0), (0.5, 0.5), (1, 0), (1, 0.5), (0.5, 1), (0.5, 0.5), (0, 1)]
elif shape == 13: # crown
coords = [ (0, 0), (1, 0), (1, 1), (0, 1), (1, 0.5), (0.5, 0.25), (0.5, 0.75), (0, 0.59), (0.5, 0.25)]
elif shape == 14: # radioactive
coords = [ (0, 0.5), (0.5, 0.5), (0.5, 0), (1, 0), (0.5, 0.5), (1, 0.5), (0.5, 1), (0.5, 0.5), (0, 1)]
else: # tiles
coords = [ (0, 0), (1, 0), (0.5, 0.5), (0.5, 0), (0, 0.5), (1, 0.5), (0.5, 1), (0.5, 0.5), (0, 1)]

# scale up

for i in range(len(coords)):
coords[i] = (coords[i][0] * size, coords[i][1] * size)

return coords

def draw_rotated_polygon(self, orig, box_size, sprite, x, y, shapeangle, angle, size, fillstyle):

print("Draw rotated polygon: sprite=%s, x=%s, y=%s, shapeangle=%s, angle=%s, size=%s, fillstyle=%s" % (sprite, x, y, shapeangle, angle, size, fillstyle))

poly_img = Image.new('RGBA', (box_size, box_size))

# ImageDraw.Draw(poly_img).polygon([
# (0, size),
# (size/2, 0),
# (size, size)
# ], fill=(255,255,255))
ImageDraw.Draw(poly_img).polygon(sprite, fill=fillstyle)
pillow_angle = (angle - 180) * -1
poly_img = poly_img.rotate(pillow_angle)
orig.paste(poly_img, (x, y))
#
# #img.rotate(angle * math.pi / 180, center=(x, y))
# if angle == 90:
# img = orig.rotate(angle * -1, center=(x, y)) # Pillow rotate is counter clockwise!
# img.show()
# else:
# img = orig
#
# draw = ImageDraw.Draw(img)
# draw.rectangle(
# [x, y, x+size, y+size], outline=(0,0,0)
# )
#
# #center = (x, y)
# #img.rotate(angle * math.pi / 180, center=center)
# #img.rotate(shapeangle, center=(size/2, size/2))
#
# # move sprite to the correct box
# translated_sprite = [
# (s[0] + x, s[1] + y) for s in sprite
# ]
# draw.polygon(translated_sprite, fill=fillstyle)
#
#
#
#
#
# # # var halfSize = size / 2;
# # half_size = size / 2
# #
# # # # ctx.translate(x, y);
# # # # ctx.rotate(angle * Math.PI / 180);
# # center = (x, y)
# # img.rotate(angle * math.pi / 180, center=center)
# # #
# # # # ctx.translate(halfSize, halfSize);
# # # # ctx.rotate(shapeangle);
# # center = (half_size, half_size)
# # img.rotate(shapeangle, center=center)
# # #
# # # # var tmpSprite = [];
# # # # for (var p = 0; p < sprite.length; p++) {
# # # # tmpSprite[p] = sprite[p] - halfSize;
# # # # }
# # # # fillPoly(ctx, tmpSprite);
# # tmpsprite = [(coords[0] + center[0] - half_size, coords[1] + center[1] - half_size) for coords in sprite]
# # draw.polygon(tmpsprite, fillstyle)
#
# # debug
#
# # img.rotate(shapeangle * -1, center=center)
# # img.rotate((angle * math.pi / 180) * -1, center=(x, y))
return orig


def get_center(self, shape, size):

if shape == 0: # empty
center = []
elif shape == 1: # fill
center = [0, 0, 1, 0, 1, 1, 0, 1]
elif shape == 2: # diamond
center = [ 0.5, 0, 1, 0.5, 0.5, 1, 0, 0.5]

elif shape == 3: # reverse diamond
center = [0, 0, 1, 0, 1, 1, 0, 1, 0, 0.5, 0.5, 1, 1, 0.5, 0.5, 0, 0, 0.5]

elif shape == 4: # cross
center = [ 0.25, 0, 0.75, 0, 0.5, 0.5, 1, 0.25, 1, 0.75, 0.5, 0.5, 0.75, 1, 0.25, 1, 0.5, 0.5, 0, 0.75, 0, 0.25, 0.5, 0.5]

elif shape == 5: # morning star
center = [ 0, 0, 0.5, 0.25, 1, 0, 0.75, 0.5, 1, 1, 0.5, 0.75, 0, 1, 0.25, 0.5]

elif shape == 6: # small square
center = [ 0.33, 0.33, 0.67, 0.33, 0.67, 0.67, 0.33, 0.67]

elif shape == 7: # checkerboard
center = [ 0, 0, 0.33, 0, 0.33, 0.33, 0.66, 0.33, 0.67, 0, 1, 0, 1, 0.33, 0.67, 0.33, 0.67, 0.67,
1, 0.67, 1, 1, 0.67, 1, 0.67, 0.67, 0.33, 0.67, 0.33, 1, 0, 1, 0, 0.67, 0.33, 0.67,
0.33, 0.33, 0, 0.33]
else: # tiles
center = [ 0, 0, 1, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1]

# apply ratios
for i in range(len(center)):
center[i] = center[i] * size

return center

def draw(self, hash, size, rotate):

img = Image.new('RGBA', (size, size))
#img = ImageDraw.Draw(i)

corner_sprite_shape = int(hash[0], 16)
side_sprite_shape = int(hash[1], 16)
center_sprite_shape = int(hash[2], 16) & 7

half_pi = math.pi / 2

corner_sprite_rotation = half_pi * (int(hash[3], 16) & 3)
side_sprite_rotation = half_pi * (int(hash[4], 16) & 3)
center_sprite_background = int(hash[5], 16) % 2

# corner sprite foreground color
cfr = int(hash[6:8], 16)
cfg = int(hash[8:10], 16)
cfb = int(hash[10:12], 16)

# side sprite foreground color
sfr = int(hash[12:14], 16)
sfg = int(hash[14:16], 16)
sfb = int(hash[16:18], 16)

# size of each sprite
block_size = int(size / 3)
# totalsize = size

# start with blank 3x3 identicon

# generate corner sprites
corner = self._get_sprite(corner_sprite_shape, block_size)
### ctx.fillStyle = "rgb(" + cfr + "," + cfg + "," + cfb + ")";

if not rotate:
corner_sprite_rotation = 0

fillstyle = (cfr, cfg, cfb)

img = self.draw_rotated_polygon(img, block_size, corner, 0, 0, corner_sprite_rotation, 0, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, corner, size - block_size, 0, corner_sprite_rotation, 90, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, corner, size - block_size, size - block_size, corner_sprite_rotation, 180, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, corner, 0, size - block_size, corner_sprite_rotation, 270, block_size, fillstyle)

# draw sides
if not rotate:
side_sprite_rotation = 0

side = self._get_sprite(side_sprite_shape, size)

fillstyle = (sfr, sfg, sfb)
img = self.draw_rotated_polygon(img, block_size, side, 0, block_size, side_sprite_rotation, 0, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, side, 2 * block_size, 0, side_sprite_rotation, 90, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, side, 3 * block_size, 2 * block_size, side_sprite_rotation, 180, block_size, fillstyle)
img = self.draw_rotated_polygon(img, block_size, side, block_size, 3 * block_size, side_sprite_rotation, 270, block_size, fillstyle)
#
# center = self.get_center(center_sprite_shape, size)
#
# # make sure there's enough contrast before we use background color of side sprite
#
# if center_sprite_background > 0 and (abs(cfr - sfr) > 127 or abs(cfg - sfg) > 127 or abs(cfb - sfb) > 127):
# fillstyle = (sfr, sfg, sfb)
# else:
# fillstyle = (cfr, cfg, cfb)
#
# if center:
# self.draw_rotated_polygon(img, center, size, size, 0, 0, size, fillstyle)
return img

+ 1
- 0
requirements.txt View File

@@ -0,0 +1 @@
Pillow

+ 67
- 0
test.py View File

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-

from pydenticon5 import Pydenticon5

p = Pydenticon5()
p.draw('071e3f61671e790fc492b583a01ae22b', 180, 0).show()
# 071e3f61671e790fc492b583a01ae22b
# abcde9c290d0fb1ca068ffaddf22cbd0
# 94d093eda664addd6e450d7e9881bcad
# d6a3104f846a8165d50b5b14af7f0313
# 211cd88046364c21c9b619d5e119eba9
# c45635f6c3cf0ae2cbade753980667ad
# e4d909c290d0fb1ca068ffaddf22cbd0
# fb469d7ef430b0baf0cab6c436e70375
# 098f6bcd4621d373cade4e832627b4f6
# 81d5381bc1bd1f795970a22b6f19b0c8
# a46ae8d094a190cf890a3d54df54b59c
# 589293d9e6e3ed1bc91fa2cc828f91d9
# 2048561fdd17e80531ba4e29f543ecfc
# f1902ee7999262719edf2b39a4747f85
# a5414c9d27243e857d54b1e2309bf58e
# 5a6309327e044f0ff51388ac879869db
# e45aaef667ac6ae08cf88785c4e901c0
# 25ab3b38f7afc116f18fa9821e44d561
# 2f6c2404198add983753e94fc24e752f
# dc57b55036e648390508e2f3277b9ab5
# 739c5b1cd5681e668f689aa66bcc254c
# 16c75dbf8dc6239f9d74b96299404446
# d90fe1178a183ec92bdb7a2ab2df06f0
# 24a1a3bc832644156b357026cbca787e
# d4528bfc85cbf1377e1c84c18a7c730e
# 9edf71b9ce29b59c2db12810f40a2870
# 9f6b918a4da1dd5a1ef888607aac440d
# 64c5857d6a56157c426074f3b6437917
# c9cb450e5ccb84806134dbf44e3d3366
# 9fc4f98751e9f7ad7114b46e6babd3d1
# f456eb93f6f55ab83146cfb6ce7acc9c
# 8b40a072809a51b5fbd0f47e95267a08
# 4c1d5466e3e0dca6adcf8d3379bd5c93
# 24f80fd406fa88765c631dc78a582230
# cca4a1658b11d3bbd905e6f6c4b100b3
# 808271918ac8d973447dbebe60cc6f77
# d49921a2878af306054e20e0c90dc010
# 9c35a101f93d2999970c06c00639471c
# b17f49b533397d68d33732e424d9a5e3
# 5145e1299684b7f092be73c0795a1509
# 378d397007693fc72ee20dcab7d04594
# 31020cc740e8d620b0178171fb175fe0
# 5f8e518fd288cf9e8492ed4ae9b0382c
# 9948abfedd979c0407ebae27db4b9e3d
# c63501f4aced22d23647445256a5b045
# b438911b33e9378fb71391a37f8a1d3c
# a7e528b4a79d120bfdd02ab80d2e638f
# 5e57d93e095d874ffaaeb6a80504fd0e
# af12d03e5b7c2e25ee23f823cd8322ca
# be0dc8187703a612fff7926aa58ab054
# 2f895d91dbd09991f669a9cb58615825
# bb08f8f7f2910029fe74c879873cfa87
# 57fe4602e139db1f53a53c64a780bb0d
# a18f3a67c46a52875b26c390b181ee66
# 2cfcfd96203ff2f17c4a7f4e69398e3d
# ef7bf4cbfb9104faad17cd9a91bc1ac8
# e1761b8fb966cb3480f6d1d851855a95
# d22e81efa901eea60d9e6fc884711360
# 4d0ee028589c4f6f7b52fde872fb6b2d
# dc469d10b57502a73cbc2efa53989feb
# fe533d35b1ef243c16d189548780869b

Loading…
Cancel
Save