プログラムでWebPファイルが“静止画”か“動画”か判定する方法
概要
以前より判定する方法がないか疑問を持っていました。
今回調べてみた結果、WebPファイルにある チャンク(Chunk)ヘッダー情報 で “静止画像” か “アニメーション画像(動画)” か判定する方法が見つかりました。
この記事のターゲット
- プログラムで WebPファイルが 静止画像 か アニメーション画像 か判定したい方
この記事はPowerShellのコマンドレットを使用して検証
対応方法
WebPファイルをバイナリモードで読み取り、「 WebPのヘッダー情報 」と「 XMP拡張データ内にあるチャンク(Chunk)のヘッダー情報 」の2点で判断する方法。
WebPファイルのヘッダー情報についての説明
ここでは、一般的なバイナリーエディターのように1行あたり16バイトで表現しています。
-
WebPファイル ヘッダー情報
1行目、先頭から12桁にあるヘッダー情報でWebPファイルか判定できます。1行目 01桁目 ~ 04桁目 :
RIFF
# WebPファイルの判定 条件1/2
1行目 05桁目 ~ 08桁目 :(その他のデータ)
1行目 09桁目 ~ 12桁目 :WEBP
# WebPファイルの判定 条件2/2 -
チャンク ヘッダー情報
続いて13桁目以降からはチャンク ヘッダー情報でWebPファイルの種類を判別できます。1行目 13桁目 ~ 16桁目 :
VP8␣
# 非可逆圧縮の静止画
VP8L
# 可逆圧縮の静止画(ロスレス)
VP8X
# XMP拡張データを含む 静止画像 or アニメーション画像
※ 上記にある「␣
」は、半角スペースを表す。 -
チャンク データ情報
チャンク ヘッダーがVP8X
のWebPファイルは、2行目以降にあるXMP拡張データを参照する事で、
アニメーションのWebPファイルか判定が可能です。2行目 15桁目 ~ 16桁目 :
ANIM
# アニメーションのWebPファイル
+
3行目 01桁目 ~ 02桁目
画像:アニメーションのWebPファイルをバイナリーエディターで確認
プログラム(PowerShellのコマンド)でデータを解析してみる
PowerShellコマンドで確認
実際にアニメーションのWebPファイルをバイナリーモードで読み取ってヘッダー情報を確認してみます。
なお、PowerShellでバイナリー情報が表示できる「Format-Hex
」コマンドレットを使用。
# バイナリモードでアニメーションのWebPファイルを読み取る
PS D:\Downloads> [System.Object[]]$webp_hex_ascii = (Format-Hex -Path .\animation.webp | Select-Object Ascii)
PS D:\Downloads>
# ヘッダー情報を表示
PS D:\Downloads>
PS D:\Downloads> $webp_hex_ascii[0].Ascii
RIFF$1� WEBPVP8X
PS D:\Downloads>
# 1行目 01桁目 ~ 04桁目:WebPファイルの判定 条件1/2
PS D:\Downloads> $webp_hex_ascii[0].Ascii.ToString().Substring(0, 4)
RIFF
# → 条件1/2 に合致。
PS D:\Downloads>
# 1行目 05桁目 ~ 08桁目:(その他のデータ)
PS D:\Downloads> $webp_hex_ascii[0].Ascii.ToString().Substring(4, 4)
$1�
PS D:\Downloads>
# 1行目 09桁目 ~ 12桁目:WebPファイルの判定 条件2/2
PS D:\Downloads> $webp_hex_ascii[0].Ascii.ToString().Substring(8, 4)
WEBP
# → 条件2/2 に合致。1/2 と 2/2 の結果でWebPファイルである事を確認。
PS D:\Downloads>
# 1行目 13桁目 ~ 16桁目:拡張データの有無を判定
PS D:\Downloads> $webp_hex_ascii[0].Ascii.ToString().Substring(12, 4)
VP8X
# → 'VP8X' となり拡張データを含むWebPファイルである事を確認。
PS D:\Downloads>
# 2行目 15桁目 ~ 16桁目 + 3行目 1桁目 ~ 2桁目:アニメーションのWebPファイルか判定
PS D:\Downloads> [System.String]$animation_chunk = $webp_hex_ascii[1].Ascii.ToString().Substring(14, 2) + $webp_hex_ascii[2].Ascii.ToString().Substring(0, 2)
PS D:\Downloads>
PS D:\Downloads> $animation_chunk
ANIM
# → 'ANIM' となりアニメーションのWebPファイルである事を確認。
PS D:\Downloads>
コマンド結果をふまえてIF文で判定
WebPファイルか判定
[System.Object[]]$webp_hex_ascii = (Format-Hex -Path .\animation.webp | Select-Object Ascii)
if (($webp_hex_ascii[0].Ascii.ToString().Substring(0, 4) -eq 'RIFF') -and
($webp_hex_ascii[0].Ascii.ToString().Substring(8, 4) -eq 'WEBP')) {
# WebPファイル形式の場合
Write-Host 'Is "WebP file"'
}
変換が正しくできているという前提なのであれば、上記のようにわざわざバイナリーでヘッダー情報を確認しなくとも拡張子が「webp」か判定した方がはやい。
“静止画像”or“アニメーション画像”の判定
# バイナリーデータで読み取る[3行分(48バイト)を抽出]
[System.Object[]]$webp_hex_ascii = (Format-Hex -Path .\animation.webp -Count 48 | Select-Object Ascii)
# チャンクデータより判定
[System.String]$chunk_header = $webp_hex_ascii[0].Ascii.ToString().Substring(12, 4)
[System.String]$chunk_data = $webp_hex_ascii[1].Ascii.ToString().Substring(14, 2) + $webp_hex_ascii[2].Ascii.ToString().Substring(0, 2)
if (($chunk_header -eq 'VP8X') -and
($chunk_data -eq 'ANIM')) {
# アニメーション画像である
Write-Host 'Is "Animation image"'
}
else {
# 静止画像である
Write-Host 'Is "Still image"'
}
参考情報
-
普段よく使用している画像編集ソフト「GIMP」でWebP変換する際に指定できるオプション
https://docs.gimp.org/2.10/ja/gimp-images-out.html#file-webp-save -
WebPファイルを詳しく解説している記事
https://note.com/mith_mmk/n/n31d1c81e142b -
公式ドキュメント:WebPファイル 拡張ファイル形式
https://developers.google.com/speed/webp/docs/riff_container?hl=ja#extended_file_format
まとめ
- バイナリーモードでXMP拡張データにあるチャンクデータで「 アニメーション画像 」か判断
先頭からByte換算すると … 「31バイト目 ~ 34バイト目 のデータ」がANIM
だとアニメーション画像。
1行16バイトで表現すると … 「“2行目 15桁目 ~ 16桁目”と“3行目 1桁目 ~ 2桁目”を結合した文字列」がANIM
がアニメーション画像。 - 上記以外の場合、「 静止画像 」と判断
関連記事
Discussion