【Python】PillowでアニメーションGIFのリサイズ
最近アニメーションGIFを一括でリサイズすることがあり、その時のプログラムの覚書です。
01.プログラム
from PIL import Image
# アニメーションGIFを読み込む
image = Image.open("sample.gif")
# 幅と高さを取得
width, height = image.size
# アニメーションの各フレームをリサイズしてリストに格納
resize_image_list = []
for index in range(image.n_frames):
image.seek(index)
resize_image_list.append(image.resize((width // 2, height // 2)))
# アニメーションGIFとして書き出し
resize_image_list[0].save(
"resize_sample.gif",
save_all=True,
append_images=resize_image_list[1:],
loop=0,
)
02.解説
02-01.ファイルタイプ
少々、補足説明を書いていきます。
アニメーションGIFをPillowで開くと「PIL.GifImagePlugin.GifImageFile」の形式で読み込まれます。 ※jpgやbmp等は「PIL.Image.Image」
image = Image.open("sample.gif")
print(image)
<PIL.GifImagePlugin.GifImageFile image mode=P size=200x113 at 0x29888A333D0>
「PIL.GifImagePlugin.GifImageFile」は複数の「PIL.Image.Image」を内包する形式で、n_framesを参照することで枚数を確認できます。
print(image.n_frames)
50
tell()を使用することで現在参照しているフレームのインデックスを取得できます。
読み込んだ状態だと最初のフレームを指しているので0です。
print(image.tell())
0
seek()を使用することで参照フレームを変更することが出来ます。
image.seek(20)
print(image.tell())
20
imageにアクセスすると、参照フレームを「PIL.Image.Image」として扱い処理を行います。
resize_image = image.resize((100, 100))
print(resize_image)
<PIL.Image.Image image mode=P size=100x100 at 0x1BD415F7F10>
少々注意が必要なのが、アニメーションGIFを読み込み、
そのまま処理すると最初のフレームのみに処理をしてしまい、アニメーションではなくなってしまうことです。
image = Image.open("sample.gif")
print(image.tell())
print(image)
resize_image = image.resize((100, 100))
print(resize_image)
0
<PIL.GifImagePlugin.GifImageFile image mode=P size=200x113 at 0x29888A333D0>
<PIL.Image.Image image mode=P size=100x100 at 0x1BD415F7F10>
02-02.リサイズ
アニメーションGIFをリサイズする場合には、各フレームに対し処理をします。
# 幅と高さを取得
width, height = image.size
# アニメーションの各フレームをリサイズしてリストに格納
resize_image_list = []
for index in range(image.n_frames):
image.seek(index)
resize_image_list.append(image.resize((width // 2, height // 2)))
02-03.保存
アニメーションGIFとして保存し直します。
1枚目のフレームに対しsave()を使用し、append_imagesオプションで残りのフレームを指定します。
save_allで全ての画像を保存、loopでアニメーションのループ回数を指定します(0だと無限ループ)
詳細は公式ドキュメントにて → Image file formats — Pillow (PIL Fork) documentation
# アニメーションGIFとして書き出し
resize_image_list[0].save(
"resize_sample.gif",
save_all=True,
append_images=resize_image_list[1:],
loop=0,
)
追記:
出来上がったGIFが上手く表示されないときは、最適化オプション(optimize)をFalseにすることで表示できるようになる場合もあります。
# アニメーションGIFとして書き出し
resize_image_list[0].save(
"resize_sample.gif",
save_all=True,
append_images=resize_image_list[1:],
loop=0,
optimize=False,
)
以上。
Discussion