Pillow 通过裁剪而不是保留纵横比来创建缩略图
Pillow create thumbnail by cropping instead of preserving aspect ratio
默认情况下,thumbnail
方法会保留纵横比,这可能会导致缩略图大小不一致。
Image.thumbnail(size, resample=3)
Make this image into a thumbnail. This method modifies the image to contain a thumbnail version of itself, no larger than the given size. This method calculates an appropriate thumbnail size to preserve the aspect of the image, calls the draft() method to configure the file reader (where applicable), and finally resizes the image.
我希望它裁剪图像,以便缩略图填满提供的整个 canvas,这样图像就不会变形。例如,Image.thumbnail((200, 200), Image.ANTIALIAS)
在 640 x 480 的图像上将以 480 x 480 裁剪到中心,然后精确缩放到 200 x 200(不是 199 或 201)。如何做到这一点?
这分两个阶段最容易做到:先裁剪,然后生成缩略图。裁剪到给定的宽高比很常见,因此在 PILLOW 中确实应该有一个功能,但据我所知没有。这是一个简单的实现,猴子修补到图像 class:
from PIL import Image
class _Image(Image.Image):
def crop_to_aspect(self, aspect, divisor=1, alignx=0.5, aligny=0.5):
"""Crops an image to a given aspect ratio.
Args:
aspect (float): The desired aspect ratio.
divisor (float): Optional divisor. Allows passing in (w, h) pair as the first two arguments.
alignx (float): Horizontal crop alignment from 0 (left) to 1 (right)
aligny (float): Vertical crop alignment from 0 (left) to 1 (right)
Returns:
Image: The cropped Image object.
"""
if self.width / self.height > aspect / divisor:
newwidth = int(self.height * (aspect / divisor))
newheight = self.height
else:
newwidth = self.width
newheight = int(self.width / (aspect / divisor))
img = self.crop((alignx * (self.width - newwidth),
aligny * (self.height - newheight),
alignx * (self.width - newwidth) + newwidth,
aligny * (self.height - newheight) + newheight))
return img
Image.Image.crop_to_aspect = _Image.crop_to_aspect
鉴于此,您可以只写
cropped = img.crop_to_aspect(200,200)
cropped.thumbnail((200, 200), Image.ANTIALIAS)
默认情况下,thumbnail
方法会保留纵横比,这可能会导致缩略图大小不一致。
Image.thumbnail(size, resample=3) Make this image into a thumbnail. This method modifies the image to contain a thumbnail version of itself, no larger than the given size. This method calculates an appropriate thumbnail size to preserve the aspect of the image, calls the draft() method to configure the file reader (where applicable), and finally resizes the image.
我希望它裁剪图像,以便缩略图填满提供的整个 canvas,这样图像就不会变形。例如,Image.thumbnail((200, 200), Image.ANTIALIAS)
在 640 x 480 的图像上将以 480 x 480 裁剪到中心,然后精确缩放到 200 x 200(不是 199 或 201)。如何做到这一点?
这分两个阶段最容易做到:先裁剪,然后生成缩略图。裁剪到给定的宽高比很常见,因此在 PILLOW 中确实应该有一个功能,但据我所知没有。这是一个简单的实现,猴子修补到图像 class:
from PIL import Image
class _Image(Image.Image):
def crop_to_aspect(self, aspect, divisor=1, alignx=0.5, aligny=0.5):
"""Crops an image to a given aspect ratio.
Args:
aspect (float): The desired aspect ratio.
divisor (float): Optional divisor. Allows passing in (w, h) pair as the first two arguments.
alignx (float): Horizontal crop alignment from 0 (left) to 1 (right)
aligny (float): Vertical crop alignment from 0 (left) to 1 (right)
Returns:
Image: The cropped Image object.
"""
if self.width / self.height > aspect / divisor:
newwidth = int(self.height * (aspect / divisor))
newheight = self.height
else:
newwidth = self.width
newheight = int(self.width / (aspect / divisor))
img = self.crop((alignx * (self.width - newwidth),
aligny * (self.height - newheight),
alignx * (self.width - newwidth) + newwidth,
aligny * (self.height - newheight) + newheight))
return img
Image.Image.crop_to_aspect = _Image.crop_to_aspect
鉴于此,您可以只写
cropped = img.crop_to_aspect(200,200)
cropped.thumbnail((200, 200), Image.ANTIALIAS)