Mercurial > public > sg101
comparison 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 |
comparison
equal
deleted
inserted
replaced
970:bd594bcba5eb | 971:4f265f61874b |
---|---|
1 """ | |
2 This file contains common utility functions for manipulating images for | |
3 the rest of the applications in the project. | |
4 """ | |
5 from PIL import ImageFile | |
6 from PIL import Image | |
7 | |
8 | |
9 def parse_image(file): | |
10 """ | |
11 Returns a PIL Image from the supplied Django file object. | |
12 Throws IOError if the file does not parse as an image file or some other | |
13 I/O error occurred. | |
14 | |
15 """ | |
16 parser = ImageFile.Parser() | |
17 for chunk in file.chunks(): | |
18 parser.feed(chunk) | |
19 image = parser.close() | |
20 return image | |
21 | |
22 | |
23 def downscale_image_square(image, size): | |
24 """ | |
25 Scale an image to the square dimensions given by size (in pixels). | |
26 The new image is returned. | |
27 If the image is already smaller than (size, size) then no scaling | |
28 is performed and the image is returned unchanged. | |
29 | |
30 """ | |
31 # don't upscale | |
32 if (size, size) >= image.size: | |
33 return image | |
34 | |
35 (w, h) = image.size | |
36 if w > h: | |
37 diff = (w - h) / 2 | |
38 image = image.crop((diff, 0, w - diff, h)) | |
39 elif h > w: | |
40 diff = (h - w) / 2 | |
41 image = image.crop((0, diff, w, h - diff)) | |
42 image = image.resize((size, size), Image.ANTIALIAS) | |
43 return image | |
44 | |
45 | |
46 # Various image transformation functions: | |
47 def flip_horizontal(im): | |
48 return im.transpose(Image.FLIP_LEFT_RIGHT) | |
49 | |
50 def flip_vertical(im): | |
51 return im.transpose(Image.FLIP_TOP_BOTTOM) | |
52 | |
53 def rotate_180(im): | |
54 return im.transpose(Image.ROTATE_180) | |
55 | |
56 def rotate_90(im): | |
57 return im.transpose(Image.ROTATE_90) | |
58 | |
59 def rotate_270(im): | |
60 return im.transpose(Image.ROTATE_270) | |
61 | |
62 def transpose(im): | |
63 return rotate_90(flip_horizontal(im)) | |
64 | |
65 def transverse(im): | |
66 return rotate_90(flip_vertical(im)) | |
67 | |
68 # From http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html | |
69 # EXIF Orientation tag values: | |
70 # 1 = Horizontal (normal) | |
71 # 2 = Mirror horizontal | |
72 # 3 = Rotate 180 | |
73 # 4 = Mirror vertical | |
74 # 5 = Mirror horizontal and rotate 270 CW | |
75 # 6 = Rotate 90 CW | |
76 # 7 = Mirror horizontal and rotate 90 CW | |
77 # 8 = Rotate 270 CW | |
78 | |
79 ORIENT_FUNCS = { | |
80 2: flip_horizontal, | |
81 3: rotate_180, | |
82 4: flip_vertical, | |
83 5: transpose, | |
84 6: rotate_270, | |
85 7: transverse, | |
86 8: rotate_90, | |
87 } | |
88 | |
89 ORIENT_TAG = 0x112 | |
90 | |
91 | |
92 def orient_image(im): | |
93 """Transforms the given image according to embedded EXIF data. | |
94 | |
95 The image instance, im, should be a PIL Image. | |
96 If there is EXIF information for the image, and the orientation tag | |
97 indicates that the image should be transformed, perform the transformation. | |
98 | |
99 Returns a tuple of the form (flag, image) where flag is True if the image | |
100 was oriented and False otherwise. image is either a new transformed image or | |
101 the original image instance. | |
102 | |
103 """ | |
104 if hasattr(im, '_getexif'): | |
105 try: | |
106 exif = im._getexif() | |
107 except IndexError: | |
108 # Work around issue seen in Pillow | |
109 # https://github.com/python-pillow/Pillow/issues/518 | |
110 exif = None | |
111 | |
112 if exif and ORIENT_TAG in exif: | |
113 orientation = exif[ORIENT_TAG] | |
114 func = ORIENT_FUNCS.get(orientation) | |
115 if func: | |
116 return (True, func(im)) | |
117 | |
118 return (False, im) |