Project

General

Profile

Exiv2 programatically add custom property

Added by Ladislav Kopecky over 4 years ago

Hi,

I am starting with Exiv2 library with C++.

Is there any way how add custom namespace and XMP property to Exiv2 with C++ source code?

I found only this way how add new namespace to Exiv2. It is working.
Exiv2::XmpProperties::registerNs("http://customNamespace.com/", "cn");
xmpData["Xmp.cn.foo"] = "boo";

But when I want use this to create array serialization it finish with error: Failed to serialize XMP data

// Add an array of structures
Exiv2::XmpTextValue tv("");
tv.setXmpArrayType(Exiv2::XmpValue::xaSeq);
xmpData.add(Exiv2::XmpKey("Xmp.cn.foo"), &tv); // Set the array type.
tv.setXmpArrayType(Exiv2::XmpValue::xaNone);
tv.read("Birthday party");
xmpData.add(Exiv2::XmpKey("Xmp.cn.foo[1]/stRef:open"), &tv);

It is here some way how to create array serialization with custom property?

Thank you
Ladislav


Replies (1)

RE: Exiv2 programatically add custom property - Added by Robin Mills over 4 years ago

Ladislav

I had this conversation (by email) with a user last week!

Robin

On 22 May 2017, at 20:25, P M <pm@xxxxxxx.com> wrote:

hi Robin,

I am trying to integrate Exiv2 with our software, and running into an exception doing things like 
xmpData["Xmp.Camera.RigName"] = "1234ABCD5678";

Likewise, attempts to set some other common XMP entries lead to the same result:
xmpData["Xmp.Camera.SerialNumber"] = 12345678;

There's a file xmpsample.cpp with something very similar to this; what am I doing wrong?

In addition, I tried to follow xmpData.add(Exiv2::XmpKey(...), v.get()); routine - just to run into compiler errors. 
Are these XMP tags declared someplace, along with "prescribed" data types and methods?

Thank you,

My Response

I’m not a Metadata expert. I’m a retired Software Engineer. I know a lot about the Exiv2 code. I know very little about the meaning of the metadata or how various keys and values should be used.

Exiv2 has a predefined set of 69 namespaces which you can discover with the command:

529 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 exiv2 --verbose --version --grep xmlns
exiv2 0.26 001a00 (64 bit build)
xmlns=DICOM:http://ns.adobe.com/DICOM/
xmlns=GPano:http://ns.google.com/photos/1.0/panorama/
…

They are documented here: http://www.exiv2.org/metadata.html

If you want to add a namespace such as “Camera” you have to register it:

532 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -M'reg Camera http://clanmills.com/ns/Camera' -M'set Xmp.Camera.Make "123456789"' ~/Stonehenge.jpg 

Once the namespace is in your file, you don’t need to register it again to read data.

533 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -pa —grep Camera ~/Stonehenge.jpg
Xmp.Camera.Make                              XmpText     9  123456789
533 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ 

However, you do have to register it to write another key:

538 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -M'reg Camera http://clanmills.com/ns/Camera' -M'set Xmp.Camera.BodyColor Black' ~/Stonehenge.jpg 
539 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -px --grep Camera ~/Stonehenge.jpg 
Xmp.Camera.Make                              XmpText     9  123456789
Xmp.Camera.BodyColor                         XmpText     5  Black

You can change the URI associated with a namespace:

540 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -M'reg Camera http://clanmills.com/ns/Camora' -M'set Xmp.Camera.BodyColor Black' ~/Stonehenge.jpg 
Warning: Updating namespace URI for Camera from http://clanmills.com/ns/Camera/ to http://clanmills.com/ns/Camora/
541 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ 

In general, Exiv2 XMP support is a veneer over the Adobe XMPsdk. We neither add a metadata policeman, nor disable checks performed by Adobe. It appears to me that you can add any key to a namespace, even when it’s not mentioned in the spec. So, the “Dublin Core” namespace is documented here http://www.exiv2.org/tags-xmp-dc.html You can add keys which are not mentioned in the specification.

534 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -M'set Xmp.dc.Today "Tuesday"' ~/Stonehenge.jpg 
535 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $ exiv2 -px --grep Today ~/Stonehenge.jpg 
Xmp.dc.Today                                 XmpText     7  Tuesday
536 rmills@rmillsmbp:~/gnu/git/exiv2/test/data $

You should be able to figure out the APIs being used by the exiv2(.exe) application from the documentation. In general, almost everything in the library can be exercised from the exiv2(.exe) command-line program and you can build/debug that to see what’s going on.

For example, the command to register a namespace is implemented in src/actions.cpp as:

    void Modify::regNamespace(const ModifyCmd& modifyCmd)
    {
        if (Params::instance().verbose_) {
            std::cout << _("Reg ") << modifyCmd.key_ << "=\"" 
                      << modifyCmd.value_ << "\"" << std::endl;
        }
        Exiv2::XmpProperties::registerNs(modifyCmd.value_, modifyCmd.key_);
    }

547 rmills@rmillsmbp:~/gnu/git/exiv2/src $ exiv2 --verbose -M'reg Camera http://clanmills.com/ns/Comora' -M'set Xmp.Camera.BodyColor Black' ~/Stonehenge.jpg 
File 1/1: /Users/rmills/Stonehenge.jpg
Reg Camera="http://clanmills.com/ns/Comora" 
Warning: Updating namespace URI for Camera from http://clanmills.com/ns/Camora/ to http://clanmills.com/ns/Comora/
Set Xmp.Camera.BodyColor "Black" (XmpText)
548 rmills@rmillsmbp:~/gnu/git/exiv2/src $ 

Exiv2::XmpProperties::registerNs is documented here: http://www.exiv2.org/doc/classExiv2_1_1XmpProperties.html

You can query the Xmp data in an image with this command:

551 rmills@rmillsmbp:~/gnu/git/exiv2/src $ exiv2 -px ~/Stonehenge.jpg 
Xmp.xmp.Rating                               XmpText     9  123456789
Xmp.xmp.ModifyDate                           XmpText    25  2015-07-16T20:25:28+01:00
Xmp.Camera.Make                              XmpText     9  123456789
Xmp.Camera.BodyColor                         XmpText     5  Black
Xmp.dc.Today                                 XmpText     7  Tuesday
Xmp.dc.description                           LangAlt     1  lang="x-default" Classic View

And dump the raw XMP/xml as follows:

552 rmills@rmillsmbp:~/gnu/git/exiv2/src $ exiv2 -pX ~/Stonehenge.jpg  | xmllint --format -
<?xml version="1.0"?>
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:Camera="http://clanmills.com/ns/Comora/" xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="" xmp:Rating="123456789" xmp:ModifyDate="2015-07-16T20:25:28+01:00" Camera:Make="123456789" Camera:BodyColor="Black" dc:Today="Tuesday">
      <dc:description>
        <rdf:Alt>
          <rdf:li xml:lang="x-default">Classic View</rdf:li>
        </rdf:Alt>
      </dc:description>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
553 rmills@rmillsmbp:~/gnu/git/exiv2/src $ 

I hope that helps.

Robin

    (1-1/1)