Ejemplo completo funcionando disponible en GitHub:
read-and-write-xmp-in-psd-ai-files-java
La forma antigua era dolorosa
Imagina la limpieza de archivos que nadie se ofrece a hacer. Una carpeta de maestros PSD y fuentes AI necesita avisos de derechos y palabras clave antes de entrar al DAM. La rutina: abrir un archivo en Photoshop, abrir Información del archivo, escribir el copyright, escribir las palabras clave, guardar, cerrar, siguiente archivo. Cada guardado vuelve a renderizar un archivo con capas solo para cambiar unas cuantas cadenas de metadatos xmp. El archivo que me enseñó esta lección era una carpeta de archivos Illustrator sin etiquetar que nadie podía buscar; lo solucionamos con un bucle, no con más paciencia.
Multiplica la rutina por un archivo y deja de ser una tarea y se convierte en un proyecto. Peor aún, es no auditado: nadie puede demostrar después qué archivos se procesaron, y los que se omitieron se ven idénticos hasta que una cuestión de licencias los descubre. La ruta del panel también acopla silenciosamente la entrada de datos a las herramientas de diseño. Quien corrige los metadatos necesita una licencia de Adobe, una estación de trabajo que abra maestros con capas cómodamente y la paciencia para esperar guardados que vuelven a renderizar el arte solo para cambiar cadenas.
El costo real de hacerlo manualmente: los metadatos corregidos a mano son metadatos que nadie puede verificar después; el proceso no deja rastro salvo diseñadores cansados.
Hay una forma mejor
GroupDocs.Metadata para Java lee y escribe el paquete XMP directamente. Convierte getRootPackage() a IXmp y el paquete, sus esquemas y sus matrices son objetos Java ordinarios, idénticos para contenedores PSD y AI, sin software de Adobe involucrado. La documentación enumera más de 170 formatos bajo la misma API.
Antes de comenzar, necesitarás:
- JDK 8 o posterior con Maven
- GroupDocs.Metadata para Java 24.7 (obtener una licencia temporal)
- Un archivo PSD o AI para practicar
Agrega la dependencia y el repositorio de GroupDocs a tu pom.xml:
mvn dependency:get -Dartifact=com.groupdocs:groupdocs-metadata:24.7
El repositorio complementario incluye un pom.xml listo más muestras de ambos formatos, y valida cada paso a continuación.
La nueva forma: cuatro operaciones en Java
Paso 1 — Ver qué lleva un archivo
El instantáneo volca el paquete y cada esquema en un LinkedHashMap, preservando el orden que declara el archivo.
// 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;
Los pequeños ayudantes put y collect prefieren getInterpretedValue() para que las fechas lleguen legibles, y el barrido guiado por Specification captura paquetes de proveedores. La versión del repositorio recorre siete esquemas; la forma sigue siendo la misma.
Paso 2 — Leer los campos que responden preguntas
Las licencias preguntan por dc:rights. La búsqueda se preocupa por dc:subject. Ambos viven en Dublin Core, y la lectura con alcance cuesta nueve campos, no una caminata de árbol.
// 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);
}
El esquema Photoshop funciona de la misma manera mediante getters tipados (getCity(), getCredit(), getColorMode() y cinco más), cubriendo los campos de metadatos PSD que Bridge y Lightroom leen. En el repositorio ese lector envuelve cada getter con un ayudante a prueba de nulos, de modo que un archivo escasamente poblado devuelve cadenas vacías en lugar de sorpresas. Ese detalle importa más de lo que parece: el objetivo de automatizar un archivo es que los archivos extraños fluyan en lugar de detener el bucle.
Ambas lecturas con alcance comparten un perfil de costo que vale la pena nombrar. Un archivo abierto, un esquema, sin caminata de árbol. Colócalas en manejadores de solicitudes y puertas; guarda el instantáneo completo para trabajos de ingestión que almacenen todo.
Paso 3 — Estampar y etiquetar sin abrir Adobe
Los escritores crean de forma segura cualquier elemento que falte, lo que los hace seguros para exportaciones nuevas que no llevan paquete alguno.
// 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);
Las palabras clave siguen el mismo patrón con una sola llamada, escribiendo toda la bolsa como una matriz 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 cierra el bucle: vuelve a leer los resultados y verifica que la cadena de copyright y la primera palabra clave realmente sobrevivieron al guardado.
Ese aserto final merece una frase de defensa. Las escrituras de metadatos fallan silenciosamente cuando fallan; el archivo se guarda, los bytes cambian y el valor que pretendías escribir simplemente no está porque un objeto de esquema estaba obsoleto o una ruta apuntaba al original. Una lectura posterior después de cada escritura cuesta una apertura extra por archivo y convierte “el script terminó” en “los valores están presentes”, que es la afirmación que realmente quiere un propietario de archivo. Manténlo en producción, no solo en la demo.
¿Cómo hacen realmente las palabras clave que los activos sean encontrables?
Las herramientas de búsqueda no leen píxeles; leen dc:subject. Bridge, los indexadores DAM y las plataformas de stock tratan esa bolsa como el vocabulario del activo, de modo que un archivo sin palabras clave nunca coincide con una consulta. Escribir la bolsa como un XmpArray Unordered, como hace AddKeywords, es lo que pasa un activo de invisible a encontrable, y la escritura cuesta un guardado.
Comparación lado a lado: antes vs. después
| Antes (edición en panel) | Después (pipeline Java) | |
|---|---|---|
| Herramientas | Photoshop o Bridge por archivo | Un proyecto Maven, sin licencia de Adobe |
| Cobertura | Campos que expone el panel | Cada esquema más paquetes de proveedores |
| Repetibilidad | Depende de quién hizo clic | Mismo bucle, mismo resultado, auditable |
| Archivos sin XMP | El comportamiento del panel varía | Los guardas crean el paquete y los esquemas |
| Verificación | Confianza | Lectura de confirmación por archivo |
La fila de verificación decide por los archivos: un script que prueba sus propias escrituras es la diferencia entre “etiquetamos los archivos” y “podemos mostrártelo”.
Ejemplo del mundo real: la entrega de la agencia
Un estudio recibe entregas mixtas de PSD y AI de tres agencias, cada una con su propia disciplina de metadatos. Su trabajo de ingestión ahora ejecuta el instantáneo al llegar, marca los archivos cuyo dc:rights está vacío, los estampa con la línea de derechos contratada y escribe el conjunto de palabras clave de la campaña. El mismo bucle sirve a ambos formatos porque nada en el código nombra un contenedor, y los metadatos de Adobe Illustrator que llegan en blanco dejan la ingestión etiquetada y buscable.
El efecto posterior es la parte que el estudio no predijo: tarjetas de puntuación de agencias. Como el trabajo de ingestión registra qué entregas llegaron con campos de derechos vacíos, compras ahora ve qué proveedores envían metadatos limpios y cuáles dependen del cliente para corregirlos. La conversación con el mayor infractor tomó un solo gráfico.
¿Qué más puedes hacer con GroupDocs.Metadata?
- EXIF e IPTC en los mismos archivos: los PSD llevan tres estándares de metadatos; la misma biblioteca lee los otros dos a través de sus propios paquetes, de modo que un perfil completo del activo está a dos lecturas de distancia.
- Más de 170 formatos adicionales: el mismo punto de entrada
Metadatasirve a Office, PDF, audio y video, que es como un trabajo de ingestión cubre todo un archivo mixto. - Búsqueda de propiedades:
findPropertiescon unaSpecificationbarre cualquier archivo por cualquier predicado que definas, desde verificaciones de derechos hasta búsquedas de campos personalizados.
Conclusión
Lo que antes era una rutina de panel por archivo ahora son cuatro operaciones Java: instantáneo, lectura con alcance, estampado de propiedad, escritura de palabras clave. El mismo código sirve a archivos PSD y AI, los guardas hacen seguras las exportaciones vacías, y el proyecto de muestra con aserciones prueba todo antes de apuntarlo a un archivo real.
¿Listo para retirar el panel de Información de archivo?
- Compila el proyecto de muestra con
mvn compile exec:java - Revisa la guía de caso de uso estilo comparación
- Lee la referencia de Working with XMP metadata