XMP Feature is available in Photoshop 25.0

XMP module in UXP offers JavaScript access to the Adobe XMP Core and XMP Files libraries. This feature is now available in UXP 7.2 with Photoshop 25.0.

For more details refer:
https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/uxp/XMP/

@vinayKumarG @pkrishna

7 Likes

This is a great feature addition! Thanks so much!

Reading through the documentation I have one question. Maybe I missed this, but I wonder how XMP’s File I/O relates to Photoshop’s I/O? It seems to me like in order to access a document’s metadata you call XMP’s file I/O. Let’s assume I have a document open in Photoshop, modifying its contents, let’s say I also want to update its metadata. Would XMP’s file I/O use the file that’s already being worked on by Photoshop or open it again separately?

@dotproduct,
It depends on how you would update the XMP data, using the batchplay to update or use XMPFile

If you use batchplay, it would make use of the file already opened by photoshop, which is the recommended way for already opened files,

If you use XMPFile to write then it would open separately, recommend to use when you dont want to open the file in Photoshop

Great, thanks for clarifying! So using batchPlay I assume the idea would be to pass the serialized string to the XMPMeta constructor, correct?

Yes, passing serialized string to the XMPMeta constructor, modify the content on the object using the methods provided and pass it back as string in batchplay to update

Perfect. Thanks again for this feature, I’m sure it will make it much easier to work with metadata!

2 Likes

@vinayKumarG
Is it possible to provide working example of this since I am not being able to make it work and couldn’t also find anything in the docs.
What I am trying to do is

  1. Read the XMP data of the currently opened file in PS with batchplay
  2. Modify one of the properties(custom namespace)
  3. Save the XMP data to the currently opened file in PS

@freakpazo,

Here is a sample,


// Batchplay commands to get and set XMP
const bp = require("photoshop").action.batchPlay;
// GETTER
const getDocumentXMP = () => {
    return bp(
        [
            {
                _obj: "get",
                _target: {
                    _ref: [
                        { _property: "XMPMetadataAsUTF8" },
                        { _ref: "document", _enum: "ordinal", _value: "targetEnum" },
                    ],
                },
            },
        ],
        { synchronousExecution: true }
    )[0].XMPMetadataAsUTF8;
};

const psCore = require("photoshop").core;
const setDocumentXMP = async (xmpString) => {
    try {
        await psCore.executeAsModal(
            async () =>
                await bp(
                    [
                        {
                            _obj: "set",
                            _target: [
                                { _property: "XMPMetadataAsUTF8" },
                                { _ref: "document", _enum: "ordinal", _value: "targetEnum" },
                            ],
                            to: {
                                _obj: "XMPMetadataAsUTF8",
                                XMPMetadataAsUTF8: xmpString,
                            },
                        },
                    ],
                    { synchronousExecution: false }
                ),
            { commandName: "Setting XMP..." }
        );
    } catch (error) {
        console.error(error);
    }
};

function updateXMP(xmp) {
    xmp.appendArrayItem(XMPConst.NS_DC, "title", "Sample Title", 0, XMPConst.ARRAY_IS_ALTERNATIVE);
    xmp.appendArrayItem(XMPConst.NS_DC, "Creator", "Sample Creator Value", 0, XMPConst.ARRAY_IS_ORDERED);
    xmp.appendArrayItem(XMPConst.NS_DC, "description", "Set description Here", 0, XMPConst.ARRAY_IS_ALTERNATIVE);
    xmp.setProperty(XMPConst.NS_XMP, "Rating", 4); // Rating Number
    xmp.setProperty(XMPConst.NS_PHOTOSHOP, "AuthorsPosition", "Sample Author Position");
    xmp.setProperty(XMPConst.NS_PHOTOSHOP, "CaptionWriter", "Sample Caption Writer");
    return xmp;
}


// Fetch XMP Form Current Document
let xmpData = getDocumentXMP();
let meta = new XMPMeta(xmpData);
meta = updateXMP(meta);
setDocumentXMP(meta.serialize());