From 4e23254e73d2d921116f6b7ad399a2c905a0f0cf Mon Sep 17 00:00:00 2001 From: Matthew Tretter Date: Wed, 21 Sep 2011 19:02:18 -0400 Subject: [PATCH] Crop processor accepts anchor argument. --- imagekit/models.py | 14 ------------- imagekit/options.py | 2 -- imagekit/processors.py | 46 ++++++++++++++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/imagekit/models.py b/imagekit/models.py index 8e22975..b9ace46 100644 --- a/imagekit/models.py +++ b/imagekit/models.py @@ -16,20 +16,6 @@ from imagekit.utils import img_to_fobj # Modify image file buffer size. ImageFile.MAXBLOCK = getattr(settings, 'PIL_IMAGEFILE_MAXBLOCK', 256 * 2 ** 10) -# Choice tuples for specifying the crop origin. -# These are provided for convenience. -CROP_HORZ_CHOICES = ( - (0, _('left')), - (1, _('center')), - (2, _('right')), -) - -CROP_VERT_CHOICES = ( - (0, _('top')), - (1, _('center')), - (2, _('bottom')), -) - class ImageModelBase(ModelBase): """ ImageModel metaclass diff --git a/imagekit/options.py b/imagekit/options.py index f23683e..833dd23 100644 --- a/imagekit/options.py +++ b/imagekit/options.py @@ -35,8 +35,6 @@ class Options(object): new_name = '{0}_{1}.{2}'.format(filename, specname, extension) return os.path.join(os.path.join('cache', filepath), new_name) - crop_horz_field = 'crop_horz' - crop_vert_field = 'crop_vert' preprocessor_spec = None save_count_as = None specs = None diff --git a/imagekit/processors.py b/imagekit/processors.py index a4ae9a0..ea75b31 100644 --- a/imagekit/processors.py +++ b/imagekit/processors.py @@ -93,27 +93,51 @@ class _Resize(ImageProcessor): class Crop(_Resize): - def __init__(self, width=None, height=None): + + TOP_LEFT = 'tl' + TOP = 't' + TOP_RIGHT = 'tr' + BOTTOM_LEFT = 'bl' + BOTTOM = 'b' + BOTTOM_RIGHT = 'br' + CENTER = 'c' + LEFT = 'l' + RIGHT = 'r' + + _ANCHOR_PTS = { + TOP_LEFT: (0, 0), + TOP: (0.5, 0), + TOP_RIGHT: (1, 0), + LEFT: (0, 0.5), + CENTER: (0.5, 0.5), + RIGHT: (1, 0.5), + BOTTOM_LEFT: (0, 1), + BOTTOM: (0.5, 1), + BOTTOM_RIGHT: (1, 1), + } + + def __init__(self, width=None, height=None, anchor=None): super(Crop, self).__init__(width, height) + self.anchor = anchor def process(self, img, fmt, obj, spec): cur_width, cur_height = img.size - crop_horz = getattr(obj, obj._ik.crop_horz_field, 1) - crop_vert = getattr(obj, obj._ik.crop_vert_field, 1) + horizontal_anchor, vertical_anchor = Crop._ANCHOR_PTS[self.anchor or \ + Crop.CENTER] ratio = max(float(self.width)/cur_width, float(self.height)/cur_height) resize_x, resize_y = ((cur_width * ratio), (cur_height * ratio)) crop_x, crop_y = (abs(self.width - resize_x), abs(self.height - resize_y)) x_diff, y_diff = (int(crop_x / 2), int(crop_y / 2)) box_left, box_right = { - 0: (0, self.width), - 1: (int(x_diff), int(x_diff + self.width)), - 2: (int(crop_x), int(resize_x)), - }[crop_horz] + 0: (0, self.width), + 0.5: (int(x_diff), int(x_diff + self.width)), + 1: (int(crop_x), int(resize_x)), + }[horizontal_anchor] box_upper, box_lower = { - 0: (0, self.height), - 1: (int(y_diff), int(y_diff + self.height)), - 2: (int(crop_y), int(resize_y)), - }[crop_vert] + 0: (0, self.height), + 0.5: (int(y_diff), int(y_diff + self.height)), + 1: (int(crop_y), int(resize_y)), + }[vertical_anchor] box = (box_left, box_upper, box_right, box_lower) img = img.resize((int(resize_x), int(resize_y)), Image.ANTIALIAS).crop(box) return img, fmt