Implemented configurable crop fields

This commit is contained in:
Justin Driscoll 2009-01-08 13:37:15 -05:00
parent 8e51a21975
commit bc8c44acff
6 changed files with 28 additions and 33 deletions

View file

@ -1,11 +1,12 @@
""" Default ImageKit configuration """
from imagekit.specs import ImageSpec
from imagekit import processors
class ResizeThumbnail(processors.Resize):
width = 100
height = 75
crop = ('center', 'center')
height = 50
crop = True
class EnhanceSmall(processors.Adjustment):
contrast = 1.2

View file

@ -11,14 +11,11 @@ from imagekit import specs
class IKModelBase(ModelBase):
def __init__(cls, name, bases, attrs):
parents = [b for b in bases if isinstance(b, IKModelBase)]
if not parents:
return
user_opts = getattr(cls, 'IKConfig', None)
opts = Options(user_opts)
try:
module = __import__(opts.config_module, {}, {}, [''])
except ImportError:
@ -30,7 +27,6 @@ class IKModelBase(ModelBase):
and spec != specs.ImageSpec]:
setattr(cls, spec.name(), specs.Descriptor(spec))
opts.specs.append(spec)
setattr(cls, '_ik', opts)
@ -59,25 +55,18 @@ class IKModel(models.Model):
(self.get_absolute_url(), prop.url)
else:
return u'<a href="%s"><img src="%s"></a>' % \
(self.ik_image_field.url, prop.url)
(self._imgfield.url, prop.url)
admin_thumbnail_view.short_description = _('Thumbnail')
admin_thumbnail_view.allow_tags = True
@property
def _imgfield(self):
return getattr(self, self._ik.image_field)
def _cleanup_cache_dirs(self):
try:
os.removedirs(self.cache_path)
except:
pass
def _clear_cache(self):
for spec in self._ik.specs:
prop = getattr(self, spec.name())
prop._delete()
self._cleanup_cache_dirs()
def _pre_cache(self):
for spec in self._ik.specs:

View file

@ -5,6 +5,8 @@ class Options(object):
"""
image_field = 'image'
crop_horz_field = 'crop_horz'
crop_vert_field = 'crop_vert'
max_image_size = None
cache_dir = 'images'
save_count_as = None

View file

@ -11,34 +11,36 @@ from imagekit import *
class ImageProcessor(object):
""" Base image processor class """
@classmethod
def process(cls, image):
def process(cls, image, obj):
return image
class Resize(ImageProcessor):
width = None
height = None
crop = False # ('top', 'left')
crop = False
upscale = False
@classmethod
def process(cls, image):
def process(cls, image, obj):
cur_width, cur_height = image.size
if cls.crop:
crop_horz = getattr(obj, obj._ik.crop_horz_field, 1)
crop_vert = getattr(obj, obj._ik.crop_vert_field, 1)
ratio = max(float(cls.width)/cur_width, float(cls.height)/cur_height)
resize_x, resize_y = ((cur_width * ratio), (cur_height * ratio))
crop_x, crop_y = (abs(cls.width - resize_x), abs(cls.height - resize_y))
x_diff, y_diff = (int(crop_x / 2), int(crop_y / 2))
box_upper, box_lower = {
'top': (9, cls.height),
'center': (int(y_diff), int(y_diff + cls.height)),
'bottom': (int(crop_y), int(resize_y)),
}[cls.crop[0]]
box_left, box_right = {
'left': (0, cls.width),
'center': (int(x_diff), int(x_diff +cls.width)),
'right': (int(crop_x), int(resize_x)),
}[cls.crop[1]]
0: (0, cls.width),
1: (int(x_diff), int(x_diff + cls.width)),
2: (int(crop_x), int(resize_x)),
}[crop_horz]
box_upper, box_lower = {
0: (0, cls.height),
1: (int(y_diff), int(y_diff + cls.height)),
2: (int(crop_y), int(resize_y)),
}[crop_vert]
box = (box_left, box_upper, box_right, box_lower)
image = image.resize((int(resize_x), int(resize_y)), Image.ANTIALIAS).crop(box)
else:
@ -74,7 +76,7 @@ class Transpose(ImageProcessor):
method = 'FLIP_LEFT_RIGHT'
@classmethod
def process(cls, image):
def process(cls, image, obj):
return image.transpose(getattr(Image, cls.method))
@ -85,7 +87,7 @@ class Adjustment(ImageProcessor):
sharpness = 1.0
@classmethod
def process(cls, image):
def process(cls, image, obj):
for name in ['Color', 'Brightness', 'Contrast', 'Sharpness']:
factor = getattr(cls, name.lower())
if factor != 1.0:

View file

@ -21,10 +21,10 @@ class ImageSpec(object):
return getattr(cls, 'access_as', cls.__name__.lower())
@classmethod
def process(cls, image):
def process(cls, image, obj):
processed_image = image.copy()
for proc in cls.processors:
processed_image = proc.process(processed_image)
processed_image = proc.process(processed_image, obj)
return processed_image
@ -38,7 +38,8 @@ class Accessor(object):
if self._exists():
return
self._img = self.spec.process(Image.open(self._obj._imgfield.path))
self._img = self.spec.process(Image.open(self._obj._imgfield.path),
self._obj)
fmt = self._img.format or 'JPEG'
tmp = tempfile.TemporaryFile()

View file

@ -40,7 +40,7 @@ class TestResizeCropped(ImageSpec):
class TestPhoto(IKModel):
""" Minimal ImageModel class for testing """
image = models.ImageField(upload_to='originals')
image = models.ImageField(upload_to='images')
class IKConfig:
config_module = 'imagekit.tests'