django-imagekit/imagekit/processors/resize.py

137 lines
4.5 KiB
Python
Raw Normal View History

from imagekit.lib import Image
from .crop import SmartCrop as _SmartCrop
import warnings
2011-10-20 03:12:47 +00:00
class Resize(object):
pass
2012-02-11 01:46:16 +00:00
class Fill(object):
"""
Resizes an image , cropping it to the exact specified width and height.
2011-10-31 14:12:03 +00:00
"""
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):
"""
:param width: The target width, in pixels.
:param height: The target height, in pixels.
2011-10-31 14:12:03 +00:00
:param anchor: Specifies which part of the image should be retained
when cropping. Valid values are:
2012-02-11 01:46:16 +00:00
- Fill.TOP_LEFT
- Fill.TOP
- Fill.TOP_RIGHT
- Fill.LEFT
- Fill.CENTER
- Fill.RIGHT
- Fill.BOTTOM_LEFT
- Fill.BOTTOM
- Fill.BOTTOM_RIGHT
"""
self.width = width
self.height = height
self.anchor = anchor
def process(self, img):
cur_width, cur_height = img.size
2012-02-11 01:46:16 +00:00
horizontal_anchor, vertical_anchor = Fill._ANCHOR_PTS[self.anchor or \
Fill.CENTER]
2011-10-31 14:12:03 +00:00
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 = {
2012-01-27 12:45:22 +00:00
0: (0, self.width),
0.5: (int(x_diff), int(x_diff + self.width)),
2012-01-27 12:45:22 +00:00
1: (int(crop_x), int(resize_x)),
}[horizontal_anchor]
box_upper, box_lower = {
2012-01-27 12:45:22 +00:00
0: (0, self.height),
0.5: (int(y_diff), int(y_diff + self.height)),
2012-01-27 12:45:22 +00:00
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
2012-02-11 01:46:16 +00:00
class Crop(Fill):
def __init__(self, *args, **kwargs):
warnings.warn('`imagekit.processors.resize.Crop` has been renamed to'
'`imagekit.processors.resize.Fill`.', DeprecationWarning)
super(Crop, self).__init__(*args, **kwargs)
class Fit(object):
"""
2011-10-31 14:12:03 +00:00
Resizes an image to fit within the specified dimensions.
2011-10-20 03:12:47 +00:00
2011-10-31 14:12:03 +00:00
"""
def __init__(self, width=None, height=None, upscale=None, mat_color=None):
"""
:param width: The maximum width of the desired image.
:param height: The maximum height of the desired image.
2011-10-31 14:12:03 +00:00
:param upscale: A boolean value specifying whether the image should
be enlarged if its dimensions are smaller than the target
dimensions.
:param mat_color: If set, the target image size will be enforced and
the specified color will be used as background color to pad the image.
"""
self.width = width
self.height = height
self.upscale = upscale
self.mat_color = mat_color
def process(self, img):
cur_width, cur_height = img.size
if not self.width is None and not self.height is None:
2011-10-20 03:12:47 +00:00
ratio = min(float(self.width) / cur_width,
float(self.height) / cur_height)
else:
if self.width is None:
2011-10-20 03:12:47 +00:00
ratio = float(self.height) / cur_height
else:
2011-10-20 03:12:47 +00:00
ratio = float(self.width) / cur_width
new_dimensions = (int(round(cur_width * ratio)),
int(round(cur_height * ratio)))
if (cur_width > new_dimensions[0] or cur_height > new_dimensions[1]) or \
self.upscale:
img = img.resize(new_dimensions, Image.ANTIALIAS)
if self.mat_color:
new_img = Image.new('RGBA', (self.width, self.height), self.mat_color)
new_img.paste(img, ((self.width - img.size[0]) / 2, (self.height - img.size[1]) / 2))
2012-02-11 03:04:20 +00:00
img = new_img
return img
class SmartCrop(_SmartCrop):
def __init__(self, *args, **kwargs):
warnings.warn('The SmartCrop processor has been moved to'
' `imagekit.processors.crop.SmartCrop`, where it belongs.',
DeprecationWarning)
super(SmartCrop, self).__init__(*args, **kwargs)