Python の Pillow ライブラリを使ったら画像リサイズが簡単に書けた

今回書いたスクリ

https://github.com/stakiran/ires

python ires.py -r 50 sample.jpg sample.png を実行すると、50% リサイズした sample_50.jpgsample_50.png を生成する感じ。

Pillow?

Python で画像を簡単に扱うライブラリ。

python-pillow/Pillow: The friendly PIL fork (Python Imaging Library) によると 4000 star くらい。

インストールは pip install Pillow でいける。

どんな感じでリサイズ書いた?

以下みたいな感じ(ブログ用に書いた断片なのでそのままでは動きません)。

from PIL import Image
from PIL import ImageFile

# 画像ファイル名から画像ハンドル?をゲットして、
img = Image.open(infilepath, 'r')

# リサイズ後のサイズを指定してリサイズ実行
w, h = 640, 480
newsize = (w, h)
resized_img = img.resize(new_size)

# リサイズした画像ハンドル?を保存する。
resized_img.save(outfilepath, 'JPEG',
    quality=100,
    optimize=True,
    progressive=True
)

「んだよ、リサイズは比率で指定できねえの?」 できる。画像ハンドラ?の size プロパティ。

img = Image.open(infilepath, 'r')

# これで元画像のサイズをゲット
w, h = img.size

# あとはよしなに

ハマったこと

JPEG でリサイズした時に「IOError: encoder error -2 when writing image file」が出た。原因は、内部で使うバッファサイズが足りてないこと。対処法は、足りる程度にバッファサイズを設定しておけばよい。

参考: How to save progressive jpeg using Python PIL 1.1.7? - Stack Overflow

def save_to_jpg(imageinst, filename):
    # バッファが小さくて
    # IOError: encoder error -2 when writing image file
    # が起きるので, テキトーにでかいバッファサイズを設定しとく.
    # from: https://stackoverflow.com/questions/6788398/how-to-save-progressive-jpeg-using-python-pil-1-1-7
    #
    # [以下調べてない]
    # - 単に最大 w, h の乗算でいい? それともさらに n 倍が必要?
    ImageFile.MAXBLOCK = max_width*max_height

    imageinst.save(filename, 'JPEG',
        quality=100,
        optimize=True,
        progressive=True
    )

width*height で正しいかは知らんけど、まあ問題起きたら対処するということで。

今回公開した irs コマンドに限って言えば、コマンドライン引数でこのバッファサイズを指定できるようにしてあるので問題無いと思う。

感想

本当に便利。

他にも色んなインタフェースが用意されてるので、初心者から上級者まで幅広く遊べるんじゃなかろうか。