1
0

More than 1 year has passed since last update.

Python: 画像データからサムネイルを作成する

Posted at
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)

サムネイルを長方形にしたい場合は改造の必要がありんす:joy:

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0