text: from PIL import Image, ImageDraw
  from hashlib import md5
  import base64
  import random
  from six import StringIO
  
  GRID_SIZE = 5
  BORDER_SIZE = 20
  SQUARE_SIZE = 40
  
  
  class Identicon(object):
  	def __init__(self, str_, background='#fafbfc'):
  		"""
  		`str_` is the string used to generate the identicon.
  		`background` is the background of the identicon.
  		"""
  		w = h = BORDER_SIZE * 2 + SQUARE_SIZE * GRID_SIZE
  		self.image = Image.new('RGB', (w, h), background)
  		self.draw = ImageDraw.Draw(self.image)
  		self.hash = self.digest(str_)
  
  	def digest(self, str_):
  		"""
  		Returns a md5 numeric hash
  		"""
  		return int(md5(str_.encode('utf-8')).hexdigest(), 16)
  
  	def calculate(self):
  		"""
  		Creates the identicon.
  		First three bytes are used to generate the color,
  		remaining bytes are used to create the drawing
  		"""
  		# color = (self.hash & 0xff, self.hash >> 8 & 0xff, self.hash >> 16 & 0xff)
  		color = random.choice((
  			(254, 196, 197),
  			(253, 138, 139),
  			(254, 231, 206),
  			(254, 208, 159),
  			(210, 211, 253),
  			(163, 165, 252),
  			(247, 213, 247),
  			(242, 172, 238),
  			(235, 247, 206),
  			(217, 241, 157),
  			(211, 248, 237),
  			(167, 242, 221),
  			(255, 249, 207),
  			(254, 245, 161),
  			(211, 241, 254),
  			(168, 228, 254),
  			(207, 245, 210),
  			(159, 235, 164),
  		))
  		# print color
  		# color = (254, 232, 206)
  
  		self.hash >>= 24  # skip first three bytes
  		square_x = square_y = 0  # init square position
  		for x in range(GRID_SIZE * (GRID_SIZE + 1) // 2):
  			if self.hash & 1:
  				x = BORDER_SIZE + square_x * SQUARE_SIZE
  				y = BORDER_SIZE + square_y * SQUARE_SIZE
  				self.draw.rectangle(
  					(x, y, x + SQUARE_SIZE, y + SQUARE_SIZE),
  					fill=color,
  					outline=color
  				)
  				# following is just for mirroring
  				x = BORDER_SIZE + (GRID_SIZE - 1 - square_x) * SQUARE_SIZE
  				self.draw.rectangle(
  					(x, y, x + SQUARE_SIZE, y + SQUARE_SIZE),
  					fill=color,
  					outline=color
  				)
  			self.hash >>= 1  # shift to right
  			square_y += 1
  			if square_y == GRID_SIZE:  # done with first column
  				square_y = 0
  				square_x += 1
  
  	def generate(self):
  		"""
  		Save and show calculated identicon
  		"""
  		self.calculate()
  		with open('identicon.png', 'wb') as out:
  			self.image.save(out, 'PNG')
  		self.image.show()
  
  	def base64(self, format='PNG'):
  		'''
  		usage:  i = Identicon('xx')
  				print(i.base64())
  		return: this image's base64 code
  		created by: liuzheng712
  		bug report: https://github.com/liuzheng712/identicons/issues
  		'''
  		self.calculate()
  		fp = StringIO()
  		self.image.encoderinfo = {}
  		self.image.encoderconfig = ()
  
  		if format.upper() not in Image.SAVE:
  			Image.init()
  		save_handler = Image.SAVE[format.upper()]
  		try:
  			save_handler(self.image, fp, '')
  		finally:
  			fp.seek(0)
  			return "data:image/png;base64,{0}".format(base64.b64encode(fp.read()))
  