summaryrefslogtreecommitdiffstats
path: root/imagekit/specs.py
diff options
context:
space:
mode:
Diffstat (limited to 'imagekit/specs.py')
-rw-r--r--imagekit/specs.py119
1 files changed, 119 insertions, 0 deletions
diff --git a/imagekit/specs.py b/imagekit/specs.py
new file mode 100644
index 0000000..a6832ba
--- /dev/null
+++ b/imagekit/specs.py
@@ -0,0 +1,119 @@
+""" ImageKit image specifications
+
+All imagekit specifications must inherit from the ImageSpec class. Models
+inheriting from ImageModel will be modified with a descriptor/accessor for each
+spec found.
+
+"""
+import os
+from StringIO import StringIO
+from imagekit.lib import *
+from imagekit.utils import img_to_fobj
+from django.core.files.base import ContentFile
+
+class ImageSpec(object):
+ pre_cache = False
+ quality = 70
+ increment_count = False
+ processors = []
+
+ @classmethod
+ def name(cls):
+ return getattr(cls, 'access_as', cls.__name__.lower())
+
+ @classmethod
+ def process(cls, image, obj):
+ processed_image = image.copy()
+ for proc in cls.processors:
+ processed_image = proc.process(processed_image, obj)
+ return processed_image
+
+
+class Accessor(object):
+ def __init__(self, obj, spec):
+ self._img = None
+ self._obj = obj
+ self.spec = spec
+
+ def _get_imgfile(self):
+ format = self._img.format or 'JPEG'
+ if format != 'JPEG':
+ imgfile = img_to_fobj(self._img, format)
+ else:
+ imgfile = img_to_fobj(self._img, format,
+ quality=int(self.spec.quality),
+ optimize=True)
+ return imgfile
+
+ def _create(self):
+ if self._exists():
+ return
+ # process the original image file
+ fp = self._obj._imgfield.storage.open(self._obj._imgfield.name)
+ fp.seek(0)
+ fp = StringIO(fp.read())
+ try:
+ self._img = self.spec.process(Image.open(fp), self._obj)
+ # save the new image to the cache
+ content = ContentFile(self._get_imgfile().read())
+ self._obj._imgfield.storage.save(self.name, content)
+ except IOError:
+ pass
+
+ def _delete(self):
+ self._obj._imgfield.storage.delete(self.name)
+
+ def _exists(self):
+ return self._obj._imgfield.storage.exists(self.name)
+
+ def _basename(self):
+ filename, extension = \
+ os.path.splitext(os.path.basename(self._obj._imgfield.name))
+ return self._obj._ik.cache_filename_format % \
+ {'filename': filename,
+ 'specname': self.spec.name(),
+ 'extension': extension.lstrip('.')}
+
+ @property
+ def name(self):
+ return os.path.join(self._obj._ik.cache_dir, self._basename())
+
+ @property
+ def url(self):
+ self._create()
+ if self.spec.increment_count:
+ fieldname = self._obj._ik.save_count_as
+ if fieldname is not None:
+ current_count = getattr(self._obj, fieldname)
+ setattr(self._obj, fieldname, current_count + 1)
+ self._obj.save(clear_cache=False)
+ return self._obj._imgfield.storage.url(self.name)
+
+ @property
+ def file(self):
+ self._create()
+ return self._obj._imgfield.storage.open(self.name)
+
+ @property
+ def image(self):
+ if self._img is None:
+ self._create()
+ if self._img is None:
+ self._img = Image.open(self.file)
+ return self._img
+
+ @property
+ def width(self):
+ return self.image.size[0]
+
+ @property
+ def height(self):
+ return self.image.size[1]
+
+
+class Descriptor(object):
+ def __init__(self, spec):
+ self._spec = spec
+
+ def __get__(self, obj, type=None):
+ return Accessor(obj, self._spec)