From 79b61706313bff52b5a29e3536a609fe6635c52d Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Mon, 27 Jul 2015 11:58:08 +0100 Subject: [PATCH] Use rect class in fill operation --- wagtail/wagtailimages/image_operations.py | 41 ++----------- wagtail/wagtailimages/rect.py | 73 +++++++++++++++++++++++ 2 files changed, 78 insertions(+), 36 deletions(-) diff --git a/wagtail/wagtailimages/image_operations.py b/wagtail/wagtailimages/image_operations.py index d1d90da7e..3e6201629 100644 --- a/wagtail/wagtailimages/image_operations.py +++ b/wagtail/wagtailimages/image_operations.py @@ -1,9 +1,9 @@ from __future__ import division import inspect -import math from wagtail.wagtailimages.exceptions import InvalidFilterSpecError +from wagtail.wagtailimages.rect import Rect class Operation(object): @@ -118,48 +118,17 @@ class FillOperation(Operation): crop_y = fp_y - (fp_v - 0.5) * crop_height # Convert crop box into rect - left = crop_x - crop_width / 2 - top = crop_y - crop_height / 2 - right = crop_x + crop_width / 2 - bottom = crop_y + crop_height / 2 + rect = Rect.from_point(crop_x, crop_y, crop_width, crop_height) # Make sure the entire focal point is in the crop box if focal_point is not None: - if left > focal_point.left: - right -= left - focal_point.left - left = focal_point.left - - if top > focal_point.top: - bottom -= top - focal_point.top - top = focal_point.top - - if right < focal_point.right: - left += focal_point.right - right - right = focal_point.right - - if bottom < focal_point.bottom: - top += focal_point.bottom - bottom - bottom = focal_point.bottom + rect = rect.move_to_cover(focal_point) # Don't allow the crop box to go over the image boundary - if left < 0: - right -= left - left = 0 - - if top < 0: - bottom -= top - top = 0 - - if right > image_width: - left -= right - image_width - right = image_width - - if bottom > image_height: - top -= bottom - image_height - bottom = image_height + rect = rect.move_to_clamp(Rect(0, 0, image_width, image_height)) # Crop! - willow.crop((math.floor(left), math.floor(top), math.ceil(right), math.ceil(bottom))) + willow.crop(rect.round()) # Get scale for resizing # The scale should be the same for both the horizontal and diff --git a/wagtail/wagtailimages/rect.py b/wagtail/wagtailimages/rect.py index 04ac061e2..e264e3081 100644 --- a/wagtail/wagtailimages/rect.py +++ b/wagtail/wagtailimages/rect.py @@ -1,5 +1,7 @@ from __future__ import division +import math + class Vector(object): def __init__(self, x, y): @@ -86,6 +88,77 @@ class Rect(object): # Included for backwards compatibility return self.left, self.top, self.right, self.bottom + def clone(self): + return type(self)(self.left, self.top, self.right, self.bottom) + + def round(self): + """ + Returns a new rect with all attributes rounded to integers + """ + clone = self.clone() + + # Round down left and top + clone.left = int(math.floor(clone.left)) + clone.top = int(math.floor(clone.top)) + + # Round up right and bottom + clone.right = int(math.ceil(clone.right)) + clone.bottom = int(math.ceil(clone.bottom)) + + return clone + + def move_to_clamp(self, other): + """ + Moves this rect so it is completely covered by the rect in "other" and + returns a new Rect instance. + """ + other = Rect(*other) + clone = self.clone() + + if clone.left < other.left: + clone.right -= clone.left - other.left + clone.left = other.left + + if clone.top < other.top: + clone.bottom -= clone.top - other.top + clone.top = other.top + + if clone.right > other.right: + clone.left -= clone.right - other.right + clone.right = other.right + + if clone.bottom > other.bottom: + clone.top -= clone.bottom - other.bottom + clone.bottom = other.bottom + + return clone + + def move_to_cover(self, other): + """ + Moves this rect so it completely covers the rect specified in the + "other" parameter and returns a new Rect instance. + """ + other = Rect(*other) + clone = self.clone() + + if clone.left > other.left: + clone.right -= clone.left - other.left + clone.left = other.left + + if clone.top > other.top: + clone.bottom -= clone.top - other.top + clone.top = other.top + + if clone.right < other.right: + clone.left += other.right - clone.right + clone.right = other.right + + if clone.bottom < other.bottom: + clone.top += other.bottom - clone.bottom + clone.bottom = other.bottom + + return clone + def __iter__(self): return iter((self.left, self.top, self.right, self.bottom))