mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-27 16:14:01 +00:00
121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
from __future__ import division
|
|
|
|
from wagtail.wagtailimages.utils.focal_point import FocalPoint
|
|
|
|
|
|
class CropBox(object):
|
|
def __init__(self, left, top, right, bottom):
|
|
self.left = int(left)
|
|
self.top = int(top)
|
|
self.right = int(right)
|
|
self.bottom = int(bottom)
|
|
|
|
def __getitem__(self, key):
|
|
return (self.left, self.top, self.right, self.bottom)[key]
|
|
|
|
@property
|
|
def width(self):
|
|
return self.right - self.left
|
|
|
|
@property
|
|
def height(self):
|
|
return self.bottom - self.top
|
|
|
|
@property
|
|
def size(self):
|
|
return self.width, self.height
|
|
|
|
def as_tuple(self):
|
|
return self.left, self.top, self.right, self.bottom
|
|
|
|
def __eq__(self, other):
|
|
return self.as_tuple() == other.as_tuple()
|
|
|
|
def __ne__(self, other):
|
|
return not (self == other)
|
|
|
|
def __repr__(self):
|
|
return 'CropBox(left: %d, top: %d, right: %d, bottom: %d)' % (
|
|
self.left, self.top, self.right, self.bottom
|
|
)
|
|
|
|
|
|
def crop_to_centre(image_size, crop_size):
|
|
(original_width, original_height) = image_size
|
|
(crop_width, crop_height) = crop_size
|
|
|
|
# final dimensions should not exceed original dimensions
|
|
final_width = min(original_width, crop_width)
|
|
final_height = min(original_height, crop_height)
|
|
|
|
left = (original_width - final_width) / 2
|
|
top = (original_height - final_height) / 2
|
|
|
|
return CropBox(left, top, left + final_width, top + final_height)
|
|
|
|
|
|
def crop_to_point(image_size, crop_size, focal_point):
|
|
(original_width, original_height) = image_size
|
|
(crop_width, crop_height) = crop_size
|
|
|
|
if not focal_point:
|
|
focal_point = FocalPoint(original_width / 2, original_height / 2)
|
|
|
|
# Make sure that the crop size is no smaller than the focal point
|
|
crop_width = max(crop_width, focal_point.width)
|
|
crop_height = max(crop_height, focal_point.height)
|
|
|
|
# Make sure final dimensions do not exceed original dimensions
|
|
final_width = min(original_width, crop_width)
|
|
final_height = min(original_height, crop_height)
|
|
|
|
# Get UV for focal point
|
|
focal_point_u = focal_point.x / original_width
|
|
focal_point_v = focal_point.y / original_height
|
|
|
|
# Get crop box
|
|
left = focal_point.x - focal_point_u * final_width
|
|
top = focal_point.y - focal_point_v * final_height
|
|
right = focal_point.x - focal_point_u * final_width + final_width
|
|
bottom = focal_point.y - focal_point_v * final_height + final_height
|
|
|
|
# Make sure the entire focal point is in the crop box
|
|
focal_point_left = focal_point.x - focal_point.width / 2
|
|
focal_point_top = focal_point.y - focal_point.height / 2
|
|
focal_point_right = focal_point.x + focal_point.width / 2
|
|
focal_point_bottom = focal_point.y + focal_point.height / 2
|
|
|
|
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
|
|
|
|
# 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 > original_width:
|
|
left -= right - original_width
|
|
right = original_width
|
|
|
|
if bottom > original_height:
|
|
top -= bottom - original_height
|
|
bottom = original_height
|
|
|
|
return CropBox(left, top, right, bottom)
|