Skip to content

Commit

Permalink
Merge branch 'Jimdo-exif'
Browse files Browse the repository at this point in the history
  • Loading branch information
grantmcconnaughey committed Dec 17, 2017
2 parents f940db8 + 2de2a60 commit 16d721c
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 2 deletions.
26 changes: 26 additions & 0 deletions avatar/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,38 @@ def save(self, *args, **kwargs):
def thumbnail_exists(self, size):
return self.avatar.storage.exists(self.avatar_name(size))

def transpose_image(self, image):
"""
Transpose based on EXIF information.
Borrowed from django-imagekit:
imagekit.processors.Transpose
"""
EXIF_ORIENTATION_STEPS = {
1: [],
2: ['FLIP_LEFT_RIGHT'],
3: ['ROTATE_180'],
4: ['FLIP_TOP_BOTTOM'],
5: ['ROTATE_270', 'FLIP_LEFT_RIGHT'],
6: ['ROTATE_270'],
7: ['ROTATE_90', 'FLIP_LEFT_RIGHT'],
8: ['ROTATE_90'],
}
try:
orientation = image._getexif()[0x0112]
ops = EXIF_ORIENTATION_STEPS[orientation]
except:
ops = []
for method in ops:
image = image.transpose(getattr(Image, method))
return image

def create_thumbnail(self, size, quality=None):
# invalidate the cache of the thumbnail with the given size first
invalidate_cache(self.user, size)
try:
orig = self.avatar.storage.open(self.avatar.name, 'rb')
image = Image.open(orig)
image = self.transpose_image(image)
quality = quality or settings.AVATAR_THUMB_QUALITY
w, h = image.size
if w != size or h != size:
Expand Down
Binary file added tests/data/image_exif_orientation.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/data/image_no_exif.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 23 additions & 2 deletions tests/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os.path

import math
from django.contrib.admin.sites import AdminSite
from django.test import TestCase
try:
Expand All @@ -15,7 +16,7 @@
from avatar.models import Avatar
from avatar.templatetags import avatar_tags
from avatar.signals import avatar_deleted
from PIL import Image
from PIL import Image, ImageChops


class AssertSignal:
Expand Down Expand Up @@ -43,8 +44,17 @@ def upload_helper(o, filename):
return response


class AvatarTests(TestCase):
def root_mean_square_difference(image1, image2):
"Calculate the root-mean-square difference between two images"
diff = ImageChops.difference(image1, image2).convert('L')
h = diff.histogram()
sq = (value * (idx ** 2) for idx, value in enumerate(h))
sum_of_squares = sum(sq)
rms = math.sqrt(sum_of_squares / float(image1.size[0] * image1.size[1]))
return rms


class AvatarTests(TestCase):
def setUp(self):
self.testdatapath = os.path.join(os.path.dirname(__file__), "data")
self.user = get_user_model().objects.create_user('test', '[email protected]', 'testpassword')
Expand Down Expand Up @@ -199,6 +209,17 @@ def test_automatic_thumbnail_creation_CMYK(self):
image = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb'))
self.assertEqual(image.mode, 'RGB')

def test_thumbnail_transpose_based_on_exif(self):
upload_helper(self, "image_no_exif.jpg")
avatar = get_primary_avatar(self.user)
image_no_exif = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb'))

upload_helper(self, "image_exif_orientation.jpg")
avatar = get_primary_avatar(self.user)
image_with_exif = Image.open(avatar.avatar.storage.open(avatar.avatar_name(settings.AVATAR_DEFAULT_SIZE), 'rb'))

self.assertLess(root_mean_square_difference(image_with_exif, image_no_exif), 1)

def test_has_avatar_False_if_no_avatar(self):
self.assertFalse(avatar_tags.has_avatar(self.user))

Expand Down

0 comments on commit 16d721c

Please sign in to comment.