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 "&"
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