Move additional logic into RH obj

This commit is contained in:
Robohash 2013-08-28 18:08:26 -04:00
parent 78759d8aa5
commit a1ca07ddf8
3 changed files with 80 additions and 35 deletions

1
__init__.py Normal file
View File

@ -0,0 +1 @@
from .robohash import Robohash

View File

@ -3,19 +3,24 @@ import os
import hashlib
import Image
class Robohash(object):
"""
Robohash is a quick way of generating unique avatars for a site.
The original use-case was to create somewhat memorable images to represent a RSA key.
"""
def __init__(self,string,hashcount=11):
def __init__(self,string,hashcount=11,ignoreext = True):
"""
Creates our Robohasher
Takes in the string to make a Robohash out of.
"""
# Optionally remove an images extension before hashing.
if ignoreext is True:
string = self._remove_exts(string)
string = string.encode('utf-8')
hash = hashlib.sha512()
hash.update(string)
self.hexdigest = hash.hexdigest()
@ -28,12 +33,32 @@ class Robohash(object):
self.iter = 4
self._create_hashes(hashcount)
self.resourcedir = os.path.dirname(__file__) + '/'
# Get the list of backgrounds and RobotSets
self.sets = self._listdirs('sets')
self.bgsets = self._listdirs('backgrounds')
self.sets = self._listdirs(self.resourcedir + 'sets')
self.bgsets = self._listdirs(self.resourcedir + 'backgrounds')
# Get the colors in set1
self.colors = self._listdirs('sets/set1')
self.colors = self._listdirs(self.resourcedir + 'sets/set1')
self.format = 'png'
def _remove_exts(self,string):
"""
Sets the string, to create the Robohash
"""
# If the user hasn't disabled it, we will detect image extensions, such as .png, .jpg, etc.
# We'll remove them from the string before hashing.
# This ensures that /Bear.png and /Bear.bmp will send back the same image, in different formats.
if string.lower().endswith(('.png','.gif','.jpg','.bmp','.jpeg','.ppm','.datauri')):
format = string[string.rfind('.') +1 :len(string)]
if format.lower() == 'jpg':
format = 'jpeg'
self.format = format
string = string[0:string.rfind('.')]
return string
def _create_hashes(self,count):
"""
@ -55,7 +80,6 @@ class Robohash(object):
Go through each subdirectory of `path`, and choose one file from each to use in our hash.
Continue to increase self.iter, so we use a different 'slot' of randomness each time.
"""
chosen_files = []
# Get a list of all subdirectories
@ -79,18 +103,44 @@ class Robohash(object):
return chosen_files
def assemble(self,roboset=None,format='png',bgset=None,sizex=300,sizey=300):
def assemble(self,roboset=None,color=None,format=None,bgset=None,sizex=300,sizey=300):
"""
Build our Robot!
Returns the robot image itself.
"""
# Set a default set for the robot
if roboset is None:
# Allow users to manually specify a robot 'set' that they like.
# Ensure that this is one of the allowed choices, or allow all
# If they don't set one, take the first entry from sets above.
if roboset == 'any':
roboset = self.sets[self.hasharray[1] % len(self.sets) ]
elif roboset in self.sets:
roboset = roboset
else:
roboset = self.sets[0]
# Only set1 is setup to be color-seletable. The others don't have enough pieces in various colors.
# This could/should probably be expanded at some point..
# Right now, this feature is almost never used. ( It was < 44 requests this year, out of 78M reqs )
if roboset == 'set1':
randomcolor = self.colors[self.hasharray[0] % len(self.colors) ]
roboset = 'set1/' + randomcolor
if color in self.colors:
roboset = 'set1/' + color
else:
randomcolor = self.colors[self.hasharray[0] % len(self.colors) ]
roboset = 'set1/' + randomcolor
# If they specified a background, ensure it's legal, then give it to them.
if bgset in self.bgsets:
bgset = bgset
elif bgset == 'any':
bgset = self.bgsets[ self.hasharray[2] % len(self.bgsets) ]
# If we set a format based on extension earlier, use that. Otherwise, PNG.
if format is None:
format = self.format
# Each directory in our set represents one piece of the Robot, such as the eyes, nose, mouth, etc.
@ -102,17 +152,17 @@ class Robohash(object):
# First, we'll get a list of parts of our robot.
roboparts = self._get_list_of_files('sets/' + roboset)
roboparts = self._get_list_of_files(self.resourcedir + 'sets/' + roboset)
# Now that we've sorted them by the first number, we need to sort each sub-category by the second.
roboparts.sort(key=lambda x: x.split("#")[1])
if bgset is not None:
bglist = []
backgrounds = os.listdir('backgrounds/' + bgset)
backgrounds = os.listdir(self.resourcedir + 'backgrounds/' + bgset)
backgrounds.sort()
for ls in backgrounds:
if not ls.startswith("."):
bglist.append('backgrounds/' + bgset + "/" + ls)
bglist.append(self.resourcedir + 'backgrounds/' + bgset + "/" + ls)
background = bglist[self.hasharray[3] % len(bglist)]
# Paste in each piece of the Robot.

View File

@ -223,6 +223,7 @@ class ImgHandler(tornado.web.RequestHandler):
sizey = 300
format = "png"
bgset = None
color = None
# Normally, we pass in arguments with standard HTTP GET variables, such as
# ?set=any and &size=100x100
@ -259,17 +260,11 @@ class ImgHandler(tornado.web.RequestHandler):
string = self.request.remote_ip
# If the user hasn't disabled it, detect if there is requested extension.
# If so, remove it from the string, but set the format.
# This ensures that /Bear.png and /Bear.bmp will send back the same image, in different formats.
if args.get('ignoreext','false').lower() != 'true':
if string.lower().endswith(('.png','.gif','.jpg','.bmp','.jpeg','.ppm','.datauri')):
format = string[string.rfind('.') +1 :len(string)]
if format.lower() == 'jpg':
format = 'jpeg'
string = string[0:string.rfind('.')]
# Detect if the user has passed in a flag to ignore extensions.
# Pass this along to to Robohash obj later on.
ignoreext = args.get('ignoreext','false').lower() == 'true'
# Split the size variable in to sizex and sizey
if "size" in args:
sizex,sizey = args['size'].split("x")
@ -306,6 +301,7 @@ class ImgHandler(tornado.web.RequestHandler):
# Create our Robohashing object
r = Robohash(string)
# Allow users to manually specify a robot 'set' that they like.
# Ensure that this is one of the allowed choices, or allow all
# If they don't set one, take the first entry from sets above.
@ -333,25 +329,23 @@ class ImgHandler(tornado.web.RequestHandler):
# Right now, this feature is almost never used. ( It was < 44 requests this year, out of 78M reqs )
if args.get('color') in r.colors:
roboset = 'set1/' + args.get('color')
roboset = 'set1'
color = args.get('color')
# If they DID choose set1, randomly choose a color.
if roboset == 'set1':
randomcolor = r.colors[r.hasharray[0] % len(r.colors) ]
roboset = 'set1/' + randomcolor
if roboset == 'set1' and color is None:
color = r.colors[r.hasharray[0] % len(r.colors) ]
roboset = 'set1'
# Allow them to set a background, or default to None
if args.get('bgset') in r.bgsets:
# Allow them to set a background, or keep as None
if args.get('bgset') in r.bgsets + ['any']:
bgset = args.get('bgset')
elif args.get('bgset','').lower() == 'any':
bgset = r.bgsets[ r.hasharray[2] % len(r.bgsets) ]
# We're going to be returning the image directly, so tell the browser to expect a binary.
self.set_header("Content-Type", "image/" + format)
# Build our Robot.
r.assemble(roboset=roboset,format=format,bgset=bgset,sizex=sizex,sizey=sizey)
r.assemble(roboset=roboset,format=format,bgset=bgset,color=color,sizex=sizex,sizey=sizey)
# Print the Robot to the handler, as a file-like obj
if r.format != 'datauri':