無知を晒す

ふだんの出来事はこっちに書いてます: http://tana.hatenablog.com

どれが最新のファイルかわからなくなったことはないですか? XMPでどれが最新か見分けませんか?

こんにちは.私は id:side_tana.これは ミクシィグループ Advent Calendar 2018 - Qiita 9 日目の記事です.*1

qiita.com

日々を過ごしていると,目の前に複数のファイルがあり,そのどれが最新かわからなくて困る, といった場面に出くわします.皆さんも経験があるのではないでしょうか?

f:id:side_tana:20181209204244p:plain
画像はイメージです

特に雑にファイルをコピーしたり,何らかのサービスやツールを経由してデータをやりとりしているとファイルシステムのタイムスタンプも役に立たず途方にくれることもしばしばだと思います.*2

で,最近 Adobe XMP というファイルにメタデータを付与するための仕様について知る機会があったので,今回は Adobe XMP のデータを元に最新のファイルを見つけてみたいと思います.

なお Adobe XMP と書いているように Adobe が中心となって策定している仕様を利用しますので,全てのファイルで有効な方法ではありません.

PSD ファイルのメタデータを確認してみる

PSD に含まれる XMP メタデータについては,Photoshop で簡単に確認ができます.対象のファイルを Photoshop で開き,ファイルメニューからファイル情報を選択し,開いた画面の左側にあるリストから「Rawデータ」を選択すると,以下のような画面が表示されます.

f:id:side_tana:20181209204731p:plain

これが XMP で表現されたメタデータになります.こうして XMP のデータを眺めているとこんな箇所が出て来ます.

   <xmpMM:History>
    <rdf:Seq>
     <rdf:li
      stEvt:action="created"
      stEvt:instanceID="a8ae5a69-eb77-4089-95e2-f42d2b3de612"
      stEvt:when="2018-08-07T23:37:16.842+09:00"
      stEvt:softwareAgent="XD"/>
     <rdf:li
      stEvt:action="saved"
      stEvt:instanceID="f6d3e01d-15ed-47a9-92a1-2ea2301b2a71"
      stEvt:when="2018-09-23T23:01:14.891+09:00"
      stEvt:softwareAgent="XD"/>
    </rdf:Seq>
   </xmpMM:History>

いかにもそれらしいですね.この xmpMM:History 要素ですが,仕様上は XMP Media Management namespace のプロパティとして以下のように定義されています.

High-level actions that resulted in this resource. It is intended to give human readers a description of the steps taken to make the changes from the previous version to this one. The list should be at an abstract level; it is not intended to be an exhaustive keystroke or other detailed history. The description should be sufficient for metadata management, as well as for workflow enhancement.

ファイルの更新履歴のようなので,これで最新のファイルを発見できそうです.

PSD ファイルから XMP メタデータを取り出してみる

XMPメタデータを読み取るために,我々*3はまず PSD のヘッダフォーマットについて理解する必要があります.

PSD ファイルは8BPS から始まる26バイトのヘッダブロックを持ちます.次に可変長のカラーモードデータを持ち,そのあとにイメージリソースが続きます.イメージリソースには複数のブロックが含まれ,各ブロックは8BIMから始まり,2バイトのイメージリソースID,可変長の name フィールド,4バイトのイメージリソースデータのバイト長,実際のイメージリソースデータ,と続きます.

また,XMPメタデータはイメージリソースブロックに含まれ,イメージリソースID は 1060,nameフィールドは 2バイトの null であることがドキュメントで示されています.これらの情報を元に実装すると,<?xpacket?> で囲まれた xml ドキュメントを取り出すことができます. *4

f:id:side_tana:20181209210045p:plain
man ascii は便利 #宣言的知識

こうして xmp メタデータを取り出すことができればあとはこっちのものです.実際に複数の PSD ファイルの履歴をまとめて表示するページを用意しました*5.どうぞお手元の PSD ファイルをドラッグ&ドロップで読み込ませて見てください.(全ての処理はブラウザ上で完結しているので,外部への送信などはしていません.)

XmpMmHistoryViewer


f:id:side_tana:20181209215250g:plain

こうして メタデータから最新の編集時刻を見つけ出し,最新版を見つけ出すことができました.*6

おわりに

今回は XMP メタデータについて紹介し、実際にその一部である XMP Media Management namespace に含まれる ResourceEvent を利用してみました。XMP には他にもキャンバスサイズやサムネイル、使用しているフォントリストなど、使いがいのあるデータが色々と埋まっています。一方で,XMP は必ずこのデータを含む,と言った制約はほぼないため,欲しいデータが含まれているかどうかは実際に手を動かして見ないとわからないのが難しいところですね.

ぜひ年末のファイルシステムの大掃除に役立てたり、正月休みの空いた時間に身の回りをファイルを手にとってメタデータを取り出してみたりして楽しんでください。

*1:昨日の記事は @manji602 さんで ユーザにやさしいサービスを作るための3つのポイント - 問い合わせはサービス改善への近道 - - Qiitaでした.

*2:と書いておいてなんですが筆者はここしばらくソースコード以外のデータを触る業務から離れているためこう言った経験はめっきり減りました.と思ったけど Google Spreadsheet が野放図に複製されてどれが最新かわからなくなる地獄みたいなのあったな,あれまじでどうにかなりませんか,本当に困っています.

*3:我々

*4:実際のところ,あるファイルから XMP メタデータを取り出す方法というのは大きな問題です.XMP メタデータはファイル形式が変わっても引き継がれる場合があるため,事前にファイル形式を定められないケースがあるためです.具体的には Photoshop で作成した画像を jpeg として書き出した際にメタデータが引き継がれる,と言ったようなケースです.基本的なアプローチとしては今回のようにファイル形式に関する前提知識を利用して取り出すことが推奨されています.xpacket マーカを頼りに探索的に取り出すことアプローチもありますが,不確実性が高く壊れやすいロジックのため推奨されていません.

*5:動作についてはAdobe Photoshop CC 2019 で作成された PSD ファイルでのみ正しく動作することを確認してます.偶然手元にあった Adobe Photoshop CS5 Macintosh で作られたやつはダメだった.2019 では単一の要素にまとめられてた箇所か とっ散らかってた.

*6:本当は編集ツリーみたいなのまで作ろうと思ったのですが,どうやらイベントが新規に記録されるタイミングと更新されるタイミングがあるらしく,意図通りに保存記録を積み上げたデータが作れなかったので断念したという背景があります