Yearly Archives: 2024

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式をそのまま突っ込んでしまえば良いのでしょうけど……。まぁ、自分の必要性に応じてできるだけ簡単な方法を使いましょう。

2024-10-21 ,

XMPメタデータをimage-dired内で使う

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

xmp-image-dired.elを追加し、image-dired内で画像ファイルのメタデータを操作できるようにしました。具体的には次のことが可能です。

  • マークしたファイルまたは現在のポイントが指すファイルに対するプロパティの設定
  • 現在のポイントが指すファイルからのプロパティの取得
  • サムネイルのプロパティ値に基づくフィルタ(一時的な非表示)

現在対応しているプロパティは次の通りです。

  • xmp:Rating
  • xmp:Label
  • dc:subject
  • dc:title
  • dc:description
  • dc:creators

image-diredにはタグやコメントを付ける機能が既にありますが、それでは物足りないという人のためのものです(標準機能のタグやコメントは.emacs.d内に独自形式で保存されるので他のアプリと連携できないという問題もあります)。

参考までに設定例としてxmp-setup.elを追加したので、それを使えば簡単にこれらの機能をdiredとimage-diredの両方から利用できるようになります(フィルタはimage-diredのみ。diredではマーク操作が可能)。次のキーが使えるようになります。

  • プロパティ設定
    • ' s r : Set Rating
    • ' s l : Set Label
    • ' s s : Set Subjects
    • ' a s : Add Subjects
    • ' r s : Remove Subjects
    • ' s t : Set Title
    • ' s d : Set Description
    • ' s c : Set Creators
  • プロパティ取得
    • ' g a : Get All properties
    • ' g r : Get Rating
    • ' g l : Get Label
    • ' g s : Get Subjects
    • ' g t : Get Title
    • ' g d : Get Description
    • ' g c : Get Creators
  • マーク(diredのみ)
    • ' m r : Mark by Rating
    • ' m l : Mark by Label
    • ' m s : Mark by Subjects
    • ' m t : Mark by Title
    • ' m d : Mark by Description
    • ' m c : Mark by Creator
  • フィルタ(image-diredのみ)
    • ' f r : Filter by Rating
    • ' f l : Filter by Label
    • ' f s : Filter by Subjects
    • ' f - : Clear Filter

例えば ' s r でレーティングを設定して、 ' f r で特定のレーティングのみを表示する、といった使い方ができます。 ' f - でフィルタを解除します。HydraやらTransientやらで使いやすくした方が良いと思いますが、とりあえず設定例ということで。

ここで言うLabel(xmp:Labelプロパティ)は、ファイルに対して一つだけ設定できる短い文字列です。定義については https://developer.adobe.com/xmp/docs/XMPNamespaces/xmp/ を参照してください。Adobe Lightroom等ではカラーラベルを設定するとこのプロパティにRedやBlueといった色名が設定されるらしいです。

Subject(dc:subject)は、ファイルの主題を表すキーワード等のリストです。定義については https://developer.adobe.com/xmp/docs/XMPNamespaces/dc/https://www.dublincore.org/specifications/dublin-core/dcmi-terms/terms/subject/ を参照してください。実質的にはある種のタグとして使用してしまって良いのではないかと思います。主題なので、ファイルが何を表現しているのかといった観点から付けた方が良いのだと思います。何か作業の状態等を付けるのは憚られる感じかと思います。

フィルタ表示機能は元々image-diredが対応していないものを無理矢理実現しているので、Emacsのバージョンアップに伴って機能しなくなる可能性があります。気がついたら直すつもりです。

image-dired内でマークしたファイルにdc:subjectプロパティを設定している所
図1: image-dired内でマークしたファイルにdc:subjectプロパティを設定している所
2024-10-19 ,

EmacsからファイルのXMPメタデータを取得・設定する

XMP(Extensible Metadata Platform)というメタデータを記述するための仕様があります。

https://developer.adobe.com/xmp/docs/

https://developer.adobe.com/xmp/docs/XMPSpecifications/

メタデータというと例えばタイトル、作成者、作成日、内容説明、ラベルといったものが代表的ですが、それに限らずあらゆる関連情報を表現することが出来る拡張可能な枠組みがXMPです。

例えば XMPSpecificationPart1.pdf というPDFファイル(バイナリ)の最後の方には次のようなXMLテキストが含まれています。

...バイナリ略...
<?xpacket begin="(略)" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.0-c316 44.253921, Sun Oct 01 2006 17:14:39">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:dc="http://purl.org/dc/elements/1.1/">
         <dc:format>application/pdf</dc:format>
         <dc:title>
            <rdf:Alt>
               <rdf:li xml:lang="x-default">XMP Specification Part 1: Data Model, Serialization, and Core Properties</rdf:li>
            </rdf:Alt>
         </dc:title>
         <dc:creator>
            <rdf:Seq>
               <rdf:li>Adobe Systems Incorporated</rdf:li>
            </rdf:Seq>
         </dc:creator>
      </rdf:Description>
      <rdf:Description rdf:about=""
            xmlns:xap="http://ns.adobe.com/xap/1.0/">
         <xap:CreateDate>2012-03-21T08:55:04Z</xap:CreateDate>
         <xap:CreatorTool>FrameMaker 8.0</xap:CreatorTool>
         <xap:ModifyDate>2012-03-21T08:57:17-07:00</xap:ModifyDate>
         <xap:MetadataDate>2012-03-21T08:57:17-07:00</xap:MetadataDate>
      </rdf:Description>
      <rdf:Description rdf:about=""
            xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
         <pdf:Producer>Acrobat Distiller 8.1.0 (Windows)</pdf:Producer>
         <pdf:Copyright>Copyright 2012, Adobe Systems Incorporated. All rights reserved.</pdf:Copyright>
      </rdf:Description>
      <rdf:Description rdf:about=""
            xmlns:pdfx="http://ns.adobe.com/pdfx/1.3/">
         <pdfx:Copyright>Copyright 2012, Adobe Systems Incorporated. All rights reserved.</pdfx:Copyright>
      </rdf:Description>
      <rdf:Description rdf:about=""
            xmlns:xapMM="http://ns.adobe.com/xap/1.0/mm/">
         <xapMM:DocumentID>uuid:3806c052-1c0d-4599-b3ff-38c0441bbb3a</xapMM:DocumentID>
         <xapMM:InstanceID>uuid:abc82103-c360-4b74-8812-ff4c81eceaea</xapMM:InstanceID>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>
...空白文字略...
<?xpacket end="w"?>
...バイナリ略...

これによって、このPDFのタイトルが「XMP Specification Part 1: Data Model, Serialization, and Core Properties」、作成者が「Adobe Systems Incorporated」、作成日時が「2012-03-21T08:55:04Z」であることを示しているわけです。

XMPはJPEGファイルの中にも埋め込まれていることがあり、様々な撮影情報が記録されていることがあります。

写真のメタデータと言えばExifが代表的ですが、私の使っているカメラではカメラ内で設定したレーティング(写真の評価)だけがXMPとして記録されるようになっていました(それ以外の撮影情報は全てExifで記録されていました)。

また、写真編集ソフトや各種ビューアもこのXMPを利用するものが多いです。沢山ある写真を評価したり分類したりしたときに、その情報をサイドカーファイルと呼ばれるXMLファイル(IMG0001.JPG.xmpのようなファイル名)に保存するようになっているソフトが多くあります。darktableにいたっては現像のための全てのパラメータをサイドカーファイルに保存します。サイドカーファイルは少々煩わしい存在ですが、メタデータをネットワークストレージを介して共有したり他のソフトと交換したりするのには最適でしょう。

というわけで、EmacsからもこのXMPで書かれたメタデータを読み書きするためのライブラリを作成しました。

misohena/el-xmp: Emacs XMP (Extensible Metadata Platform) Library

今のところ基本的な情報を読み書きするためのコマンドやDired上でメタデータを元にマークするコマンドくらいしかありません。

サイドカーファイル(拡張子が.xmpのXMLテキスト)からの読み取りはもちろん、JPEG内のAPP1セグメント内にあるXMPパケットも読み取れるようになっています。その他の場合は汎用的なパケットスキャン(<?xpacket を探す)が使われますが、確実に読み取れるとは限りません。

保存は全てサイドカーファイルに対して行われます。一応パケット内に書き戻すことも可能なのですが、危ないのでデフォルトでは無効になっています。

Diredでマークするときなど、数千ファイルくらいあると読み取りにかなりの時間がかかります。一応Emacsのセッション中だけ有効なキャッシュ機構があるので、二回目以降は速くなるはずです。

永続的なファイルメタデータキャッシュ機構もそのうち作りたいと考えています。

Diredでレーティングを元にjpgファイルをマークしてimage-diredで表示させた例
図1: Diredでレーティングを元にjpgファイルをマークしてimage-diredで表示させた例