見出し画像

【Pillow】PythonでアニメーションWebPを作る

60fpsで画像を動かしたいと思ってアニメーションGIFを作ったのですが、仕様的にできずスローになるようですね。

アニメーションWebPなら実現できそうだったので、備忘録に。


そもそもWebPとは

WebP(ウェッピー)はGoogleが開発した画像形式です。
他の画像形式をいいとこ取りしたような、以下の特徴があります。

  • 画質を保ちつつ容量が軽い

  • 透過処理が可能

  • アニメーションに対応

  • 新しめの規格なので古いアプリやブラウザでは見られないことも

ライブラリのインストール

Pythonで画像処理をするためのライブラリが必要で、今回はPillowとImageioを使います。
なお、記事投稿時点の以下最新バージョンで実装します。

  • Pillow:11.0.0

  • imageio:2.36.0

pip install pillow
pip install imageio

実装方法

アニメーションWebPへの変換処理は、複数の画像を読み込んでWebPとして保存するだけなので数行で済みます。

保存時の処理にて後述の「表示時間 (duration)」のパラメータをミリ秒で設定するのですが、今回の私の目的である60fpsで表示するためには、

1000 [ミリ秒] ÷ 60 [fps] = 16.6666…

なので、16.66ミリ秒で実装します。

ちなみにこの設定で作った各フレームの表示時間は、以下のような感じで16ミリ秒と17ミリ秒が混ざって生成されました。

Frame 1: 150 ms
Frame 2: 17 ms
Frame 3: 16 ms
Frame 4: 17 ms
Frame 5: 17 ms
Frame 6: 16 ms
Frame 7: 17 ms
Frame 8: 17 ms
Frame 9: 16 ms
……

また、Frame 1は容量の削減か、生成時に同じ画像と見なされて長めに設定されたようです。

パラメータ

良く使うと思われるパラメータを箇条書きで。

  • duration
    (Integer, Float, List, Tuple) 各フレームの表示時間をミリ秒単位で指定します。各フレームで個別に設定する場合はリストまたはタプルを渡します。

  • loop
    (Integer) アニメーションのループ回数を指定します。0は無限ループ、1は1回のみ再生して停止します。デフォルトは0。

  • quality
    (Integer) 0(最低品質)から100(最高品質)までの範囲で設定が可能。デフォルトは80。

その他のパラメータは以下公式ドキュメントを参照してください。

コード

from PIL import Image
import imageio

# 読み込む画像ファイルのリスト
image_files = ["image1.png", "image2.png", "image3.png"]

# 画像を開き、リストに追加
images = [Image.open(image_file) for image_file in image_files]

# 出力ファイル名
output_file = "output_animation.webp"

# WebPとして保存
imageio.mimwrite(output_file, images, format="webp", duration=16.66, loop=1)

ちなみに、ライブラリのインストールでPillowを入れましたが、インポートするパッケージの名前はPillowではなくPILなので注意してください。

おまけコード

複数の画像からアニメーションを作る場合は大抵連番のファイル名だと思うので、連番ファイルを読み込みやすそうなコードを作りました。

from PIL import Image
import imageio

# 読み込む画像ファイルのリスト
image_files = []

# 共通連番ファイル名
file_name = "image{0}.png"

# ファイル名生成
start_num = 0 # 最初の連番ファイルの数値
end_num = 179 # 最後の連番ファイルの数値
for file in range(start_num, end_num + 1):
    image_files.append(file_name.format(str(file)))
    # ゼロパディングしてるなら下
    # image_files.append(file_name.format(str(file).zfill(3)))

# 画像を開き、リストに追加
images = [Image.open(image_file) for image_file in image_files]

# 出力ファイル名
output_file = "output_animation.webp"

# WebPとして保存
imageio.mimwrite(output_file, images, format="webp", duration=16.66, loop=1)

参考URL


いいなと思ったら応援しよう!

とよでんキングダム
サポートいただけると嬉しいです!今後の活動費として使わせていただきます。