summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/photos/admin.py28
-rw-r--r--app/photos/forms.py55
-rw-r--r--app/photos/migrations/0004_luximage_alt.py20
-rw-r--r--app/photos/migrations/0005_auto_20160318_1244.py25
-rw-r--r--app/photos/migrations/0006_auto_20160318_2047.py30
-rw-r--r--app/photos/migrations/0007_auto_20160320_0802.py20
-rw-r--r--app/photos/migrations/0008_luximagesize_quality.py21
-rw-r--r--app/photos/migrations/0009_auto_20160320_0907.py20
-rw-r--r--app/photos/models.py78
-rw-r--r--app/photos/readexif.py59
-rw-r--r--app/photos/templatetags/get_image_by_size.py (renamed from app/photos/templatetags/get_image_size.py)4
-rw-r--r--app/photos/utils.py4
12 files changed, 308 insertions, 56 deletions
diff --git a/app/photos/admin.py b/app/photos/admin.py
index 659dcb6..9453734 100644
--- a/app/photos/admin.py
+++ b/app/photos/admin.py
@@ -4,7 +4,7 @@ from django.contrib.gis.admin import OSMGeoAdmin
from django.conf.urls import patterns
from django.conf.urls import url
from django.utils.translation import ungettext, ugettext_lazy as _
-from photos.models import Photo, PhotoGallery, LuxImage, LuxGallery
+from photos.models import Photo, PhotoGallery, LuxImage, LuxGallery, LuxImageSize
from django.shortcuts import render
from django.contrib.admin import helpers
from django.http import HttpResponseRedirect
@@ -13,10 +13,17 @@ from django.http import HttpResponseRedirect
from .forms import UploadZipForm, GalleryForm
+class LuxImageSizeAdmin(OSMGeoAdmin):
+ pass
+
+
+admin.site.register(LuxImageSize, LuxImageSizeAdmin)
+
+
class LuxImageAdmin(OSMGeoAdmin):
- list_display = ('pk', 'admin_thumbnail', 'pub_date',)
- list_filter = ('pub_date',)
+ list_display = ('pk', 'admin_thumbnail', 'pub_date', 'location')
+ list_filter = ('pub_date', 'location')
search_fields = ['title', 'caption']
# Options for OSM map Using custom ESRI topo map
default_lon = -9285175
@@ -29,6 +36,21 @@ class LuxImageAdmin(OSMGeoAdmin):
map_template = 'gis/admin/osm.html'
openlayers_url = '/static/admin/js/OpenLayers.js'
+ fieldsets = (
+ (None, {
+ 'fields': (('image', 'pub_date'), 'sizes', ('title', 'alt'), 'caption', 'point', ('is_public', 'is_video'), ('photo_credit_source','photo_credit_url'))
+ }),
+ ('Exif Data', {
+ 'classes': ('collapse',),
+ 'fields': ('exif_raw', 'exif_aperture', 'exif_make', 'exif_model', 'exif_exposure', 'exif_iso', 'exif_focal_length', 'exif_lens', 'exif_date', 'height', 'width'),
+ }),
+ )
+
+
+
+
+
+
admin.site.register(LuxImage, LuxImageAdmin)
diff --git a/app/photos/forms.py b/app/photos/forms.py
index 1f80496..8ad89f2 100644
--- a/app/photos/forms.py
+++ b/app/photos/forms.py
@@ -2,10 +2,8 @@ import zipfile
from zipfile import BadZipFile
import logging
import datetime
-import time
import os
from io import BytesIO
-from fractions import Fraction
try:
import Image
except ImportError:
@@ -17,21 +15,18 @@ from django.utils.safestring import mark_safe
from django.contrib import messages
from django.core.files.base import ContentFile
from django.contrib.admin import widgets
-from django.contrib.gis.geos import Point
from django.conf import settings
-import exiftool
-from photos.models import LuxImage, LuxGallery
-from locations.models import Location
+from photos.models import LuxImage, LuxGallery, LuxImageSize
from .utils import resize_image
+from .readexif import readexif
logger = logging.getLogger('photos.forms')
class GalleryForm(forms.ModelForm):
class Meta:
- model = LuxGallery
fields = '__all__'
widgets = {
'images': forms.SelectMultiple,
@@ -152,56 +147,24 @@ class UploadZipForm(forms.Form):
image.image.save(filename, contentfile)
image.save()
gallery.images.add(image)
-
- with exiftool.ExifTool() as et:
- meta = et.get_metadata(image.image.path)
- et.terminate()
- image.exif_raw = meta
- try:
- image.title = meta["EXIF:ImageDescription"]
- except:
- pass
- try:
- image.caption = meta["EXIF:UserComment"]
- except:
- pass
- try:
- image.exif_lens = meta["MakerNotes:LensType"]
- except:
- try:
- image.exif_lens = meta["XMP:Lens"]
- except:
- pass
- try:
- image.point = Point(meta["XMP:GPSLongitude"], meta["XMP:GPSLatitude"], srid=4326)
- try:
- image.location = Location.objects.filter(geometry__contains=image.point).get()
- except Location.DoesNotExist:
- pass
- except KeyError:
- pass
- image.exif_aperture = meta["EXIF:FNumber"]
- image.exif_make = meta["EXIF:Make"]
- image.exif_model = meta["EXIF:Model"]
- image.exif_exposure = str(Fraction(float(meta["EXIF:ExposureTime"])).limit_denominator())
- image.exif_iso = meta["EXIF:ISO"]
- image.exif_focal_length = meta["EXIF:FocalLength"]
- fmt_date = time.strptime(meta["EXIF:DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
- image.exif_date = time.strftime("%Y-%m-%d %H:%M:%S", fmt_date)
- image.height = meta["File:ImageHeight"]
- image.width = meta["File:ImageWidth"]
- image.save()
+ readexif(image)
count += 1
img = Image.open(image.image.path)
base_path = "%s/galleries/" % settings.IMAGES_ROOT
if img.size[0] > img.size[1]:
resize_image(img, 2280, None, 65, base_path+'large/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=2280))
resize_image(img, 1140, None, 72, base_path+'medium/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=1140))
resize_image(img, 720, None, 68, base_path+'small/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=720))
if img.size[1] > img.size[0]:
resize_image(img, None, 1600, 65, base_path+'large/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=1600))
resize_image(img, None, 800, 72, base_path+'medium/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=800))
resize_image(img, None, 460, 60, base_path+'small/', image.get_image_name())
+ image.sizes.add(LuxImageSize.objects.get(size=460))
resize_image(img, 160, None, 68, base_path+'thumb/', image.get_image_name())
zipper.close()
diff --git a/app/photos/migrations/0004_luximage_alt.py b/app/photos/migrations/0004_luximage_alt.py
new file mode 100644
index 0000000..ecbaf56
--- /dev/null
+++ b/app/photos/migrations/0004_luximage_alt.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-16 22:45
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0003_luxgallery_caption_style'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='luximage',
+ name='alt',
+ field=models.CharField(blank=True, max_length=300, null=True),
+ ),
+ ]
diff --git a/app/photos/migrations/0005_auto_20160318_1244.py b/app/photos/migrations/0005_auto_20160318_1244.py
new file mode 100644
index 0000000..584714e
--- /dev/null
+++ b/app/photos/migrations/0005_auto_20160318_1244.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-18 12:44
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0004_luximage_alt'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='luximage',
+ name='photo_credit_source',
+ field=models.CharField(blank=True, max_length=300, null=True),
+ ),
+ migrations.AddField(
+ model_name='luximage',
+ name='photo_credit_url',
+ field=models.CharField(blank=True, max_length=300, null=True),
+ ),
+ ]
diff --git a/app/photos/migrations/0006_auto_20160318_2047.py b/app/photos/migrations/0006_auto_20160318_2047.py
new file mode 100644
index 0000000..7cf0a4f
--- /dev/null
+++ b/app/photos/migrations/0006_auto_20160318_2047.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-18 20:47
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0005_auto_20160318_1244'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='LuxImageSize',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('size', models.IntegerField(max_length=5)),
+ ],
+ options={
+ 'verbose_name_plural': 'Image Sizes',
+ },
+ ),
+ migrations.AddField(
+ model_name='luximage',
+ name='sizes',
+ field=models.ManyToManyField(to='photos.LuxImageSize'),
+ ),
+ ]
diff --git a/app/photos/migrations/0007_auto_20160320_0802.py b/app/photos/migrations/0007_auto_20160320_0802.py
new file mode 100644
index 0000000..474bd42
--- /dev/null
+++ b/app/photos/migrations/0007_auto_20160320_0802.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-20 08:02
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0006_auto_20160318_2047'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='luximagesize',
+ name='size',
+ field=models.IntegerField(),
+ ),
+ ]
diff --git a/app/photos/migrations/0008_luximagesize_quality.py b/app/photos/migrations/0008_luximagesize_quality.py
new file mode 100644
index 0000000..06dc0cc
--- /dev/null
+++ b/app/photos/migrations/0008_luximagesize_quality.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-20 08:47
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0007_auto_20160320_0802'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='luximagesize',
+ name='quality',
+ field=models.IntegerField(default=65),
+ preserve_default=False,
+ ),
+ ]
diff --git a/app/photos/migrations/0009_auto_20160320_0907.py b/app/photos/migrations/0009_auto_20160320_0907.py
new file mode 100644
index 0000000..ccfebf5
--- /dev/null
+++ b/app/photos/migrations/0009_auto_20160320_0907.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9 on 2016-03-20 09:07
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('photos', '0008_luximagesize_quality'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='luximagesize',
+ old_name='size',
+ new_name='width',
+ ),
+ ]
diff --git a/app/photos/models.py b/app/photos/models.py
index 50ae43b..46c659e 100644
--- a/app/photos/models.py
+++ b/app/photos/models.py
@@ -10,14 +10,34 @@ from django.conf import settings
from taggit.managers import TaggableManager
from locations.models import Location, Region
+from .utils import resize_image
+from .readexif import readexif
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from django.db.models.signals import m2m_changed
+
def get_upload_path(self, filename):
- return "images/galleries/original/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename)
+ return "images/original/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename)
+
+
+class LuxImageSize(models.Model):
+ width = models.IntegerField()
+ quality = models.IntegerField()
+
+ class Meta:
+ verbose_name_plural = 'Image Sizes'
+
+ def __str__(self):
+ return str(self.width)
class LuxImage(models.Model):
image = models.FileField(blank=True, null=True, upload_to=get_upload_path)
title = models.CharField(null=True, blank=True, max_length=300)
+ alt = models.CharField(null=True, blank=True, max_length=300)
+ photo_credit_source = models.CharField(null=True, blank=True, max_length=300)
+ photo_credit_url = models.CharField(null=True, blank=True, max_length=300)
caption = models.TextField(blank=True, null=True)
pub_date = models.DateTimeField()
exif_raw = models.TextField(blank=True, null=True)
@@ -35,6 +55,7 @@ class LuxImage(models.Model):
location = models.ForeignKey(Location, null=True, blank=True)
is_public = models.BooleanField(default=True)
is_video = models.BooleanField(default=False)
+ sizes = models.ManyToManyField(LuxImageSize)
flickr_id = models.CharField(null=True, blank=True, max_length=80)
class Meta:
@@ -48,15 +69,27 @@ class LuxImage(models.Model):
else:
return "%s" % self.pk
+ def get_admin_image(self):
+ for size in self.sizes.all():
+ if size.width <= 800:
+ return self.get_image_by_size(size)
+
+
def get_image_name(self):
- return self.image.url.split("galleries/original/")[1]
+ return self.image.url.split("original/")[1][5:-4]
- def get_image_size(self, size="original"):
+ def get_image_ext(self):
+ return self.image.url[-3:]
+
+ def get_image_by_size(self, size="original"):
base = self.get_image_name()
- return "%sgalleries/%s/%s" % (settings.IMAGES_URL, size, base)
+ if size == "original":
+ return "%soriginal/%s/%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, self.get_image_ext())
+ else:
+ return "%s%s/%s_%s.%s" % (settings.IMAGES_URL, self.pub_date.strftime("%Y"), base, size, self.get_image_ext())
def admin_thumbnail(self):
- return force_text('<a href="%s"><img src="%s"></a>' % (self.get_image_size(), self.get_image_size("thumb")))
+ return force_text('<a href="%s"><img src="%s"></a>' % (self.get_image_by_size(), self.get_image_by_size("tn")))
admin_thumbnail.allow_tags = True
admin_thumbnail.short_description = 'Thumbnail'
@@ -79,6 +112,25 @@ class LuxImage(models.Model):
return "/admin/photos/luximage/%s/change/" % n.pk
+@receiver(post_save, sender=LuxImage)
+def post_save_events(sender, update_fields, created, instance, **kwargs):
+ instance = readexif(instance)
+ post_save.disconnect(post_save_events, sender=LuxImage)
+ instance.save()
+ post_save.connect(post_save_events, sender=LuxImage)
+
+
+@receiver(m2m_changed, sender=LuxImage.sizes.through)
+def update_photo_sizes(sender, instance, **kwargs):
+ print("hellow world")
+ base_path = "%s/%s/" % (settings.IMAGES_ROOT, instance.pub_date.strftime("%Y"))
+ img = Image.open(instance.image.path)
+ resize_image(img, 160, None, 65, base_path, "%s_tn.%s" % (instance.get_image_name(), instance.get_image_ext()))
+ for size in instance.sizes.all():
+ print(size.width)
+ resize_image(img, size.width, None, size.quality, base_path, "%s_%s.%s" % (instance.get_image_name(), size.width, instance.get_image_ext()))
+
+
class LuxGallery(models.Model):
title = models.CharField(blank=True, max_length=300)
description = models.TextField(blank=True, null=True)
@@ -317,3 +369,19 @@ class PhotoGallerySitemap(Sitemap):
def lastmod(self, obj):
return obj.pub_date
+
+
+def resize_luximage(self, image):
+ image.save()
+ img = Image.open(image.image.path)
+ base_path = "%s/galleries/" % settings.IMAGES_ROOT
+ if img.size[0] > img.size[1]:
+ resize_image(img, 2280, None, 65, base_path+'large/', image.get_image_name())
+ resize_image(img, 1140, None, 72, base_path+'medium/', image.get_image_name())
+ resize_image(img, 720, None, 68, base_path+'small/', image.get_image_name())
+ if img.size[1] > img.size[0]:
+ resize_image(img, None, 1600, 65, base_path+'large/', image.get_image_name())
+ resize_image(img, None, 800, 72, base_path+'medium/', image.get_image_name())
+ resize_image(img, None, 460, 60, base_path+'small/', image.get_image_name())
+
+ resize_image(img, 160, None, 68, base_path+'thumb/', image.get_image_name())
diff --git a/app/photos/readexif.py b/app/photos/readexif.py
new file mode 100644
index 0000000..0b3f7f7
--- /dev/null
+++ b/app/photos/readexif.py
@@ -0,0 +1,59 @@
+import time
+from fractions import Fraction
+
+from django.contrib.gis.geos import Point
+
+import exiftool
+
+from locations.models import Location
+
+
+def readexif(image):
+ """
+ takes an image and fills in all the exif data tracked in the image model
+
+ """
+ with exiftool.ExifTool() as et:
+ meta = et.get_metadata(image.image.path)
+ et.terminate()
+ image.exif_raw = meta
+ try:
+ image.title = meta["EXIF:ImageDescription"]
+ except:
+ try:
+ image.title = meta["XMP:Title"]
+ except:
+ pass
+ try:
+ image.caption = meta["EXIF:UserComment"]
+ except:
+ pass
+ try:
+ image.exif_lens = meta["MakerNotes:LensType"]
+ except:
+ try:
+ image.exif_lens = meta["XMP:Lens"]
+ except:
+ pass
+ try:
+ image.point = Point(meta["XMP:GPSLongitude"], meta["XMP:GPSLatitude"], srid=4326)
+ try:
+ image.location = Location.objects.filter(geometry__contains=image.point).get()
+ except Location.DoesNotExist:
+ pass
+ except KeyError:
+ pass
+ try:
+ image.exif_aperture = meta["EXIF:FNumber"]
+ except:
+ pass
+ image.exif_make = meta["EXIF:Make"]
+ image.exif_model = meta["EXIF:Model"]
+ image.exif_exposure = str(Fraction(float(meta["EXIF:ExposureTime"])).limit_denominator())
+ image.exif_iso = meta["EXIF:ISO"]
+ image.exif_focal_length = meta["EXIF:FocalLength"]
+ fmt_date = time.strptime(meta["EXIF:DateTimeOriginal"], "%Y:%m:%d %H:%M:%S")
+ image.exif_date = time.strftime("%Y-%m-%d %H:%M:%S", fmt_date)
+ image.height = meta["File:ImageHeight"]
+ image.width = meta["File:ImageWidth"]
+ return image
diff --git a/app/photos/templatetags/get_image_size.py b/app/photos/templatetags/get_image_by_size.py
index 4ca6c66..c56c44e 100644
--- a/app/photos/templatetags/get_image_size.py
+++ b/app/photos/templatetags/get_image_by_size.py
@@ -3,6 +3,6 @@ from django import template
register = template.Library()
@register.simple_tag
-def get_image_size(obj, *args):
- method = getattr(obj, "get_image_size")
+def get_image_by_size(obj, *args):
+ method = getattr(obj, "get_image_by_size")
return method(*args)
diff --git a/app/photos/utils.py b/app/photos/utils.py
index 6cc64a3..e880277 100644
--- a/app/photos/utils.py
+++ b/app/photos/utils.py
@@ -1,4 +1,7 @@
import os
+import subprocess
+
+# pip install python-resize-image
from resizeimage import resizeimage
@@ -13,3 +16,4 @@ def resize_image(img, width=None, height=None, quality=72, base_path="", filenam
os.makedirs(base_path)
path = "%s%s" % (base_path, filename)
newimg.save(path, newimg.format, quality=quality)
+ subprocess.call(["jpegoptim", "%s" % path])