from django.http import HttpResponse, Http404
from django.views.decorators.cache import cache_control
from PIL import Image

@cache_control(max_age=3600*24*30)
def gradient(request, direction, r1, g1, b1, r2, g2, b2, size, grad_size):
	"""
	Create an image gradient on the fly as a PNG file.

	Arguments:

	direction
		The direction of the gradient as 'left', 'right', 'up' or 'down'.

	r1, g1, b1, r2, g2, b2
		RGB Values for the start and the end of the gradient. (0 to 255)

	size
		The width or height of the generated image.

	grad_size
		The width or height of the gradient. If greater	than 'size', the
		invisible part of the gradient is simply discarded.

	Use a regular expression like this in urls.py:
	r'^gradient-([a-z]*)-([0-9]*),([0-9]*),([0-9]*)-to-([0-9]*),([0-9]*),([0-9]*)-([0-9]*})-of-([0-9]*).png$'

	Example usage from CSS:
	'background: url(/gradient-down-255,255,255-to-0,0,0-70-of-120.png) repeat-x;'

	Author: Jens Breit
	"""
	rgb1 = (int(r1),int(g1),int(b1))
	rgb2 = (int(r2),int(g2),int(b2))
	size = int(size)
	grad_size = int(grad_size)
	# validate input ranges
	for z in rgb1 + rgb2:
		if z < 0 or z > 255:
			raise Http404
	if size > 2000:
		raise Http404
	# create image
	if direction == 'up' or direction == 'down':
		im = Image.new('RGB', (1, size))
	elif direction == 'left' or direction == 'right':
		im = Image.new('RGB', (size, 1))
	else:
		raise Http404 # because of invalid direction
	def channel(i, c):
		"""calculate the value of a single color channel for a single pixel"""
		return rgb1[c] + int((i * 1.0 / grad_size) * (rgb2[c] - rgb1[c]))
	def color(i):
		"""calculate the RGB value of a single pixel"""
		return tuple([channel(i, c) for c in range(3)])
	gradient = [ color(i) for i in xrange(size) ]
	if direction == 'up' or direction == 'left':
		gradient.reverse()
	# put gradient into image
	im.putdata(gradient)	
	# send image
	r = HttpResponse()
	r['Content-Type'] = 'image/png'
	im.save(r, 'PNG')
	return r