Project

General

Profile

Merging two sets of XmpData

Added by Tobias E. over 6 years ago

Hello,

I guess I need your advice how to properly do something with libexiv2. I want to read XMP data from an image and then add more XMP data from a .xmp file to the same XmpData object so I can work on the merged data. However, just calling Exiv2::XmpParser::decode twice obviously doesn't work since it clears the XmpDatum. Is there some helper function that I missed or do I have to read the .xmp file into its own XmpData and then iterate over all Xmpdatum and use add() from the first object?

Thanks in advance
Tobias


Replies (4)

RE: Merging two sets of XmpData - Added by Robin Mills over 6 years ago

I think you'll have to do the merge by adding data elements one at a time. Here are another couple suggestions:

1) I've added a sample application exiv2json to extract metadata into a JSON object. If you're not a XML guru, you might two JSON objects easier to merge.
2) I've added an option -pX to extract the "raw" XMP. You might find it easier to merge a couple of XML packets with xmllint (which includes XPath).

If you adopt either of those external approaches, you'll end up with a XML (or JSON) object that you'll want to insert into the file. I'm not too sure how to push that data into the image, however I think it's possible with the insert sub command.

RE: Merging two sets of XmpData - Added by Tobias E. over 6 years ago

Thanks, iterating over the data should be simple. I am using libexiv2 and not the command line tool, so external programs won't help me.

RE: Merging two sets of XmpData - Added by Tobias E. over 6 years ago

In case someone else want to do something similar, this is the test code I ended up with:

// g++ -W -Wall -g `pkg-config --cflags --libs exiv2` -o merge merge.cpp
#include <exiv2/image.hpp>
#include <iostream>

int main()
{
  Exiv2::XmpData xmpData1, xmpData2;
  std::string xmpPacket;

  // read 1st XMP, could also be an image
  Exiv2::DataBuf buf = Exiv2::readFile("1.xmp");
  xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
  Exiv2::XmpParser::decode(xmpData1, xmpPacket);

  // read 2nd XMP (sidecar)
  buf = Exiv2::readFile("2.xmp");
  xmpPacket.assign(reinterpret_cast<char *>(buf.pData_), buf.size_);
  Exiv2::XmpParser::decode(xmpData2, xmpPacket);

  // merge 2 into 1, so that 2 has higher priority
  for(Exiv2::XmpData::const_iterator it = xmpData2.begin(); it != xmpData2.end(); it++)
    xmpData1.add(*it);

  // print for inspection
  if(Exiv2::XmpParser::encode(xmpPacket, xmpData1, Exiv2::XmpParser::useCompactFormat | Exiv2::XmpParser::omitPacketWrapper) != 0)
    std::cout << "Failed to serialize XMP data" << std::endl;
  else
    std::cout << xmpPacket << std::endl;

  // cleanup
  Exiv2::XmpParser::terminate();
  return 1;
}

RE: Merging two sets of XmpData - Added by Robin Mills over 6 years ago

Well done, Tobias. And thank you for sharing your solution. The spirit of open-source is to share the intellectual property. If you know something - pass it on for others to use. Thank You Very Much for this contribution.

    (1-4/4)