
サンプル・プログラム
非可逆と可逆の両方の圧縮形式に対応しており、背景を透明にしたり画像を半透明にするアルファチャネルを備えている。可逆圧縮の場合はPNGより26%小さくなり、非可逆圧縮の場合はJPEG画像より30%小さくなるという。
ただ、まだ対応していないアプリがあるようなので、今回はWebP画像ファイルをPNG画像ファイルに変換し、WebP未対応アプリでも画像処理ができるようなツールを作ることにする。
また、今回作ったアプリを応用すれば、処理したあとのPNG画像ファイルをWebP画像ファイルに変換することもできる。もちろん、WebPやPNG以外の画像フォーマットの相互変換もできる。
ただ、まだ対応していないアプリがあるようなので、今回はWebP画像ファイルをPNG画像ファイルに変換し、WebP未対応アプリでも画像処理ができるようなツールを作ることにする。
また、今回作ったアプリを応用すれば、処理したあとのPNG画像ファイルをWebP画像ファイルに変換することもできる。もちろん、WebPやPNG以外の画像フォーマットの相互変換もできる。
画像フォーマット変換

インストールできたら、プログラム "webp2png.py" を実行してみてほしい。ファイルダイアログを表示するので、変換したいWebP画像ファイルを選択する。複数選択できる。
すると、自動的にファイル変換が始まり、同じフォルダ、同じファイル名で、拡張子を .png にしたPNG画像ファイルを保存する。変換保存できたら、変換元と変換先のファイル名をコンソールに出力する。もし保存するPNGファイルと同名ファイルが存在していれば、上書きしないでエラーメッセージを表示する。
webp2png.py
import os
import tkinter as tk
from tkinter import filedialog
try:
import cv2
import imageio
except ImportError as errmsg:
print(f"外部ライブラリをインストールしてください ... {errmsg}")
exit()
# 初期値
dialogTitle = "WebPファイルを選択してください"
filetypes = [("WebP files", "*.webp"), ("All files", "*.*")]
filenames = filedialog.askopenfilenames(title=dialogTitle, filetypes=filetypes)
# 画像フォーマット変換処理
try:
for fullname in filenames:
# 選択ファイルが存在するかどうか(バリデーション)
if os.path.exists(fullname):
# WebPファイルを読み込む
webpImage = imageio.v2.imread(fullname)
# pngファイル名を生成する
pngFullname = fullname.replace(".webp", ".png")
# 同名ファイルがあれば例外発生
if os.path.exists(pngFullname):
raise FileExistsError(f"{pngFullname} が存在します")
# png形式で保存する
else:
cv2.imwrite(pngFullname, webpImage)
# 変換結果をコンソールに出力する
print(f"{os.path.basename(fullname)} => {os.path.basename(pngFullname)}")
# 例外処理
except Exception as e:
print(f"エラーが発生しました -- {str(e)}")
メイン・プログラムでは、標準ライブラリ tkinter を使ってファイルダイアログを表示する。tkinter は、ファイルダイアログ以外にも、テキスト入力ボックスやラジオボタン、チェックボックス、メニューなどの、基本的な入出力GUIを、OSを問わずウィンドウ表示することができる。「6.3 pywebviewを使ったGUI」で紹介したブラウザベースのGUI「pywebview」を使うほどでもないとき、標準ライブラリなのでインストールの必要もないので、tkinter が重宝する。

ファイルダイアログを呼び出すには filedialog.askopenfilenames関数を利用する。第1引数にはダイアログのタイトルを、第2引数には抽出したい拡張子タイプを渡す。拡張子タイプは、タプルをリストにしたデータ形式で、[(タイトル1, 拡張子1), (タイトル2, 拡張子2),‥‥] のように記述する。ここでは、拡張子 .webp とすべての拡張子のファイルを選べるように、[("WebP files", "*.webp"), ("All files", "*.*")] とした。もし複数の画像ファイルの拡張子で抽出したいのであれば、("Image files", "*.webp;*.jpg *.png;*.bmp") のようにセミコロン ; で拡張子を並べて書けばよい。
なお、filedialog.askopenfilenames は複数のファイルを返すことができるが、filedialog.askopenfilename は1つのファイルしか選択できない。

filedialog.askopenfilenames の戻り値はファイル名(フルパス)のリストであるので、for文 を使って1つ1つ変換していく。
ファイルダイアログで選択しているので間違いはないはずだが、念には念を入れた入力バリデーションとして、os.path.exists を使って当該画像ファイルが存在していたら変換処理を進めるようにする。

まず、imageio.v2.imread を使って変換元のWebPファイルをイメージオブジェクトとして webpImage に読み込む。
OpenCVの cv2.imread を使って読み込むことができるのだが、2024年(令和6年)9月時点で、アルファチャネルを使っていると正しく読み込めないようなので、外部ライブラリ imageio を使っている。いずれ OpenCV が対応するだろう。

次に、変換元の拡張子 .webp を .png に置換し(replace)、変換先のPNG画像ファイル名とする。
変換と保存は imwrite で行う。第1引数は保存するファイル名、第2引数はイメージオブジェクトである。imwrite はファイル名の拡張子を見て、自動的に保存する画像フォーマットを判断する。

最後に変換結果をコンソールに出力する(print)。

参考として、OpenCVで扱える画像フォーマットと拡張子の対応表を掲げる。これらのフォーマットの相互変換であれば、今回のプログラムのように、画像ファイルの読み込み、変換、保存は実質2行でできる。

ファイルダイアログを呼び出すには filedialog.askopenfilenames関数を利用する。第1引数にはダイアログのタイトルを、第2引数には抽出したい拡張子タイプを渡す。拡張子タイプは、タプルをリストにしたデータ形式で、[(タイトル1, 拡張子1), (タイトル2, 拡張子2),‥‥] のように記述する。ここでは、拡張子 .webp とすべての拡張子のファイルを選べるように、[("WebP files", "*.webp"), ("All files", "*.*")] とした。もし複数の画像ファイルの拡張子で抽出したいのであれば、("Image files", "*.webp;*.jpg *.png;*.bmp") のようにセミコロン ; で拡張子を並べて書けばよい。
なお、filedialog.askopenfilenames は複数のファイルを返すことができるが、filedialog.askopenfilename は1つのファイルしか選択できない。

filedialog.askopenfilenames の戻り値はファイル名(フルパス)のリストであるので、for文 を使って1つ1つ変換していく。
ファイルダイアログで選択しているので間違いはないはずだが、念には念を入れた入力バリデーションとして、os.path.exists を使って当該画像ファイルが存在していたら変換処理を進めるようにする。

まず、imageio.v2.imread を使って変換元のWebPファイルをイメージオブジェクトとして webpImage に読み込む。
OpenCVの cv2.imread を使って読み込むことができるのだが、2024年(令和6年)9月時点で、アルファチャネルを使っていると正しく読み込めないようなので、外部ライブラリ imageio を使っている。いずれ OpenCV が対応するだろう。

次に、変換元の拡張子 .webp を .png に置換し(replace)、変換先のPNG画像ファイル名とする。
変換と保存は imwrite で行う。第1引数は保存するファイル名、第2引数はイメージオブジェクトである。imwrite はファイル名の拡張子を見て、自動的に保存する画像フォーマットを判断する。

最後に変換結果をコンソールに出力する(print)。

参考として、OpenCVで扱える画像フォーマットと拡張子の対応表を掲げる。これらのフォーマットの相互変換であれば、今回のプログラムのように、画像ファイルの読み込み、変換、保存は実質2行でできる。
画像フォーマット | 対応拡張子 |
---|---|
BMP | .bmp, .dib |
JPEG | .hpg, .jpeg, jpe |
JPEG2000 | jp2 |
PNG | .png |
WebP | .webp |
AVIF | .avif |
Portable image format | .pbm, .pgm, .ppm, .pxm, .pnm |
PFM | .pfm |
Sun rasters | .sr, .ras |
TIFF | .tiff, .tif |
OpenEXR | .exr |
Radiance HDR | .hdr, .pic |
練習問題
次回予告
Python と外部ライブラリ OpenCV を使うことで、簡単に画像の拡大・縮小を行うことができる。次回は、ブログやSNSにデジカメで撮った写真を投稿することを想定し、縦横比を保ったまま拡大・縮小するプログラムを作っていくことにする。
コラム:ラスターデータとベクターデータ

本編で紹介した OpenCV で扱うことができる画像フォーマットは、すべてラスターデータに区分される。ラスターデータとは、点状のピクセル(ドット)を縦横方向に並べたビットマップ画像を指す。
データが連続しているため、画像の一部を切り出したり、色調や階調の変換、このあと取り上げる会の検出といった OpenCV に備わっている各種画像処理を行うのに適したデータ形式である。
データが連続しているため、画像の一部を切り出したり、色調や階調の変換、このあと取り上げる会の検出といった OpenCV に備わっている各種画像処理を行うのに適したデータ形式である。
ただし、データサイズが大きくなることと、拡大するとピクセルが目立って粗くなってしまうという短所がある。

これに対し、画像を点や直線、曲線で表すベクタデータという画像データ形式がある。たとえば、TruType形式のフォントデータや、Googleマップ上にプロットする経路図はベクターデータだ。
ベクターデータは、最低限必要な情報だけあれば図形を描くことができるので、データサイズを小さくすることができ、また、画像を拡大するtきにも図形を再描画するのでピクセルが目立ってしまうようなことはない。ただし、OpenCV に備わっている各種画像処理を行うことが難しい。

画像を使う目的によって、ラスターデータとベクターデータを使い分ける必要がある。本章は、OpenCV に備わっている画像処理を中心に学んでいくので、ラスターデータを扱う。なお、OpenCV にも直線や長方形、円といった基本図形をベクターデータとして描く機能が備わっているので、興味がある方は利用してみてほしい。

これに対し、画像を点や直線、曲線で表すベクタデータという画像データ形式がある。たとえば、TruType形式のフォントデータや、Googleマップ上にプロットする経路図はベクターデータだ。
ベクターデータは、最低限必要な情報だけあれば図形を描くことができるので、データサイズを小さくすることができ、また、画像を拡大するtきにも図形を再描画するのでピクセルが目立ってしまうようなことはない。ただし、OpenCV に備わっている各種画像処理を行うことが難しい。

画像を使う目的によって、ラスターデータとベクターデータを使い分ける必要がある。本章は、OpenCV に備わっている画像処理を中心に学んでいくので、ラスターデータを扱う。なお、OpenCV にも直線や長方形、円といった基本図形をベクターデータとして描く機能が備わっているので、興味がある方は利用してみてほしい。
(この項おわり)
「7.8 PC内蔵カメラを利用する」で利用した外部ライブラリ OpenCV は、カメラ映像をキャプチャするだけでなく、さまざまな画像処理機能を備えている。そこで今回は、画像ファイルのデータフォーマットを変換するプログラムを作ってみることにする。