WebPは比較的新しく作られた圧縮済み画像形式(仕様公表されたのが2010年)で
それぞれ高い圧縮率が出るとされる(公式によると同一画像の同等品質の圧縮後サイズで “前者が25-34%,後者が26%” の差)。ただ、JPEG画像に対してはMozillaが公開しているmozjpegと呼ばれるソフトウェアのjpegtran
コマンドを用いることで既存の画像に対して無劣化である程度ファイルサイズを削減することが可能となっており、圧縮率のメリットは小さくなっている。
WebPでは可逆/不可逆のいずれの圧縮モードでもアルファチャンネルに対応している。
可逆圧縮やアルファチャンネルの機能は2011年から2012年にかけて追加され、 “不可逆圧縮 + アルファチャンネル” が利用できる画像形式は他にはあまりない。
WebPをサポートするFirefox 65が2019年1月に公開され、2018年-2019年にかけてWebブラウザのサポート状況は大きく改善した。
GIMPについては、以前に外部の開発者により作られたプラグインに基づいたコードが公式に入り、標準で読み書きできるようになった。
プログラム内でWebP形式の画像を扱うには “libwebp” と呼ばれる公式提供のC言語ライブラリを用いると便利。 同ライブラリには、他形式の画像との間で変換が行えるツール(コマンド)群が付属しており、GNU/Linuxでもディストリのパッケージとして収録されている。Debian/Ubuntuでは
としてパッケージが用意されている。
可逆(ロスレス)圧縮はバージョン0.2.0以上でのみ対応しているが、2015年頃から後に公開されたバージョンのディストリであれば問題なく使える。
他の画像形式からWebP形式へ変換するためのコマンドはcwebp
となる。対応する入力形式は
となっている。
出力ファイルは-o
オプションで指定する。指定をしないと、内部で処理は行われるがその出力結果は破棄されるので注意。
不可逆の圧縮を行う場合は-q [0から100の値]
オプションを付ける。品質値は小数でも指定可。
$ cwebp -q [品質値(0-100)] /path/to/input.jpg -o /path/to/output.webp
可逆(ロスレス/無劣化)の圧縮を行う場合は-lossless
オプションを付ける。PNG画像から無劣化なままで変換する場合は下のようにする。
$ cwebp -lossless /path/to/input.png -o /path/to/output.webp
WebP形式から他の画像形式へ変換するためのコマンドはdwebp
となる。
出力形式は既定のPNG形式の他、PAM,PPM,PGM,YUVに対応している(-pam
など、形式を指定するオプションを付ける)。
このコマンドも、出力ファイルは-o
オプションで指定する。指定をしないと出力は行われない。
下はPNG形式に変換して出力する例。
$ dwebp /path/to/input.webp -o /path/to/output.png
下はPNG画像をWebP形式にまとめてロスレスで変換してPNG画像のディレクトリに書き出し、元画像の最終更新日時をWebPファイルに適用するPythonスクリプトの例。
png2losslesswebp.py
ライセンス:zlib
#! /usr/bin/python
"""
png2losslesswebp.py - convert PNG to lossless WebP.
(C) 2019-2020 kakurasan
Licensed under zlib
"""
from __future__ import print_function
import multiprocessing as mp
import os
try:
import queue
except ImportError:
import Queue as queue
import subprocess
import sys
# pylint: disable=too-few-public-methods
class Config:
"""Configuration data."""
cwebp = "/usr/bin/cwebp" # path to cwebp
options = ["-lossless", "-quiet"]
def run_cwebp(fname, root):
"""Run cwebp and copy last modified date/time from original PNG file."""
f_lower = fname.lower()
if f_lower.endswith(".png"):
infile = os.path.join(root, fname)
outfile = os.path.join(
root, "{}.webp".format(fname[:fname.rfind(".")]))
print("Converting '{}'".format(infile))
try:
subprocess.check_call(
[Config.cwebp] + Config.options + [infile, "-o", outfile],
)
except subprocess.CalledProcessError:
print("Failed to convert '{}'".format(infile))
return
st_before = os.stat(infile)
os.utime(outfile, (st_before.st_atime, st_before.st_mtime))
def worker(que):
"""Get filename and root from the queue and call run_cwebp()."""
while True:
try:
fname, root = que.get(True, 1)
run_cwebp(fname, root)
que.task_done()
except queue.Empty:
break
def main():
"""Put paths into a JoinableQueue and start processes."""
if len(sys.argv) < 2:
sys.exit("USAGE: {} [DIR...]".format(__file__))
que = mp.JoinableQueue()
for topdir in sys.argv[1:]:
for root, _, files in os.walk(topdir):
for fname in files:
que.put((fname, root))
for _ in range(mp.cpu_count()):
proc = mp.Process(target=worker, args=(que,))
proc.start()
que.join()
if __name__ == "__main__":
main()
下はその実行方法。動作にはlibwebp付属ツールが必要(cwebp
コマンドを使用する)。引数に指定するディレクトリは複数指定できる。
(指定ディレクトリ内のPNG画像をWebP形式に一括変換)
$ /path/to/png2losslesswebp.py /path/to/png/dir
PNG形式から変換したWebPファイルはoptipng
で最大限最適化をしたPNGファイルよりも更にファイルサイズが小さくなる場合が多いが、逆に大きくなるファイルもあるので注意が必要。