Project

General

Profile

xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2

Added by Silke Werner over 10 years ago

Hi,

I am new to using Exiv2 in my software. I try to add some "service-information"
to a screenshot the user can make from my softwares GUI. Therefore i tried
adding some XMP data with an own namespace

Exiv2::XmpData xmpData;
Exiv2::XmpProperties::registerNs("MyCompany/", "RS");
xmpData["Xmp.RS.SerialNumber"] = "123456789";
xmpData["Xmp.RS.SoftwareVersion"] = "9.9.9.9";
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(rsFile.ToStdString());
assert(image.get() != 0);
image->setXmpData(xmpData);
image->writeMetadata();

---> creates an XMP-Block in the ImageFile, that i can view correctly with ExifToolGui
but something seems to be wrong, as reading the XMP-Data from this file using the
following lines of code fails!

Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]);
assert(image.get() != 0);
image->readMetadata(); ---> XMP_Error while decoding

If i look at the jpeg file i created in a Hex-Viewer, I can see lot ans lots of spaces ( Hex 20 )
between the xmpmeta end tag and the xpacket end tag.

I think those spaces might be the problem, but where do they come from!
I would be greatful for any hint on where I am doing something wrong...

Thanks
Silke


Replies (7)

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Andreas Huggel over 10 years ago

Silke,

Can you turn your code snippets into a small reproducer program for this problem and post it here if the problem persists?

Andreas

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Silke Werner over 10 years ago

Andreas,

Thanks for offering to have a look at my problem.

I am using exiv2 with VS2008 / WinXP.
To keep it simple I "exchanged" the source-code of your "xmpsample.cpp"
with the following lines of code.

int main(int argc, char* const argv[])
try {
if (argc != 2) {
std::cout << "Usage: " << argv0 << " file\n";
return 1;
} {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return -1;
}

std::string testFile = argv[1];
//Open File and write some XMP
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(testFile);
assert(image.get() != 0);
Exiv2::XmpData xmpDataW;
Exiv2::XmpProperties::registerNs("R&S/", "RS");
xmpDataW["Xmp.RS.SerialNumber"] = "12345678";
xmpDataW["Xmp.RS.SoftwareVersion"] = "9.9.9.9";
image->setXmpData(xmpDataW);
image->writeMetadata();
image.release();
Exiv2::Image::AutoPtr imageOpenSameFileAgain = Exiv2::ImageFactory::open(testFile);
assert(imageOpenSameFileAgain.get() != 0);
imageOpenSameFileAgain->readMetadata();
Exiv2::XmpData &xmpDataR = imageOpenSameFileAgain->xmpData();
if (xmpDataR.empty()) {
std::string error(argv[1]);
error += ": No XMP data found in the file";
throw Exiv2::Error(1, error);
}
else {
Exiv2::XmpData::const_iterator pos = xmpDataR.findKey(Exiv2::XmpKey("Xmp.RS.SoftwareVersion"));
if (pos == xmpDataR.end()) {
std::string error(argv[1]);
error += ": SoftwareVersion not found in XMP data of the file";
throw Exiv2::Error(1, error);
}
Exiv2::Value::AutoPtr v = pos->getValue();
assert(v->ok());
std::string sXMPValue = v->toString();
std::cout << sXMPValue << "\n";
}
return 0;
}
catch (Exiv2::AnyError& e)

and still get the same error I encountered in my own project
"writeMetadata" seems to work fine, but opening the same file
again and trying "readMetadata" results in an XMP_Error!

see attached files

Silke

testXMP.jpg (92.3 KB) testXMP.jpg the XMP data I wrote using this code
SpacesInHexViewOfImage.JPG (209 KB) SpacesInHexViewOfImage.JPG hex view of the xmp data in this jpeg

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Silke Werner over 10 years ago

sorry, the formatting somehow scrambled my little programm code, that i posted just a minute ago.
I try adding the source code file instead

Silke

xmpsample.cpp (1.87 KB) xmpsample.cpp "my version" of xmpsample.cpp

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Andreas Huggel over 10 years ago

That's a nice reproducer. I actually expected the issue would go away when I asked for it because I couldn't reproduce it with your initial information and the exiv2 tool. But now with the sample program, I also get an XMP parsing error.
The relevant difference to your initial post is the namespace URI: with MyCompany/ it works fine! The XMP toolkit doesn't like the ampersand (&) in your URI, "R&S/". Interestingly, replacing "&" with "&" also works but generates an Exiv2 warning. (That warning looks like a bug.)

Andreas

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Andreas Huggel over 10 years ago

Interestingly, replacing "&" with "&" also works

and this confuses Redmine too. I wrote

replacing "&" with "&amp;"

Andreas

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Silke Werner over 10 years ago

Hi Andreas,

Thanks for the fast reply!
My little program works fine, once I got rid of the "&" in my URI :-)

As it is with software development, I immediately stumbled across my next problem:-)
In the "real world" my serialnumber contains non ASCII-characters ( Utf-8 coding ),
which is why i wanted to use XMP as I read that unicode strings are possible with XMP.

Unfortunately I quickly found out that writing unicode values to XMP its not as easy as

Exiv2::XmpData xmpDataW;
xmpDataW["Xmp.RS.SerialNumber"] = "12345678-ä";

Searching the forums for a while I didn't find any thread about this topic.
Maybe you have some little code snippets that show how to set a unicode string as value for a XMP property?

Cheers
Silke

RE: xmp-data created in a jpeg using exiv2 cannot be read from this file using exiv2 - Added by Andreas Huggel over 10 years ago

Unfortunately I quickly found out that writing unicode values to XMP its not as easy as

Exiv2::XmpData xmpDataW;
xmpDataW["Xmp.RS.SerialNumber"] = "12345678-ä";

It shouldn't be much more difficult. Create an std::string s with your UTF encoded text and assign it to the property

std::string s = makeUtfEncodedText();
xmpDataW["Xmp.RS.SerialNumber"] = s;

Andreas

    (1-7/7)