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