Skip to content
11 changes: 9 additions & 2 deletions imagefit/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,22 @@ class Settings(LazySettings):
# cache backend name
IMAGEFIT_CACHE_BACKEND_NAME = getattr(settings, 'IMAGEFIT_CACHE_NAME', 'imagefit')

settings.CACHES = {
if hasattr(settings, "CACHES"):
caches = settings.CACHES
else:
caches = {}
settings.CACHES = caches
caches.update({
IMAGEFIT_CACHE_BACKEND_NAME: {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(tempfile.gettempdir(), 'django_imagefit')
}
}
})

# ConditionalGetMiddleware is required for browser caching
if not 'django.middleware.http.ConditionalGetMiddleware' in settings.MIDDLEWARE_CLASSES:
settings.MIDDLEWARE_CLASSES += ('django.middleware.http.ConditionalGetMiddleware',)

IMAGEFIT_FORMAT_SETTINGS = getattr(settings, "IMAGEFIT_FORMAT_SETTINGS", {"JPEG": {"quality":85}})

settings = Settings()
51 changes: 44 additions & 7 deletions imagefit/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from imagefit.conf import settings
from PIL import Image as PilImage


import mimetypes
try:
import StringIO
Expand All @@ -18,14 +19,30 @@ class Image(object):

def __init__(self, path, cache=None, cached_name=None, *args, **kwargs):
self.path = path
self.pil = PilImage.open(path)
self.pil_ = None
self.cache = cache
self.cached_name = cached_name

# force RGB
if self.pil.mode not in ('L', 'RGB'):
self.pil = self.pil.convert('RGB')


@property
def pil(self):
"""
Load the actual image object only on demand - these can get big.
"""

if self.pil_ is None:
self.pil_ = PilImage.open(self.path)
# force RGB
if self.pil_.mode not in ('L', 'RGBA'):
self.pil_ = self.pil_.convert('RGBA')

return self.pil_

@pil.setter
def pil(self, value):
self.pil_ = value

@property
def mimetype(self):
return mimetypes.guess_type(self.path)[0]
Expand Down Expand Up @@ -73,18 +90,38 @@ def render(self):
return self.cache.get(self.cached_name)
else:
image_str = StringIO.StringIO()
# not much other supports than png, yet works
self.pil.save(image_str, 'png')
ext = self.extension
self.pil.save(image_str, ext, **settings.IMAGEFIT_FORMAT_SETTINGS.get(ext, {}))
return image_str.getvalue()

@property
def extension(self):
ext = os.path.splitext(self.cached_name)[1].lower()

try:
fmt = PilImage.EXTENSION[ext]
except KeyError:
PilImage.init()
try:
fmt = PilImage.EXTENSION[ext]
except KeyError:
fmt = "JPEG"
#raise KeyError(ext) # unknown extension
if not fmt:
fmt = "JPEG"

print(fmt)
return fmt

def save(self):
"""
Save the image to the cache if provided and not cached yet.
"""
if self.cache and not self.is_cached:
image_str = StringIO.StringIO()
# not much other supports than png, yet works
self.pil.save(image_str, 'png')
ext = self.extension
self.pil.save(image_str, ext, **settings.IMAGEFIT_FORMAT_SETTINGS.get(ext, {}))
self.cache.set(self.cached_name, image_str.getvalue())
image_str.close()

Expand Down
11 changes: 11 additions & 0 deletions imagefit/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
from django.core.cache import get_cache
from django.utils.http import http_date

from django.http import Http404, HttpResponse, HttpResponseNotModified
from django.views.static import was_modified_since

from imagefit.conf import settings
from imagefit.models import Image, Presets

import os
import stat


cache = get_cache(settings.IMAGEFIT_CACHE_BACKEND_NAME)
Expand All @@ -33,6 +37,13 @@ def resize(request, path_name, format, url):
url = url[1:]
# generate Image instance
image = Image(path=os.path.join(prefix, url))
if not os.path.exists(image.path):
return HttpResponse(status=404)

statobj = os.stat(image.path)
if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
statobj[stat.ST_MTIME], statobj[stat.ST_SIZE]):
return HttpResponseNotModified(mimetype=image.mimetype)

if settings.IMAGEFIT_CACHE_ENABLED:
image.cache = cache
Expand Down