PR

PNGのメタデータを理解する【Python解説あり】

PNGファイルのメタデータ
この記事は約12分で読めます。

PNGなどの画像ファイルには「メタデータ」と呼ばれる付加情報がついていることがあります。

たとえば、NovelAIやStable Diffusionなどの画像生成AIサービスで生成した画像ファイルには、「どのような設定で画像を生成したのか」という情報が付けられています。

NovelAIの生成画像に付けられているメタデータの例

このような情報を確認できれば、気に入った画像を生成できたときのプロンプトや設定情報を参考にできるのでとても便利です。
「メタデータ」がどのようなものかを理解することで、活用の幅が広がります。

本記事ではPNGファイルのメタデータがどのような構造になっているのかを初心者でもわかるように丁寧に解説します。
後半では、実際にPNGファイルからメタデータを抜き出すPythonコードも解説していますので、アプリやツールを作ろうとしている人にも役立つと思います。

この記事はこんな人におすすめ
  • PNGファイルのメタデータについて知りたい
  • メタデータの仕様について詳しく理解したい
  • メタデータを確認するツールを作りたい

メタデータとは

まずはざっくりと「メタデータ」とはどのようなものかを知りましょう。

データを説明するデータが「メタデータ」

らん
らん

早口言葉みたいでよくわからん…どういうこと?

画像ファイルにおいて、メインとなるデータはもちろん「画像データ」です。
ですが、よく考えてみると「画像データ」は画像それ自体の他にもさまざまな情報を持っているはずです。

たとえば、あなたが旅行に出かけて、美味しそうな料理の写真を取ったとしましょう。
そのとき記録に残したい情報は「料理の画像」以外にもいろいろあるはずです。

らん
らん

撮影した日時とか場所とかね💡

るん
るん

カメラの機種や設定も残せたら便利ですよね♪

こうしたさまざまな情報は「画像データ」を説明するデータといえます。これが「メタデータ」なのです。

画像ファイルには「メタデータ」を付与できる
画像ファイルにはさまざまな「メタデータ」が付与できる

画像生成AIとメタデータ

Stable DiffusionやNovelAIなどの画像生成AIでは、画像を生成するときにさまざまな設定を駆使しています。プロンプトを工夫したり、ステップ数を調整したり、試行錯誤しながら良い画像を生み出します。
これらの情報が画像ファイルに付けられていたら、あとから見返すことができるのでととても便利ですよね。

これを実現する仕組みが「メタデータ」なのです。
実際にNovelAIではダウンロードした生成画像にはこのようなメタデータが付与されています。

NovelAIの生成画像に付けられているメタデータの例
るん
るん

「プロンプト」や「ステップ」「スケール」など多くの情報が付いてます

メタデータの確認方法

Windowsであればファイルを右クリックして「プロパティ」を開くと、いくつかのメタデータを見ることができます。たとえば、画像の幅や高さなどの情報です。ですが、すべての情報がここで確認できるわけではありません

すべてのメタデータを確認するためには、基本的には専用のツールが必要になります。

Stable DiffusionやNovelAIにはメタデータを確認する機能が備わっているので、それらを使って確認することができます。

Stable Diffusion(WebUI)での確認方法

Stable Diffusion Web UI(AUTOMATIC1111)では、「PNG Info」タブで画像を読み込ませることでメタデータを確認できます。

Stable Diffusion WebUIで画像ファイルのメタデータを確認できる

NovelAIでの確認方法

NovelAIの画像ファイル確認ページに画像を読み込ませることで、メタデータを確認することができます。

NovelAIで画像ファイルのメタデータを確認できる

ここまでがメタデータの概要です。
さらに詳しくメタデータについて知りたい人は次に進みましょう♪

PNGのメタデータ

では、ここから先はもう少し突っ込んで「メタデータ」について理解していきましょう。

ここまで単に「画像ファイル」と言ってきましたが、「画像ファイル」にもさまざまな形式があります。代表的なものは「PNG(ピング)ファイル」と「JPEG(ジェイペグ)ファイル」です。

るん
るん

ファイルの拡張子が「.png」がPNGファイル、「.jpg」や「.jpeg」となっているのがJPEGファイルです

本記事では「PNGファイル」のメタデータについて解説していきたいと思います。

PNGファイルの大まかな構造

PNGファイルは「シグネチャ」と複数の「チャンク」で構成されています。

「シグネチャ」は「これはPNGファイルだよ」ということを識別するための貼り紙のようなものです。

そして「チャンク」はひとかたまりのデータのことです。さまざまなデータが格納されている「箱」をイメージするといいでしょう。PNGファイルという大きな箱に「チャンク」という小さな箱が詰まっているようなものと考えてください。

PNGファイルは「シグネチャー」と「チャンク」で構成される

「シグネチャ」と「チャンク」

では、具体的に「シグネチャ」と「チャンク」の中身を見ていきましょう。

シグネチャ

「シグネチャ」は「PNGファイル」であることの目印のようなもので、ファイルの先頭に存在しています。

実際のデータは「8byte」で、16進数で表すと「89 50 4e 47 0d 0a 1a 0a」というデータです。

らん
らん

このデータが付いてたらPNGファイルってことね💡

チャンク

「チャンク」は、その中身のデータによっていくつかの種類があり、これを「チャンクタイプ」といいます。チャンクタイプはアルファベット4文字で表現されます。

PNGファイルに必須のチャンクタイプはIHDR、IDATA、IENDの3つです。
IHDRは必ず先頭にあって、IENDは必ず末尾にあります。IDATというのは画像のデータです。

つまり、PNGファイルの全体的な構造は以下のようになります。

PNGファイルの全体的な構造
らん
らん

ふーん…で、メタデータはどこにあるの?

メタデータもチャンクとして付与されています。PNGファイルに「tEXt」や「iTXt」というチャンクタイプがあれば、それがメタデータです。

「チャンク」の構造

PNGでは「チャンク」が重要な役割を果たしているので、その構造を理解することがとても大切です。
「チャンク」の中身を詳しく見てみましょう。

どのようなチャンクでも必ずこのような構成になっています。

名前サイズ説明
Length4byteChank Dataのサイズ
Chank Type4byteチャンクの種類
Chank Data0byte以上データ本体
CRC4byteエラー検出のための情報
「チャンク」の構成
[PNGファイル] チャンクの構造
るん
るん

ポイントは「チャンクデータ」のサイズが可変なこと

チャンクに格納されているデータのサイズはチャンクによって変わります。よって、あらかじめ何byte分のデータを読み出せばいいかがわからないといけません。

そのために「Length」に「このチャンクのデータサイズは何byteだよ」という情報が格納されているわけです。

主なチャンクタイプ

IHDRチャンク

一番始めに来るチャンク。ここからチャンクが始まるよという目印になります。
Chunk Data部分には、画像の横幅や縦幅、ビット深度といった画像の基本情報が格納されています。

[PNGファイル] IHDRチャンク

IENDチャンク

末尾に来るチャンク。ここでチャンクはおしまいという目印。ただの目印のチャンクなので、Chunk Dataには何も入っていません。

[PNGファイル] IENDチャンク

IDATチャンク

画像データが格納されているチャンクです。画像データは複数のIDATチャンクに分割されていることもあります。

[PNGファイル] IDATチャンク

tEXtチャンク

メタデータが文字情報として格納されています。

Stable DiffusionやNovelAIの生成画像では、このtEXtチャンクにプロンプトなどの各種情報が入っています。

Chunk Dataはテキストデータなので基本的にはそのまま読み出せばいいのですが、ポイントはこのテキストデータは情報の種類を示す「キーワード」から始まることです。
そしてその後、「ヌル文字」で区切られて「テキスト」が続きます。

[PNGファイル] tEXtチャンク

キーワードには以下のものが事前定義されていますが、ここにないプライベートキーワード(1文字以上、80文字未満)を用いてもよいことになっています。

キーワード意味
Title画像の短い(1 行)タイトルまたはキャプション
Author画像の作成者の名前
Description画像の説明 (長い場合もあります)
Copyright著作権表示
Creation Time元画像の作成時間
Softwareイメージの作成に使用したソフトウェア
Disclaimer法的免責事項
Warningコンテンツの性質に関する警告
Sourceイメージの作成に使用されたソースデバイス
Commentその他のコメント
tEXtのキーワードの種類

PNGのメタデータをPythonで抜き出す

ここからはプログラミングを行ってPNGファイルからメタデータを抜き出すことで、さらに理解を深めます。

画像ファイルは、NovelAIという画像生成AIサービスで生成した以下のpngファイルを使います。実際にダウンロードして使っていただいて構いません。

PNG構造を理解するための画像ファイル
PNG構造を理解するためのサンプル画像ファイル

プログラミング言語としては「Python」を使います。
最初に全コードを載せておきます。

with open("kimono-girl.png", "rb") as bin:
    # 最初の8バイトはPNGであることのシグネチャ(89 50 4E 47 0D 0A 1A 0A)
    signature = bin.read(8)
    print(signature)

    # チャンクの読み出し
    while True:
        # Length データのサイズ
        data_len_b = bin.read(4)
        data_len = int.from_bytes(data_len_b, "big")

        # Chunk Type チャンクの種類
        chunk_type_b = bin.read(4)
        chunk_type = chunk_type_b.decode()

        print(f"{chunk_type} : {data_len} byte")

        # Chunk Data データ
        data_b = bin.read(data_len)
        if chunk_type == "tEXt":
            data = data_b.decode()
            print(data)
            print(data.split("\0"))

        # CRC
        crc_b = bin.read(4)

        if chunk_type == "IEND":
            break
るん
るん

順番に解説していきますね♪

最低限のPythonの文法は知っているという前提で解説していきますのでご了承ください。

with open("kimono-girl.png", "rb") as bin:

まず、pngファイルをバイナリ形式で開きます。open()の第一引数には画像ファイルのパスを指定してください。

画像ファイルは人間が見てもよくわからない数字の列が並んで構成されていますが、この並びには意味があります。
つまり、前から順番にここがシグネチャで、ここがチャンクで…というように並んでいます。

そのためバイナリ形式でファイルを開いて、前から順番にデータを読み出して解釈していきます。

signature = bin.read(8)
print(signature)

bin.read(n)で読み込み位置を進めながら次のnバイトを読み出すことができます。

PNGファイルは、最初の8バイトが「シグネチャ」なので、まずは最初の8バイトを読み込んでいます。
読み込んだファイルがPNGファイルかどうかをチェックしたい場合はこのシグネチャをチェックすればよいです。(このコードでは、特にチェックしていません)

while True:

さて、ここからファイルの終わりまでは「チャンク」が繰り返し続きます。なのでwhile文でループさせます。

# Length データのサイズ
data_len_b = bin.read(4)
data_len = int.from_bytes(data_len_b, "big")

# Chunk Type チャンクの種類
chunk_type_b = bin.read(4)
chunk_type = chunk_type_b.decode()

print(f"{chunk_type} : {data_len} byte")

チャンクの構造を思い出してください。
まず、4ビットのLength、4ビットのChunk Typeが並んでいます。

[PNGファイル] チャンクの構造

ポイントはその後に何ビットのデータが続くかはこの「Length」から判断できるということです。

次にデータ本体を読み出します。

# Chunk Data データ
data_b = bin.read(data_len)
if chunk_type == "tEXt":
    data = data_b.decode()
    print(data)

チャンクの種類によって処理する内容は変わるのですが、「tEXt」(テキストデータ)だったらprint文で出力させてみましょう。

[PNGファイル] tEXtチャンクの文字列をそのまま出力
らん
らん

なんか途中に変な文字があるよ…

るん
るん

キーワードとテキストの「区切り文字(ヌル文字)」です

キーワードとテキストはヌル文字で区切られていて、キーワードやテキスト文字列内にはヌル文字を含めてはならないことになっています。したがって、ヌル文字できれいに分割することができます。

print(data.split("\0"))

最後は、CRC(4バイト)を取り出します。これについては特にやることはありません。

# CRC チェックサム
crc_b = bin.read(4)

これでひとつのチャンクの読み込みは完了ですが、次のチャンクに行く前に大切なことがあります。
最後のチャンクかどうかをチェックすることです。
最後ならwhileループを終了させなければいけませんね。

るん
るん

最後のチャンクかどうかはどう判断すればいいでしょう?

らん
らん

えーと…最後は必ず「IEND」チャンクだったよね💡

そうです。チャンクはIENDチャンクが末尾になる決まりでしたね。
よって、チャンクタイプがIENDかどうかをチェックすればOKです。

if chunk_type == "IEND":
    break

まとめ

PNGファイルには、その画像を説明するデータである「メタデータ」が付与されていることがあります。
画像生成AIの生成画像では「プロンプト」や「ステップ」「シード値」などの情報を付与できるため、のちのちの画像生成で役立てることもできます。

PNGファイルは「シグネチャ」と複数の「チャンク」という比較的シンプルな構造をしています。
「チャンク」の仕様さえ理解してしまえば、Pythonなどのプログラムでメタデータを抜き出すことは難しくはありません。

らん
らん

実際にプログラミングしたらよく理解できたよ✨

るん
るん

便利なツール作成にもぜひチャレンジしてみてくださいね♪

NovelAIの生成画像のメタデータについてさらに詳しく知りたい人はこちらもぜひどうぞ!

プロフィール
この記事を書いた人
千鳥 るん | Chidori Run

画像生成AIで思い通りのイラストを描くためのノウハウを試行錯誤で模索しています。IT企業でAI戦略に関わっていたこともあるAIエンジニアです。大学生の頃から趣味でイラストを描いていましたが、仕事が忙しくなり一旦筆を置きました。最近、NovelAIと出会ってまたお絵描きへの情熱を取り戻しています。

千鳥るんをフォローする
NovelAIStable Diffusionプログラミング
スポンサーリンク
シェアする
千鳥るんをフォローする

コメント