Full working example available on GitHub:
read-and-write-xmp-in-psd-ai-files-java
旧来の方法は苦痛だった
アーカイブの整理作業を想像してください。誰もやりたがらない作業です。PSD のマスターファイルと AI のソースファイルが多数あり、DAM に入れる前に権利表示とキーワードを付ける必要があります。手順は次の通りです。Photoshop でファイルを開き、[ファイル情報] を開き、著作権情報を入力し、キーワードを入力し、保存、閉じ、次のファイルへ。文字列の XMP メタデータを数個変更するだけなのに、レイヤー付きファイルを毎回再レンダリングして保存しなければなりません。私がこの教訓を学んだアーカイブは、タグ付けされていない Illustrator ファイルが検索できずに放置されていたフォルダーで、我々は忍耐ではなくループで解決しました。
この手順をアーカイブ全体に拡大すると、単なるタスクではなくプロジェクトになります。しかも監査ができません。誰がどのファイルを処理したか証明できず、スキップされたファイルは見た目は同じでも、ライセンスの問題が出たときに初めて問題が顕在化します。パネル経由の方法は、データ入力をデザインツールに静かに結び付けてしまいます。メタデータを修正する人は Adobe のシートが必要で、レイヤーマスタを快適に開けるワークステーションが必要で、文字列だけ変更するためにアートワーク全体を再レンダリングする保存を待つ忍耐が必要です。
手作業で行う実際のコスト:手作業で修正したメタデータは後から誰も検証できません。プロセスは疲れたデザイナー以外に痕跡を残しません。
より良い方法がある
GroupDocs.Metadata for Java は XMP パケットを直接読み書きします。getRootPackage() を IXmp にキャストすれば、パケット、スキーマ、配列は普通の Java オブジェクトとして扱え、PSD と AI のコンテナで同一です。Adobe ソフトは一切必要ありません。ドキュメント(documentation)には同一 API で扱える 170 以上のフォーマットが掲載されています。
開始する前に以下を用意してください。
- JDK 8 以降(Maven 付き)
- GroupDocs.Metadata for Java 24.7(一時ライセンスを取得)
- 練習用の PSD または AI ファイル
pom.xml に依存関係と GroupDocs リポジトリを追加します。
mvn dependency:get -Dartifact=com.groupdocs:groupdocs-metadata:24.7
companion repository には、すぐに使える pom.xml と両フォーマットのサンプルが同梱されており、以下の手順すべてを検証できます。
新しい方法:Java での 4 つの操作
ステップ 1 — ファイルが保持しているものを見る
スナップショットはパケットとすべてのスキーマを 1 つの LinkedHashMap にダンプし、ファイルが宣言した順序を保持します。
// Snapshot the packet, then sweep for anything the schemes missed
Map<String, String> result = new LinkedHashMap<>();
try (Metadata metadata = new Metadata(adobeFilePath)) {
IXmp root = (IXmp) metadata.getRootPackage();
if (root != null && root.getXmpPackage() != null) {
for (MetadataProperty p : root.getXmpPackage()) {
put(result, p);
}
XmpSchemes schemes = root.getXmpPackage().getSchemes();
collect(result, schemes.getDublinCore());
collect(result, schemes.getPhotoshop());
collect(result, schemes.getXmpBasic());
collect(result, schemes.getCameraRaw());
}
for (MetadataProperty p : metadata.findProperties(new NamedPropertySpec())) {
if (!result.containsKey(p.getName())) put(result, p);
}
}
return result;
小さな put と collect ヘルパーは getInterpretedValue() を優先して日付を可読形式で取得し、Specification 主導のスイープでベンダーパケットも捕捉します。リポジトリ版は 7 つのスキーマを走査しますが、構造は同じです。
ステップ 2 — 質問に答えるフィールドを読む
ライセンス情報は dc:rights が必要です。検索は dc:subject が必要です。どちらも Dublin Core にあり、スコープ付き読み取りは 9 フィールドだけで済み、ツリートラバーサルは不要です。
// dc:* only - the interoperability fields DAM systems agree on
XmpDublinCorePackage dc = root.getXmpPackage().getSchemes().getDublinCore();
if (dc == null) return result;
for (MetadataProperty p : dc) {
String value = "";
if (p.getInterpretedValue() != null
&& p.getInterpretedValue().getRawValue() != null) {
value = String.valueOf(p.getInterpretedValue().getRawValue());
} else if (p.getValue() != null && p.getValue().getRawValue() != null) {
value = String.valueOf(p.getValue().getRawValue());
}
result.put(p.getName(), value);
}
Photoshop スキーマも同様に型付きゲッター(getCity()、getCredit()、getColorMode() など)で取得できます。リポジトリのリーダーはすべてのゲッターを null 安全ヘルパーでラップしているため、情報が少ないファイルでも空文字列が返り、例外が発生しません。この細部は思った以上に重要です。アーカイブ自動化の目的は、異常ファイルがループを止めずに流れることです。
両方のスコープ付き読み取りは「1 ファイルオープン、1 スキーマ、ツリートラバーサルなし」というコストプロファイルを共有します。リクエストハンドラやゲートに組み込んで、全スナップショットをインジェストジョブで保存すれば、すべてを一括で処理できます。
ステップ 3 — Adobe を開かずにスタンプとタグ付け
ライターは不足している要素をガード付きで作成するため、パケットが全く無い新規エクスポートでも安全に動作します。
// Create missing layers, then write rights, creator, and CreatorTool
if (root.getXmpPackage() == null) {
root.setXmpPackage(new XmpPacketWrapper());
}
if (root.getXmpPackage().getSchemes().getDublinCore() == null) {
root.getXmpPackage().getSchemes().setDublinCore(new XmpDublinCorePackage());
}
XmpDublinCorePackage dc = root.getXmpPackage().getSchemes().getDublinCore();
dc.setRights(copyright);
dc.set("dc:creator", XmpArray.from(new String[]{creator}, XmpArrayType.Ordered));
if (root.getXmpPackage().getSchemes().getXmpBasic() == null) {
root.getXmpPackage().getSchemes().setXmpBasic(new XmpBasicPackage());
}
root.getXmpPackage().getSchemes().getXmpBasic().setCreatorTool(creator);
metadata.save(outputPath);
キーワードは同じパターンで 1 回の呼び出しで書き込み、Unordered 配列として全体の bag を置き換えます。
// Replace the dc:subject bag - merge in Java first for additive tagging
root.getXmpPackage().getSchemes().getDublinCore().set(
"dc:subject", XmpArray.from(keywords, XmpArrayType.Unordered));
metadata.save(outputPath);
Main.java はループを閉じます。出力を再読込みし、著作権文字列と最初のキーワードが実際に保存されたことをアサートします。
このアサートは重要です。メタデータ書き込みは失敗しても静かに失敗します。ファイルは保存されても、書き込もうとした値が存在しないことがあります(スキーマオブジェクトが古い、パスが元ファイルを指しているなど)。各書き込み後に読み戻すことで、ファイルごとに 1 回の余分なオープンが発生しますが、「スクリプトが完了した」から「値が存在する」へと確実に変換できます。デモだけでなく本番でも必ず入れてください。
ステップ 4 — キーワードで資産を検索可能にする
検索ツールはピクセルを読まない。dc:subject を読むだけです。Bridge、DAM インデクサ、ストックプラットフォームはこの bag を資産の語彙として扱うため、キーワードが無いファイルはクエリにマッチしません。AddKeywords が行うように Unordered XmpArray として bag を書き込むことで、資産は「見えない」から「見つかる」へと変わり、書き込みは 1 回の保存で完了します。
並列比較:Before vs. After
| Before (パネル編集) | After (Java パイプライン) | |
|---|---|---|
| ツール | ファイルごとに Photoshop または Bridge | 1 つの Maven プロジェクト、Adobe シート不要 |
| カバー範囲 | パネルが公開するフィールド | すべてのスキーマ+ベンダーパケット |
| 再現性 | 誰がクリックしたかに依存 | 同一ループ、同一結果、監査可能 |
| XMP が無いファイル | パネルの挙動がバラバラ | ガードがパケットとスキーマを自動生成 |
| 検証 | 信頼 | ファイルごとの読み戻しでアサート |
検証行はアーカイブにとって決定的です。自分の書き込みを証明できるスクリプトが「タグ付けした」か「証明できる」かの違いを生みます。
実務例:エージェンシーからの引き渡し
あるスタジオは 3 つのエージェンシーから混在した PSD と AI を受け取ります。各エージェンシーは独自のメタデータ方針を持っています。新しい intake ジョブは到着時にスナップショットを取り、dc:rights が空のファイルをフラグし、契約上の権利文をスタンプし、キャンペーン用キーワードセットを書き込みます。コードはコンテナを意識しないため、両フォーマットで同一ループが使え、Illustrator のメタデータが空でも intake 時にタグ付け・検索可能になります。
この効果でスタジオが予想しなかったのは「エージェンシースコアカード」です。intake ジョブが空権利フィールドで届いた納品をログに残すことで、調達部門はどのサプライヤーがクリーンなメタデータを提供し、どのサプライヤーがクライアントに修正を依存させているかを把握できます。最も問題の多いサプライヤーとの会話は 1 枚のチャートで済みました。
GroupDocs.Metadata で他にできることは?
- 同一ファイル内の EXIF と IPTC:PSD は 3 つのメタデータ標準を保持します。同一ライブラリで他の 2 つも別パッケージとして読み取れるため、資産プロファイルはあと 2 回の読み取りで完成します。
- 170 以上のその他フォーマット:同一の
Metadataエントリーポイントが Office、PDF、音声、動画ファイルを扱い、1 つの intake ジョブで混在アーカイブ全体をカバーできます。 - プロパティ検索:
findPropertiesとSpecificationを組み合わせれば、権利チェックからカスタムフィールド検索まで、任意の述語でファイルを走査できます。
結論
かつてはファイルごとのパネル操作だった作業が、今や Java の 4 つの操作(スナップショット、スコープ付き読み取り、所有権スタンプ、キーワード書き込み)に置き換わりました。同一コードが PSD と AI の両方に対応し、ガードが空エクスポートでも安全に処理し、サンプルプロジェクトのアサートが実際のアーカイブに適用する前に全体を検証します。
File Info パネルにさようならを告げませんか?
- サンプルプロジェクト を
mvn compile exec:javaでビルド - 比較スタイルのユースケースガイド を参照
- Working with XMP metadata リファレンスを読む