🎞

プログラムでWebPファイルが“静止画”か“動画”か判定する方法

2024/01/20に公開

概要

以前より判定する方法がないか疑問を持っていました。
今回調べてみた結果、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ファイルをバイナリーエディターで確認
画像:アニメーションの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)
$1PS 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ファイルか判定

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“アニメーション画像”の判定

IF文で“静止画像”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"'
}

参考情報

まとめ

  • バイナリーモードでXMP拡張データにあるチャンクデータで「 アニメーション画像 」か判断
    先頭からByte換算すると … 「31バイト目 ~ 34バイト目 のデータ」がANIMだとアニメーション画像。
    1行16バイトで表現すると … 「“2行目 15桁目 ~ 16桁目”と“3行目 1桁目 ~ 2桁目”を結合した文字列」がANIMがアニメーション画像。
  • 上記以外の場合、「 静止画像 」と判断

関連記事

https://haretokidoki-blog.com/pasocon_powershell-startup/
https://zenn.dev/haretokidoki/articles/7e6924ff0cc960

GitHubで編集を提案

Discussion