サイズを変更する前に、画像を適切にトリミングする必要があります。基本的な考え方は、サムネイル画像と同じアスペクト(幅と高さ)の比率を持つソース画像の最大の長方形の領域を決定し、サムネイルのサイズにサイズ変更する前に、その周りの余分な部分をトリミング(トリミング)することです。このようなトリミング領域のサイズと場所を計算する関数は次のとおりです。
def cropbbox(imagewidth,imageheight, thumbwidth,thumbheight):
""" cropbbox(imagewidth,imageheight, thumbwidth,thumbheight)
Compute a centered image crop area for making thumbnail images.
imagewidth,imageheight are source image dimensions
thumbwidth,thumbheight are thumbnail image dimensions
Returns bounding box pixel coordinates of the cropping area
in this order (left,upper, right,lower).
"""
# determine scale factor
fx = float(imagewidth)/thumbwidth
fy = float(imageheight)/thumbheight
f = fx if fx < fy else fy
# calculate size of crop area
cropheight,cropwidth = int(thumbheight*f),int(thumbwidth*f)
# for centering use half the size difference of the image and the crop area
dx = (imagewidth-cropwidth)/2
dy = (imageheight-cropheight)/2
# return bounding box of centered crop area on source image
return dx,dy, cropwidth+dx,cropheight+dy
if __name__=='__main__':
print("===")
bbox = cropbbox(1024,768, 128,128)
print("cropbbox(1024,768, 128,128): {}".format(bbox))
print("===")
bbox = cropbbox(768,1024, 128,128)
print("cropbbox(768,1024, 128,128): {}".format(bbox))
print("===")
bbox = cropbbox(1024,1024, 96,128)
print("cropbbox(1024,1024, 96,128): {}".format(bbox))
print("===")
bbox = cropbbox(1024,1024, 128,96)
print("cropbbox(1024,1024, 128,96): {}".format(bbox))
トリミング領域を決定したら、呼び出してから、返された画像im.crop(bbox)
を呼び出します。im.thumbnail(...)