2024-11-06 ,

XMPメタデータエディタ、ファイル形式、EXIF、データベース

前々回前回に引き続き、el-xmpの話。

xmp-editor.elを追加してプロパティを一括で編集できるようになりました。

Diredからなら xmp-dired-do-edit-properties コマンド(' e p)、その他のファイル名が検出できるところからなら xmp-edit-file-properties コマンドで次のような編集バッファを表示できます。

複数ファイルのメタデータを編集しているところ
図1: 複数ファイルのメタデータを編集しているところ

image-diredには image-dired-dired-edit-comment-and-tags というコマンドがあってこれと似たようなことができますが「コメント」と「タグ」のみの編集となっています。こちらは好きなだけ編集項目を増やせるのが良い所です(ユーザーが独自のプロパティを定義することも可能です)。そもそも対象は画像ファイルに限定されません。サムネイルは画像ファイルの時だけimage-diredの仕組みを利用して表示しています。

デフォルトではカスタマイズ変数で指定されているプロパティのみが表示されますが、プレフィックス引数(C-u 0 ' e p)を使うかまたは末尾が-allとなっているコマンド(' e a)を使えばel-xmpが認識できる全てのプロパティを表示させることもできます。

全てのプロパティを表示させてみたところ
図2: 全てのプロパティを表示させてみたところ

上のスクリーンショットは認識できる全プロパティが表示されていますが、そこには元々EXIFで記録されているカメラの情報も入っています。

今回xmp-tiff.elxmp-exif.elを追加したことによってEXIFを読み取ることも可能になりました。JPEGスキャナはAPP1セグメントのうちEXIFとXMPパケットの両方を読み取ります。読み取ったEXIFはXMPに変換されて同一ファイル内にあるXMPパケットとマージされ、元々一つのXMPパケットだったかのように扱われます。EXIFの読み取りについてはEmacs内にすでにexif.elがありますが以前調べたように多少問題があることが分かっていた(特にエンディアンバグはまだ残っているようです)ので独自に実装しました。

ついでにTIFF画像にも対応し、こちらもJPEGと同様EXIFとXMPパケットの両方を読み取ってマージします。いくつかのカメラのRAW画像形式はTIFFベースだったので全く同じコードで対応できました。とりあえずソニーのARW、キヤノンのCR2(CR3はISO BMFFベースらしいです)、ニコンのNEFが読み込めたので、それらの拡張子ではTIFFスキャナが使われるようにしました。

PDFはファイルの中に複数のXMPパケットが混在していることが多いので汎用的なパケットスキャンではかなり高い確率で間違ったXMPパケットを読み取ってしまいます。そこでxmp-pdf.elを追加してPDFもちゃんとスキャンするように頑張ってみたのですが圧縮や暗号に対応できず読めないファイルが多く残る結果となってしまいました。その代わりpdfinfoコマンドによるXMPの抽出に対応したので、必要であればインストールしてください。pdf-toolsを入れていれば多分入っているんじゃないかと思います。無理にEmacs Lispで実装するよりもこっちの方が良いでしょう。

EXIFが読めるようになったので撮影日時が取得できるようになりました。Emacs Lispのコードレベルでは (xmp-pvalue-as-text (xmp-get-file-property "example.jpg" (xmp-xml-ename xmp-exif: "DateTimeOriginal"))) で取得できます。

ちなみにEXIFが持つ基本的な日時には DateTimeDateTimeOriginalDateTimeDigitized があり、 DateTime は更新日時(xmp:ModifyDateにマップされる)、 DateTimeOriginal は元々の撮影日時、 DateTimeDigitized はデジタル化(要するにフィルムであればスキャンした日時。デジカメであれば撮影日時と同じ)となっているようです。以前のEXIF Metadata規格では DateTimeDigitizedxmp:CreateDate にマップされていたようですが、現在は exif:DateTimeDigitized にマップされています。「作成日」というのはやや曖昧な概念と言えるでしょう。

撮影日時が読めるのであればファイルを撮影日時順にソートしたくなります。しかしDiredを開くたびに全ファイルからメタデータを読み取っていては時間がかかりすぎますから、断然キャッシュが重要になってきます。現在はEmacs起動中のみ有効なキャッシュ機構がありますが、Emacsを終了させたら消えてしまいます。やはり永続的なキャッシュ機構が必要です。

また、メタデータを編集した際の保存先も現在はサイドカーファイルのみですが、 ~/.emacs.d/ の中に隠しておく選択肢もやはり欲しい所です。ディレクトリやファイルの種類によって保存先を変えられるのが理想でしょう。

となるとやはり何らかのデータベースのような仕組みが必要になります。

image-diredのように一つのファイル( ~/.emacs.d/image-dired/.image-dired_db )に全ファイル分のメタデータをテキストで保存するのは嫌でしょう。一つ編集するたびに全部書き直さなければなりません。対象ファイルが増えたら増えた分だけ全ての場所で重くなっていきます。

サムネイルと同じようにメタデータも ファイル毎 に ~/.emacs.d/ 内に保存してしまうと言う手もあるでしょう。しかしいくら一つ一つのメタデータファイルを単純化してもディレクトリを開くときに多数のファイルにアクセスするのは効率が悪いです。

ディレクトリ毎 にメタデータファイルを作成して ~/.emacs.d/ の下に保存しておくというのは比較的バランスが取れた方法かもしれません。ファイル名はディレクトリのフルパスを何らかの規則でエンコードしたものにすれば良いでしょう。

後はちゃんとしたデータベースを使うことですね。今のEmacsにはSQLiteが組み込まれているので(コンパイルオプション次第ですがWindows版公式ビルドでちゃんと使えます)、それを使うのも良さそうです。Android OSが似たようなことをすでにしていますね。あれは端末の中にあるメディアファイルのメタデータをスキャンしてSQLiteのデータベースに保持していつでも素早く情報を取得できるようにしています。それと同じような感じにすれば良さそうです。とは言えデータベースの設計は悩み所が多そうな気がします。何を保存するか、何で検索できるようにするか。例えばdc:subject内の一つ一つの主題で高速に検索できるようになっているべきか、等。一つのプロパティが単純な一つのText型ならまだ良いのですが、Array(Seq,Seq,Alt)やStruct等の構造を持っているととたんに面倒になります。単純にデータの保存先と割り切るなら最悪S式をそのまま突っ込んでしまえば良いのでしょうけど……。まぁ、自分の必要性に応じてできるだけ簡単な方法を使いましょう。