annotate mysite/photologue/utils/reflection.py @ 88:7245c769e31e django1.3

Close this branch. I'm not sure if I merged it correctly to the default branch, because the graphlog doesn't look right. But the changes were made to default somehow. So closing this off to prevent future confusion.
author Brian Neal <bgneal@gmail.com>
date Sat, 13 Apr 2013 18:08:19 -0500
parents 0dcfcdf50c62
children
rev   line source
bgneal@1 1 """ Function for generating web 2.0 style image reflection effects.
bgneal@1 2
bgneal@1 3 Copyright (c) 2007, Justin C. Driscoll
bgneal@1 4 All rights reserved.
bgneal@1 5
bgneal@1 6 Redistribution and use in source and binary forms, with or without modification,
bgneal@1 7 are permitted provided that the following conditions are met:
bgneal@1 8
bgneal@1 9 1. Redistributions of source code must retain the above copyright notice,
bgneal@1 10 this list of conditions and the following disclaimer.
bgneal@1 11
bgneal@1 12 2. Redistributions in binary form must reproduce the above copyright
bgneal@1 13 notice, this list of conditions and the following disclaimer in the
bgneal@1 14 documentation and/or other materials provided with the distribution.
bgneal@1 15
bgneal@1 16 3. Neither the name of reflection.py nor the names of its contributors may be used
bgneal@1 17 to endorse or promote products derived from this software without
bgneal@1 18 specific prior written permission.
bgneal@1 19
bgneal@1 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
bgneal@1 21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
bgneal@1 22 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
bgneal@1 23 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
bgneal@1 24 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
bgneal@1 25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
bgneal@1 26 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
bgneal@1 27 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
bgneal@1 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
bgneal@1 29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bgneal@1 30
bgneal@1 31 """
bgneal@1 32
bgneal@1 33 try:
bgneal@1 34 import Image
bgneal@1 35 import ImageColor
bgneal@1 36 except ImportError:
bgneal@1 37 try:
bgneal@1 38 from PIL import Image
bgneal@1 39 from PIL import ImageColor
bgneal@1 40 except ImportError:
bgneal@1 41 raise ImportError("The Python Imaging Library was not found.")
bgneal@1 42
bgneal@1 43
bgneal@1 44 def add_reflection(im, bgcolor="#00000", amount=0.4, opacity=0.6):
bgneal@1 45 """ Returns the supplied PIL Image (im) with a reflection effect
bgneal@1 46
bgneal@1 47 bgcolor The background color of the reflection gradient
bgneal@1 48 amount The height of the reflection as a percentage of the orignal image
bgneal@1 49 opacity The initial opacity of the reflection gradient
bgneal@1 50
bgneal@1 51 Originally written for the Photologue image management system for Django
bgneal@1 52 and Based on the original concept by Bernd Schlapsi
bgneal@1 53
bgneal@1 54 """
bgneal@1 55 # convert bgcolor string to rgb value
bgneal@1 56 background_color = ImageColor.getrgb(bgcolor)
bgneal@1 57
bgneal@1 58 # copy orignial image and flip the orientation
bgneal@1 59 reflection = im.copy().transpose(Image.FLIP_TOP_BOTTOM)
bgneal@1 60
bgneal@1 61 # create a new image filled with the bgcolor the same size
bgneal@1 62 background = Image.new("RGB", im.size, background_color)
bgneal@1 63
bgneal@1 64 # calculate our alpha mask
bgneal@1 65 start = int(255 - (255 * opacity)) # The start of our gradient
bgneal@1 66 steps = int(255 * amount) # the number of intermedite values
bgneal@1 67 increment = (255 - start) / float(steps)
bgneal@1 68 mask = Image.new('L', (1, 255))
bgneal@1 69 for y in range(255):
bgneal@1 70 if y < steps:
bgneal@1 71 val = int(y * increment + start)
bgneal@1 72 else:
bgneal@1 73 val = 255
bgneal@1 74 mask.putpixel((0, y), val)
bgneal@1 75 alpha_mask = mask.resize(im.size)
bgneal@1 76
bgneal@1 77 # merge the reflection onto our background color using the alpha mask
bgneal@1 78 reflection = Image.composite(background, reflection, alpha_mask)
bgneal@1 79
bgneal@1 80 # crop the reflection
bgneal@1 81 reflection_height = int(im.size[1] * amount)
bgneal@1 82 reflection = reflection.crop((0, 0, im.size[0], reflection_height))
bgneal@1 83
bgneal@1 84 # create new image sized to hold both the original image and the reflection
bgneal@1 85 composite = Image.new("RGB", (im.size[0], im.size[1]+reflection_height), background_color)
bgneal@1 86
bgneal@1 87 # paste the orignal image and the reflection into the composite image
bgneal@1 88 composite.paste(im, (0, 0))
bgneal@1 89 composite.paste(reflection, (0, im.size[1]))
bgneal@1 90
bgneal@1 91 # return the image complete with reflection effect
bgneal@1 92 return composite
bgneal@1 93