mirror of
https://github.com/jazzband/django-avatar.git
synced 2026-03-16 22:20:30 +00:00
Merge branch 'Jimdo-exif'
This commit is contained in:
commit
16d721c210
4 changed files with 49 additions and 2 deletions
|
|
@ -127,12 +127,38 @@ class Avatar(models.Model):
|
|||
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:
|
||||
|
|
|
|||
BIN
tests/data/image_exif_orientation.jpg
Normal file
BIN
tests/data/image_exif_orientation.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
BIN
tests/data/image_no_exif.jpg
Normal file
BIN
tests/data/image_no_exif.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
|
|
@ -1,5 +1,6 @@
|
|||
import os.path
|
||||
|
||||
import math
|
||||
from django.contrib.admin.sites import AdminSite
|
||||
from django.test import TestCase
|
||||
try:
|
||||
|
|
@ -15,7 +16,7 @@ from avatar.utils import get_primary_avatar, get_user_model
|
|||
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:
|
||||
|
|
@ -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', 'lennon@thebeatles.com', 'testpassword')
|
||||
|
|
@ -199,6 +209,17 @@ class AvatarTests(TestCase):
|
|||
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))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue