django-imagekit/imagekit/utils.py
2012-04-19 21:33:52 -04:00

191 lines
5.2 KiB
Python

import os
import tempfile
import types
from django.db.models.loading import cache
from django.utils.functional import wraps
from imagekit.lib import Image, ImageFile
def img_to_fobj(img, format, **kwargs):
tmp = tempfile.TemporaryFile()
try:
img.save(tmp, format, **kwargs)
except IOError:
# PIL can have problems saving large JPEGs if MAXBLOCK isn't big enough,
# So if we have a problem saving, we temporarily increase it. See
# http://github.com/jdriscoll/django-imagekit/issues/50
old_maxblock = ImageFile.MAXBLOCK
ImageFile.MAXBLOCK = img.size[0] * img.size[1]
try:
img.save(tmp, format, **kwargs)
finally:
ImageFile.MAXBLOCK = old_maxblock
tmp.seek(0)
return tmp
def get_spec_files(instance):
try:
return instance._ik.spec_files
except AttributeError:
return []
def open_image(target):
target.seek(0)
img = Image.open(target)
img.copy = types.MethodType(_wrap_copy(img.copy), img, img.__class__)
return img
def _wrap_copy(f):
@wraps(f)
def copy(self):
img = f()
try:
img.app = self.app
except AttributeError:
pass
try:
img._getexif = self._getexif
except AttributeError:
pass
return img
return copy
class UnknownExtensionError(Exception):
pass
class UnknownFormatError(Exception):
pass
_pil_init = 0
def _preinit_pil():
"""Loads the standard PIL file format drivers. Returns True if ``preinit()``
was called (and there's a potential that more drivers were loaded) or False
if there is no possibility that new drivers were loaded.
"""
global _pil_init
if _pil_init < 1:
Image.preinit()
_pil_init = 1
return True
return False
def _init_pil():
"""Loads all PIL file format drivers. Returns True if ``init()`` was called
(and there's a potential that more drivers were loaded) or False if there is
no possibility that new drivers were loaded.
"""
global _pil_init
_preinit_pil()
if _pil_init < 2:
Image.init()
_pil_init = 2
return True
return False
def _extension_to_format(extension):
return Image.EXTENSION.get(extension.lower())
def _format_to_extension(format):
if format:
for k, v in Image.EXTENSION.iteritems():
if v == format.upper():
return k
return None
def extension_to_format(extension):
"""Returns the format that corresponds to the provided extension.
"""
format = _extension_to_format(extension)
if not format and _preinit_pil():
format = _extension_to_format(extension)
if not format and _init_pil():
format = _extension_to_format(extension)
if not format:
raise UnknownExtensionError(extension)
return format
def format_to_extension(format):
"""Returns the first extension that matches the provided format.
"""
extension = None
if format:
extension = _format_to_extension(format)
if not extension and _preinit_pil():
extension = _format_to_extension(format)
if not extension and _init_pil():
extension = _format_to_extension(format)
if not extension:
raise UnknownFormatError(format)
return extension
def _get_models(apps):
models = []
for app_label in apps or []:
app = cache.get_app(app_label)
models += [m for m in cache.get_models(app)]
return models
def invalidate_app_cache(apps):
for model in _get_models(apps):
print 'Invalidating cache for "%s.%s"' % (model._meta.app_label, model.__name__)
for obj in model._default_manager.order_by('-pk'):
for f in get_spec_files(obj):
f.invalidate()
def validate_app_cache(apps, force_revalidation=False):
for model in _get_models(apps):
for obj in model._default_manager.order_by('-pk'):
model_name = '%s.%s' % (model._meta.app_label, model.__name__)
if force_revalidation:
print 'Invalidating & validating cache for "%s"' % model_name
else:
print 'Validating cache for "%s"' % model_name
for f in get_spec_files(obj):
if force_revalidation:
f.invalidate()
f.validate()
def suggest_extension(name, format):
original_extension = os.path.splitext(name)[1]
try:
suggested_extension = format_to_extension(format)
except UnknownFormatError:
extension = original_extension
else:
if suggested_extension.lower() == original_extension.lower():
extension = original_extension
else:
try:
original_format = extension_to_format(original_extension)
except UnknownExtensionError:
extension = suggested_extension
else:
# If the formats match, give precedence to the original extension.
if format.lower() == original_format.lower():
extension = original_extension
else:
extension = suggested_extension
return extension