diff options
Diffstat (limited to 'imagekit/specs.py')
-rw-r--r-- | imagekit/specs.py | 119 |
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) |