import imghdr
from io import BytesIO
from PIL import Image
def create_square_thumb(
binary_of_fullimage: bytes,
thumb_size: tuple, # サムネイルのサイズ(x, y)を指定する。 例:(100, 100)
thumb_quality: int, # サムネイルの品質を指定する。↓をご参照
) -> bytes:
"""
画像データのbytesから、指定したサイズと品質でサムネイルを作ってbytesで返す。
[thumb_quality: int]
フィルタ ダウンスケーリング品質 アップスケーリング品質 パフォーマンス
PIL.Image.NEAREST ⭐⭐⭐⭐⭐
PIL.Image.BOX ⭐ ⭐⭐⭐⭐
PIL.Image.BILINEAR ⭐ ⭐ ⭐⭐⭐
PIL.Image.HAMMING ⭐⭐ ⭐⭐⭐
PIL.Image.BICUBIC ⭐⭐⭐ ⭐⭐⭐ ⭐⭐
PIL.Image.LANCZOS ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐
"""
# 画像データかどうか及び画像の場合その情報
image_type = imghdr.what(None, h=binary_of_fullimage)
if image_type is None:
return None # 画像データじゃない
with Image.open(BytesIO(binary_of_fullimage)) as im:
# 画像の中央をできるだけ大きいサイズで切り抜く
image_square_cropped = get_square_cropped_pillow_image(im.copy())
# 切り抜きを、指定したサイズと品質でリサイズする
image_square_cropped.thumbnail(thumb_size, thumb_quality)
dummy_thumb: BytesIO = BytesIO() # サムネイルを一時保存するための入れ物
# 一時的に保存(スマホ写真データなど、exif情報がある場合にも対応)
image_square_cropped.save(
dummy_thumb, format=image_type
) if "exif" not in im.info else image_square_cropped.save(
dummy_thumb, exif=im.info["exif"], format=image_type
)
# サムネイルのバイナリデータを返す
return dummy_thumb.getbuffer().tobytes()
def get_square_cropped_pillow_image(im: Image) -> Image:
"""
画像の縦・横 短い方に合わせて、画像の中央を正方形に切り抜いて返す。
"""
square_size = min(im.size)
width, height = im.size
box = None
if width > height:
top = 0
bottom = square_size
left = (width - square_size) / 2
right = left + square_size
box = (left, top, right, bottom)
else:
left = 0
right = square_size
top = (height - square_size) / 2
bottom = top + square_size
box = (left, top, right, bottom)
return im.crop(box)
サムネイルを長方形にしたい場合は改造の必要がありんす