| 1 |
from PIL import Image |
| 2 |
|
| 3 |
def flat( *nums ): |
| 4 |
'Build a tuple of ints from float or integer arguments. Useful because PIL crop and resize require integer points.' |
| 5 |
|
| 6 |
return tuple( int(round(n)) for n in nums ) |
| 7 |
|
| 8 |
class Size(object): |
| 9 |
def __init__(self, pair): |
| 10 |
self.width = float(pair[0]) |
| 11 |
self.height = float(pair[1]) |
| 12 |
|
| 13 |
@property |
| 14 |
def aspect_ratio(self): |
| 15 |
return self.width / self.height |
| 16 |
|
| 17 |
@property |
| 18 |
def size(self): |
| 19 |
return flat(self.width, self.height) |
| 20 |
|
| 21 |
def cropped_thumbnail(img, size): |
| 22 |
''' |
| 23 |
Builds a thumbnail by cropping out a maximal region from the center of the original with |
| 24 |
the same aspect ratio as the target size, and then resizing. The result is a thumbnail which is |
| 25 |
always EXACTLY the requested size and with no aspect ratio distortion (although two edges, either |
| 26 |
top/bottom or left/right depending whether the image is too tall or too wide, may be trimmed off.) |
| 27 |
''' |
| 28 |
|
| 29 |
original = Size(img.size) |
| 30 |
target = Size(size) |
| 31 |
|
| 32 |
if target.aspect_ratio > original.aspect_ratio: |
| 33 |
# image is too tall: take some off the top and bottom |
| 34 |
scale_factor = target.width / original.width |
| 35 |
crop_size = Size( (original.width, target.height / scale_factor) ) |
| 36 |
top_cut_line = (original.height - crop_size.height) / 2 |
| 37 |
img = img.crop( flat(0, top_cut_line, crop_size.width, top_cut_line + crop_size.height) ) |
| 38 |
elif target.aspect_ratio < original.aspect_ratio: |
| 39 |
# image is too wide: take some off the sides |
| 40 |
scale_factor = target.height / original.height |
| 41 |
crop_size = Size( (target.width/scale_factor, original.height) ) |
| 42 |
side_cut_line = (original.width - crop_size.width) / 2 |
| 43 |
img = img.crop( flat(side_cut_line, 0, side_cut_line + crop_size.width, crop_size.height) ) |
| 44 |
|
| 45 |
return img.resize(target.size, Image.ANTIALIAS) |
To add a comment, please login or register first.
Register or Login