Справжня вартість ручної роботи: метадані, виправлені вручну, – це метадані, які ніхто не зможе перевірити пізніше; процес не залишає слідів, окрім втомлених дизайнерів.

Повний робочий приклад доступний на GitHub:
read-and-write-xmp-in-psd-ai-files-java

Старий спосіб був болючим

Уявіть собі прибирання архіву, на яке ніхто не хоче добровільно братися. Папка з PSD‑майстрами та AI‑джерелами потребує повідомлень про права та ключових слів, перш ніж потрапити в DAM. Рутинна процедура: відкрити файл у Photoshop, відкрити «File Info», ввести копірайт, ввести ключові слова, зберегти, закрити, перейти до наступного файлу. Кожне збереження повторно рендерить багатошаровий файл лише для зміни кількох рядків XMP‑метаданих. Архів, який навчив мене цьому уроку, був папкою непомічених файлів Illustrator, які ніхто не міг знайти; ми виправили це за допомогою циклу, а не більшої терплячості.

Помножте цю рутину на архів, і вона перестає бути завданням і стає проєктом. Гірше, це не піддається аудиту: ніхто не може пізніше довести, які файли були оброблені, а пропущені виглядають ідентично, доки питання ліцензування їх не виявить. Шлях через панель також тихо зв’язує введення даних із інструментами дизайну. Той, хто виправляє метадані, потребує місця в Adobe, робочої станції, що комфортно відкриває багатошарові майстри, і терпіння чекати збережень, які повторно рендерять графіку лише для зміни рядків.

Є кращий спосіб

GroupDocs.Metadata для Java читає та записує XMP‑пакет безпосередньо. Приведіть getRootPackage() до типу IXmp, і пакет, його схеми та масиви стають звичайними об’єктами Java, ідентичними для контейнерів PSD і AI, без залучення програмного забезпечення Adobe. Документація налічує понад 170 форматів, доступних через один API.

Перш ніж розпочати, вам знадобиться:

Додайте залежність і репозиторій GroupDocs у ваш pom.xml:

mvn dependency:get -Dartifact=com.groupdocs:groupdocs-metadata:24.7

Супутній репозиторій постачається з готовим pom.xml та зразками обох форматів, і перевіряє кожен крок нижче.

Новий спосіб: чотири операції в Java

Крок 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(), тому дати приходять у читабельному вигляді, а sweep, керований Specification, ловить пакети виробників. У репозиторії реалізовано обхід семи схем; структура залишається тією ж.

Крок 2 – Прочитайте поля, що відповідають на питання

Ліцензування вимагає dc:rights. Пошук — dc:subject. Обидва живуть у Dublin Core, і scoped‑читання охоплює лише дев’ять полів, без обходу дерева.

// 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() та ще п’ять), охоплюючи поля метаданих PSD, які читаються Bridge і Lightroom. У репозиторії кожен геттер обгорнуто у null‑безпечний хелпер, тому файл з неповними даними повертає порожні рядки замість несподіванок. Ця деталь важливіша, ніж здається: головна мета автоматизації архіву — щоб «дивні» файли проходили через цикл, а не зупиняли його.

Обидва scoped‑читання мають однаковий профіль вартості, який варто назвати. Один відкритий файл, одна схема, без обходу дерева. Розмістіть їх у обробниках запитів і шлюзах; збережіть повний знімок для завдань інжестії, які зберігають усе.

Крок 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);

Ключові слова додаються тим же шаблоном одним викликом, записуючи весь bag як Unordered‑масив:

// 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 замкнує цикл: він знову читає результати і перевіряє, чи рядок копірайту та перше ключове слово дійсно збереглися після збереження.

Ця фінальна перевірка заслуговує окремого речення‑рекомендації. Запис метаданих може тихо провалитися; файл зберігається, байти змінюються, а значення, яке ви хотіли записати, просто відсутнє, бо об’єкт схеми був застарілим або шлях вказував на оригінал. Читання назад після кожного запису додає одне додаткове відкриття файлу і перетворює «скрипт завершився» у «значення присутні», що саме те, що хоче бачити власник архіву. Тримайте це у продакшені, а не лише у демонстрації.

Крок 4 – Як саме ключові слова роблять активи знайденими?

Інструменти пошуку не читають пікселі; вони читають dc:subject. Bridge, індексатори DAM та платформи стокових зображень трактують цей bag як словник активу, тому файл без ключових слів просто ніколи не відповідає запиту. Запис bag як Unordered XmpArray, як це робить AddKeywords, переводить актив з «невидимого» у «знайдений», а запис вимагає одного збереження.

Порівняння: до і після

До (редагування через панель) Після (pipeline на Java)
Інструменти Photoshop або Bridge для кожного файлу Один Maven‑проєкт, без Adobe‑місця
Покриття Поля, які показує панель Кожна схема плюс пакети виробників
Повторюваність Залежить від того, хто натискає Той самий цикл, той самий результат, аудитується
Файли без XMP Поведінка панелі різна Guard‑створення пакету та схем
Верифікація Довіра Перевірка читання назад для кожного файлу

Рядок верифікації вирішує питання для архівів: скрипт, який доводить власні записи, — це різниця між «ми позначили файли» і «ми можемо це показати».

Приклад з реального світу: передача агентства

Студія отримує змішані поставки PSD і AI від трьох агентств, кожне зі своїм підходом до метаданих. Тепер їхня робота з прийому запускає знімок при надходженні, позначає файли, у яких dc:rights порожній, додає рядок з умовами прав, і записує набір ключових слів кампанії. Один і той самий цикл працює для обох форматів, бо в коді ні один контейнер не називається, а метадані Adobe Illustrator, що надходять порожніми, залишають файл позначеним і пошуковим.

Подальший ефект — це те, чого студія не передбачала: оцінки агентств. Оскільки робота з прийому реєструє, які поставки прибули без полів прав, закупівлі тепер бачать, які постачальники надсилають чисті метадані, а які покладаються на клієнта. Розмова з найгіршим порушником зайняла один графік.

Що ще можна зробити з GroupDocs.Metadata?

  • EXIF і IPTC в тих самих файлах: PSD‑файли містять три стандарти метаданих; та сама бібліотека читає інші два через їхні пакети, тому повний профіль активу — це ще два читання.
  • 170+ інших форматів: однакова точка входу Metadata обслуговує Office, PDF, аудіо‑ та відеофайли, що дозволяє одній роботі з прийому охопити весь змішаний архів.
  • Пошук за властивістю: findProperties з Specification сканує будь‑який файл за будь‑яким предикатом, від перевірки прав до пошуку користувацьких полів.

Висновок

Те, що раніше було рутинною панельною операцією для кожного файлу, тепер — чотири операції Java: знімок, scoped‑читання, штамп власності, запис ключових слів. Той самий код працює з PSD і AI, guard‑механізми роблять порожні експорти безпечними, а підтверджений зразковий проєкт доводить всю функціональність перед тим, як його застосувати до реального архіву.

Готові відмовитися від панелі «File Info»?

Додаткові ресурси