Skip to content

Instantly share code, notes, and snippets.

@snydergd
Created January 10, 2016 05:05
Show Gist options
  • Save snydergd/37d23e2270b9949da469 to your computer and use it in GitHub Desktop.
Save snydergd/37d23e2270b9949da469 to your computer and use it in GitHub Desktop.
python VizHash using PIL
#!/bin/env python2
"""
Visual hash (see [html5 implementation](https://github.com/sametmax/VizHash.js) and
[original creator's website](http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd))
reimplemented using a Python script with PIL.
"""
from PIL import Image,ImageDraw
import hashlib
import sys
import math
import argparse
# parameters
parser = argparse.ArgumentParser(description="Create a visual hash for a piece of text")
parser.add_argument('text', type=str, metavar='text', nargs=1, help="text to create hash of")
parser.add_argument('file', type=str, metavar='file', nargs=1, help="output filename")
parser.add_argument('-w', '--width', type=int, default=256, help="width of output image")
parser.add_argument('-H', '--height', type=int, default=256, help="height of output image")
args = parser.parse_args()
width = args.width
height = args.height
text = args.text[0]
outFilename = args.file[0]
# Create hash bytes from text
theHash = hashlib.sha1(text).hexdigest() + hashlib.md5(text).hexdigest()
theHash = theHash + theHash[::-1]
def toIntArray(x):
out = []
for i in range(0,len(x),2):
out.append(int(x[i:i+2], 16))
return out
theHash = toIntArray(theHash)
hashIndex = 0
# Function to get next int of the hash
def nextInt():
global hashIndex, theHash
n = theHash[hashIndex]
hashIndex = (hashIndex + 1)%len(theHash)
return n
# Create the image from the data
im = Image.new('RGB', (width,height))
draw = ImageDraw.Draw(im)
class color:
r = g = b = 0
def __init__(self, r,g,b):
self.r = r
self.g = g
self.b = b
def __str__(self):
return "rgb(%d,%d,%d)" % (self.r,self.g,self.b)
baseColor = color(nextInt(), nextInt(), nextInt())
# gradient
def drawTheGrad(c, vertical):
for x in range(width):
for y in range(height):
d = height if vertical else math.sqrt(width*width+height*height)
t = d-(y if vertical else math.sqrt(x*x+y*y))
draw.point((x,y), str(color(baseColor.r*t/d, baseColor.g*t/d, baseColor.b*t/d)))
drawTheGrad(baseColor, nextInt()%2 == 1)
# shapes
def getX():
return nextInt()*width/256
def getY():
return nextInt()*height/256
def rect(c):
points = [getX(), getY(), getX(), getY()]
draw.rectangle(points, fill=str(c))
def ellipse(c):
center = (getX(), getY())
dims = (getX(), getY())
points = (center[0]-dims[0]/2, center[1]-dims[1]/2, center[0]+dims[0]/2-1, center[1]+dims[1]/2-1)
draw.ellipse(points, fill=str(c))
def polygon(c):
points = (getX(), getY(), getX(), getY(), getX(), getY(), getX(), getY())
draw.polygon(points, fill=str(c))
def arc(c):
start = nextInt()*360/256
end = start+nextInt()*180/256
points = [getX(), getY(), getX(), getY()]
points[0] -= points[2]/2
points[1] -= points[2]/2
points[3] = points[1]+points[2]
points[2] = points[0]+points[2]
draw.chord(points, start, end, fill=str(c))
# draw shapes
shapeDeck = [rect,ellipse, ellipse, polygon, arc, arc, arc]
for i in range(8):
shape = nextInt()%7
baseColor = color((baseColor.r+nextInt()/25)%256,
(baseColor.g+nextInt()/25)%256,
(baseColor.b+nextInt()/25)%256)
shapeDeck[shape](baseColor)
baseColor = color(nextInt(), nextInt(), nextInt())
shapeDeck[nextInt()%7](baseColor)
# output image
im.save(outFilename, "png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment