Skip to content

Commit

Permalink
EXIF fixes (linked to #142).
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Barran committed Dec 17, 2015
1 parent b8f964f commit 6d9983a
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 1,796 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ Changelog
3.4 (unreleased)
----------------

Upgrade notes:
- The EXIF property of an Image is now a method instead.

- Dropped support for Django 1.7.
- Fixed a few minor issues with the unit tests.
- Adding a watermark was crashing (fix suggested by hambro).
- Added/updated translations: Danish, Slovak (contributed by Rasmus Klett, saboter).
- Fixed Django 1.9 Deprecation warnings (contributed by jlemaes).
- Processing of EXIF data was broken (and very broken in Python 3) - updated library and bug fixes.


3.3.2 (2015-07-20)
Expand Down
9 changes: 5 additions & 4 deletions photologue/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class PhotoAdmin(admin.ModelAdmin):
search_fields = ['title', 'slug', 'caption']
list_per_page = 10
prepopulated_fields = {'slug': ('title',)}
readonly_fields = ('date_taken',)
form = PhotoAdminForm
if MULTISITE:
filter_horizontal = ['sites']
Expand Down Expand Up @@ -192,10 +193,10 @@ def remove_photos_from_current_site(modeladmin, request, queryset):
def get_urls(self):
urls = super(PhotoAdmin, self).get_urls()
custom_urls = [
url(r'^upload_zip/$',
self.admin_site.admin_view(self.upload_zip),
name='photologue_upload_zip')
]
url(r'^upload_zip/$',
self.admin_site.admin_view(self.upload_zip),
name='photologue_upload_zip')
]
return custom_urls + urls

def upload_zip(self, request):
Expand Down
44 changes: 20 additions & 24 deletions photologue/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
from io import BytesIO
from importlib import import_module
import exifread

from django.utils.timezone import now
from django.db import models
Expand Down Expand Up @@ -42,7 +43,6 @@

from sortedm2m.fields import SortedManyToManyField

from .utils import EXIF
from .utils.reflection import add_reflection
from .utils.watermark import apply_watermark
from .managers import GalleryQuerySet, PhotoQuerySet
Expand Down Expand Up @@ -259,7 +259,7 @@ class ImageModel(models.Model):
date_taken = models.DateTimeField(_('date taken'),
null=True,
blank=True,
editable=False)
help_text=_('Date image was taken; is obtained from the image EXIF data.'))
view_count = models.PositiveIntegerField(_('view count'),
default=0,
editable=False)
Expand All @@ -277,21 +277,16 @@ class ImageModel(models.Model):
class Meta:
abstract = True

@property
def EXIF(self):
def EXIF(self, file=None):
try:
f = self.image.storage.open(self.image.name, 'rb')
tags = EXIF.process_file(f)
f.close()
if file:
tags = exifread.process_file(file)
else:
with self.image.storage.open(self.image.name, 'rb') as file:
tags = exifread.process_file(file, details=False)
return tags
except:
try:
f = self.image.storage.open(self.image.name, 'rb')
tags = EXIF.process_file(f, details=False)
f.close()
return tags
except:
return {}
return {}

def admin_thumbnail(self):
func = getattr(self, 'get_admin_thumbnail_url', None)
Expand Down Expand Up @@ -429,10 +424,10 @@ def create_size(self, photosize):
if im.size != photosize.size and photosize.size != (0, 0):
im = self.resize_image(im, photosize)
# Rotate if found & necessary
if 'Image Orientation' in self.EXIF and \
self.EXIF.get('Image Orientation').values[0] in IMAGE_EXIF_ORIENTATION_MAP:
if 'Image Orientation' in self.EXIF() and \
self.EXIF().get('Image Orientation').values[0] in IMAGE_EXIF_ORIENTATION_MAP:
im = im.transpose(
IMAGE_EXIF_ORIENTATION_MAP[self.EXIF.get('Image Orientation').values[0]])
IMAGE_EXIF_ORIENTATION_MAP[self.EXIF().get('Image Orientation').values[0]])
# Apply watermark if found
if photosize.watermark is not None:
im = photosize.watermark.post_process(im)
Expand Down Expand Up @@ -480,21 +475,22 @@ def __init__(self, *args, **kwargs):
self._old_image = self.image

def save(self, *args, **kwargs):
if self.date_taken is None:
image_has_changed = False
if self._get_pk_val() and (self._old_image != self.image):
image_has_changed = True
self.clear_cache()
if self.date_taken is None or image_has_changed:
# Attempt to get the date the photo was taken from the EXIF data.
try:
exif_date = self.EXIF.get('EXIF DateTimeOriginal', None)
exif_date = self.EXIF(self.image.file).get('EXIF DateTimeOriginal', None)
if exif_date is not None:
d, t = str.split(exif_date.values)
year, month, day = d.split(':')
hour, minute, second = t.split(':')
self.date_taken = datetime(int(year), int(month), int(day),
int(hour), int(minute), int(second))
except:
pass
if self.date_taken is None:
self.date_taken = now()
if self._get_pk_val() and (self._old_image != self.image):
self.clear_cache()
logger.error('Failed to read EXIF DateTimeOriginal', exc_info=True)
super(ImageModel, self).save(*args, **kwargs)
self.pre_cache()

Expand Down

0 comments on commit 6d9983a

Please sign in to comment.