Mercurial > public > sg101
diff core/images/utils.py @ 971:4f265f61874b
Hotlink image form is functioning.
The user can now submit a URL via a form and the URL will be downloaded
and uploaded to a S3 bucket if it is an image.
Tests to follow.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Tue, 22 Sep 2015 20:23:50 -0500 |
parents | core/image.py@24fc302f9076 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/images/utils.py Tue Sep 22 20:23:50 2015 -0500 @@ -0,0 +1,118 @@ +""" +This file contains common utility functions for manipulating images for +the rest of the applications in the project. +""" +from PIL import ImageFile +from PIL import Image + + +def parse_image(file): + """ + Returns a PIL Image from the supplied Django file object. + Throws IOError if the file does not parse as an image file or some other + I/O error occurred. + + """ + parser = ImageFile.Parser() + for chunk in file.chunks(): + parser.feed(chunk) + image = parser.close() + return image + + +def downscale_image_square(image, size): + """ + Scale an image to the square dimensions given by size (in pixels). + The new image is returned. + If the image is already smaller than (size, size) then no scaling + is performed and the image is returned unchanged. + + """ + # don't upscale + if (size, size) >= image.size: + return image + + (w, h) = image.size + if w > h: + diff = (w - h) / 2 + image = image.crop((diff, 0, w - diff, h)) + elif h > w: + diff = (h - w) / 2 + image = image.crop((0, diff, w, h - diff)) + image = image.resize((size, size), Image.ANTIALIAS) + return image + + +# Various image transformation functions: +def flip_horizontal(im): + return im.transpose(Image.FLIP_LEFT_RIGHT) + +def flip_vertical(im): + return im.transpose(Image.FLIP_TOP_BOTTOM) + +def rotate_180(im): + return im.transpose(Image.ROTATE_180) + +def rotate_90(im): + return im.transpose(Image.ROTATE_90) + +def rotate_270(im): + return im.transpose(Image.ROTATE_270) + +def transpose(im): + return rotate_90(flip_horizontal(im)) + +def transverse(im): + return rotate_90(flip_vertical(im)) + +# From http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html +# EXIF Orientation tag values: +# 1 = Horizontal (normal) +# 2 = Mirror horizontal +# 3 = Rotate 180 +# 4 = Mirror vertical +# 5 = Mirror horizontal and rotate 270 CW +# 6 = Rotate 90 CW +# 7 = Mirror horizontal and rotate 90 CW +# 8 = Rotate 270 CW + +ORIENT_FUNCS = { + 2: flip_horizontal, + 3: rotate_180, + 4: flip_vertical, + 5: transpose, + 6: rotate_270, + 7: transverse, + 8: rotate_90, +} + +ORIENT_TAG = 0x112 + + +def orient_image(im): + """Transforms the given image according to embedded EXIF data. + + The image instance, im, should be a PIL Image. + If there is EXIF information for the image, and the orientation tag + indicates that the image should be transformed, perform the transformation. + + Returns a tuple of the form (flag, image) where flag is True if the image + was oriented and False otherwise. image is either a new transformed image or + the original image instance. + + """ + if hasattr(im, '_getexif'): + try: + exif = im._getexif() + except IndexError: + # Work around issue seen in Pillow + # https://github.com/python-pillow/Pillow/issues/518 + exif = None + + if exif and ORIENT_TAG in exif: + orientation = exif[ORIENT_TAG] + func = ORIENT_FUNCS.get(orientation) + if func: + return (True, func(im)) + + return (False, im)