XMP Toolkit API Overview

The XMPCore component provides the tools that allow you to parse, manipulate, and serialize XMP data, according to the Data Model and Serialization Model given in the XMP Specification. XMPCore has no knowledge of files.

The client view of the XMPCore API is provided through these C++ class templates:

The XMPFiles component provides support for locating the XMP in a file, adding XMP to a file, or updating the XMP in a file. Use it to retrieve an entire XMP packet from a file, which you can either manipulate directly or use to create a TXMPMeta object, so that you can use the XMPCore component to manipulate the individual XMP properties. XMPFiles contains a number of format-specific file handlers that know how to efficiently access the XMP in particular formats. It also includes a fallback packet scanner that can be used for unknown file formats.

The TXMP* classes are C++ template classes. The templates must be instantiated for use. You can read the template header files, TXMPMeta.hpp, and so on, for detailed information, but do not include them directly in your code.

There is one overall header file, XMP.hpp, which is the only one that C++ clients should include with the include directive. Read the instructions in this file for instantiating the template classes. When you have done this, the API is available through the concrete classes SXMPMeta, SXMPUtils, SXMPIterator, and SXMPFiles.

You should also read XMP_Const.h for detailed information about types and constants for namespace URIs and option flags.

Using of the XMP Toolkit API

Developers should understand the XMP Data Model before working with the XMP Toolkit. The data model is documented in the XMP Specification. The XMPCoverage sample in the SDK provides an in-depth illustration of the use of the XMP Toolkit. An XMP Programmer's Guide with tutorial examples is provided in the docs folder within the SDK.

Use of the XMP Toolkit is reasonably straightforward once you understand the XMP Data Model. An XMP property tree that conforms to the Data Model is encapsulated by a TXMPMeta object, and the functions of that class allow you to manipulate the namespaces, properties, and values.

To prepare XMP data for output (transferring it or embedding it in a file), it must be serialized as XML text (specifically, RDF conforming to the Serialization Model).

Similarly, you use the XMPFiles component (TXMPFiles::GetXMP()) to extract an XMP packet from a file. To work with the XMP, create a TXMPMeta object and populate it with the data using TXMPMeta::ParseFromBuffer().

You can use the XMPCore component to generate new XMP data.

Overview of XMP Toolkit Internal Architecture.

The XMP Toolkit is implemented in three layers, which isolate the return of string values, synchronization for multi-threaded use, and exception propagation. While the SDK as provided from Adobe builds a static library, this layering can easily be adapted to build a DLL.

Implementation Call Chain

The implementation of GetProperty provides a good illustration of the toolkit layering. The declaration below for TXMPMeta::GetProperty is simplified by hardwiring std::string. The XMP_StringPtr type is simply const char *.

  bool TXMPMeta::GetProperty ( XMP_StringPtr    schemaNS,
                               XMP_StringPtr    propName,
                               std::string *    propValue,
                               XMP_OptionBits * options ) const
  {
     XMP_StringPtr resultPtr = 0;
     XMP_StringLen resultLen = 0;

     bool found = this->xmpObj.GetProperty ( schemaNS, propName,
                                             &resultPtr, &resultLen, options );

     if ( found ) {
         if ( propValue != 0 ) propValue->assign ( resultPtr, resultLen );
         this->xmpObj.UnlockObject ( kXMP_NoOptions );
     }
     return found;

  }

The template object contains a data member pointer to the underlying WXMPMeta object. This is used to dispatch the call to the middle layer. The actual implementation of the XMP toolkit returns string values as a pointer and length, the pointer references private internal storage of the toolkit. The client code copies the string value to the client's string object. This minimizes the amount of string copying, and should the XMP toolkit be built as a DLL ensures that any memory allocation for the client's value is done on the client side. The call to WXMPMeta::UnlockObject is explained below.

  bool WXMPMeta::GetProperty ( XMP_StringPtr    schemaNS,
                               XMP_StringPtr    propName,
                               XMP_StringPtr *  propValue,
                               XMP_StringLen *  valueSize,
                               XMP_OptionBits * options ) const
  {
      XMP_Bool found;
      XMP_ENTER_WRAPPER ( "WXMPMeta::GetProperty" )

      if ( (schemaNS == 0) || (*schemaNS == 0) ) {
          XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
      }
      if ( (propName == 0) || (*propName == 0) ) {
          XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
      }

      if ( propValue == 0 ) propValue = &voidStringPtr;
      if ( valueSize == 0 ) valueSize = &voidStringLen;
      if ( options == 0 ) options = &voidOptionBits;

      const XMPMeta & meta = WtoXMPMeta_Ref ( *this );
      found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options );

      XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
      return found;
  }

The entry and exit macros in the WXMPMeta layer acquire the threading lock on entry and usually release it on exit. The lock is kept on exit whenever a string value is returned. Since a pointer to internal data is returned, the threading lock can't be released until after the template code in the client copies the string. The entry and exit macros also prevent uncontrolled exception propagation from the lower layer back to the client. This is not critical for use of the XMP Toolkit as a static library. But it is generally not safe to propagate C++ exceptions across DLL boundaries.


XMP-Toolkit-SDK-4.4.2 documentation generated by doxygen 1.5.6