Hello,
I'm building an iOS app that needs to attach some XMP data to a PNG image that is then sent to a web service.
I've been able to write the XMP and attach it to the image, but then the image is converted to a base64 string and sent to the web service.
When I retrieve back the image, the XMP data are gone.
This is how I write and read the data, I don't get any errors, just the XMP is gone:
+ (void)writeReference:(NSString *)referencia software:(NSString*)software version:(NSString*)softVersion fecha:(NSString*)fecha withFile:(NSString *)path error:(NSError **) error
{
std::string filename = [path UTF8String];
if(!SXMPMeta::Initialize())
{
std::cout<< "Could not initialize toolkit!";
if (error) {
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-1userInfo:@{@"message": @"Could not initialize toolkit!"}];
return;
}
}
XMP_OptionBits options = 0;
// Must initialize SXMPFiles before we use it
if(SXMPFiles::Initialize(options))
{
try
{
// Options to open the file with - open for editing and use a smart handler
XMP_OptionBits opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler;
bool ok;
SXMPFiles myFile;
std::string status = "";
// First we try and open the file
ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
if( ! ok )
{
status += "No smart handler available for " + filename + "\n";
status += "Trying packet scanning.\n";
// Now try using packet scanning
opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning;
ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
}
// If the file is open then read get the XMP data
if(ok)
{
std::cout<< status << std::endl;
std::cout<< filename << " is opened successfully"<< std::endl;
// Register the namespaces
std::string actualPrefix;
SXMPMeta::RegisterNamespace(kXMP_NS_myOwnNS, "reference", &actualPrefix);
// Create the XMP object and get the XMP data
SXMPMeta meta;
myFile.GetXMP(&meta);
///////////////////////////////////////////////////
// Now modify the XMP
meta.SetProperty(kXMP_NS_myOwnNS, "reference", [referencia UTF8String], 0);
meta.SetProperty(kXMP_NS_myOwnNS, "software", [software UTF8String], 0);
meta.SetProperty(kXMP_NS_myOwnNS, "versionSoftware", [softVersion UTF8String], 0);
meta.SetProperty(kXMP_NS_myOwnNS, "fecha", [fecha UTF8String], 0);
// Display the properties again to show changes
std::cout<< "After update:"<< std::endl;
std::string simpleValue; //Stores the value for the property
meta.GetProperty(kXMP_NS_myOwnNS, "reference", &simpleValue, 0);
std::cout<< "meta:referencia = "<< simpleValue << std::endl;
// Check we can put the XMP packet back into the file
if (myFile.CanPutXMP(meta)) {
// If so then update the file with the modified XMP
myFile.PutXMP(meta);
} else {
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-2userInfo:@{@"message": @"write error!"}];
}
// Close the SXMPFile. This *must* be called. The XMP is not
// actually written and the disk file is not closed until this call is made.
myFile.CloseFile();
}
else
{
std::cout<< "Unable to open "<< filename << std::endl;
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-3userInfo:@{@"message": @"Unable to open"}];
}
}
catch(XMP_Error& e)
{
std::cout<< "ERROR: "<< e.GetErrMsg() << std::endl;
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-3userInfo:@{@"message": @"write other error"}];
}
// Terminate the toolkit
SXMPFiles::Terminate();
SXMPMeta::Terminate();
}
else
{
std::cout<< "Could not initialize SXMPFiles.";
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-4userInfo:@{@"message": @"Could not initialize SXMPFiles."}];
}
}
+ (NSString *)readDataWithFile:(NSString *)path error:(NSError **)error
{
std::string referencia = ""; //Stores the value for the property
std::string software = "";
std::string softVersion = "";
std::string fecha = "";
std::string filename = [path UTF8String];
if(!SXMPMeta::Initialize())
{
std::cout<< "Could not initialize toolkit!";
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-1userInfo:@{@"message": @"Could not initialize toolkit!"}];
returnnil;
}
XMP_OptionBits options = 0;
// Must initialize SXMPFiles before we use it
if (!SXMPFiles::Initialize(options))
{
std::cout<< "Could not initialize SXMPFiles.";
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-4userInfo:@{@"message": @"Could not initialize SXMPFiles."}];
}
// Register the namespaces
std::string actualPrefix;
SXMPMeta::RegisterNamespace(kXMP_NS_myOwnNS, "reference", &actualPrefix);
try
{
// Options to open the file with - read only and use a file handler
XMP_OptionBits opts = kXMPFiles_OpenForRead | kXMPFiles_OpenUseSmartHandler;
bool ok;
SXMPFiles myFile;
std::string status = "";
// First we try and open the file
ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
if( ! ok )
{
status += "No smart handler available for " + filename + "\n";
status += "Trying packet scanning.\n";
// Now try using packet scanning
opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning;
ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts);
}
// If the file is open then read the metadata
if(ok)
{
std::cout<< status << std::endl;
std::cout<< filename << " is opened successfully"<< std::endl;
// Create the xmp object and get the xmp data
SXMPMeta meta;
myFile.GetXMP(&meta);
bool exists;
// Read a simple property
exists = meta.GetProperty(kXMP_NS_myOwnNS, "reference", &referencia, NULL);
exists = meta.GetProperty(kXMP_NS_myOwnNS, "software", &software, NULL);
exists = meta.GetProperty(kXMP_NS_myOwnNS, "versionSoftware", &softVersion, NULL);
exists = meta.GetProperty(kXMP_NS_myOwnNS, "fecha", &fecha, NULL);
if(exists)
{
std::cout<< "Reference = "<< referencia << std::endl;
std::cout<< "Software = "<< software << std::endl;
std::cout<< "Software Version = "<< softVersion << std::endl;
std::cout<< "Fecha = "<< fecha << std::endl;
}
else
{
referencia.clear();
software.clear();
softVersion.clear();
fecha.clear();
}
// Close the SXMPFile. The resource file is already closed if it was
// opened as read only but this call must still be made.
myFile.CloseFile();
}
else
{
std::cout<< "Unable to open "<< filename << std::endl;
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-3userInfo:@{@"message": @"Unable to open"}];
}
}
catch(XMP_Error& e)
{
std::cout<< "ERROR: "<< e.GetErrMsg() << std::endl;
*error = [NSErrorerrorWithDomain:XMPUtilsDomaincode:-3userInfo:@{@"message": @"read other error"}];
}
// Terminate the toolkit
SXMPFiles::Terminate();
SXMPMeta::Terminate();
return [NSStringstringWithUTF8String:referencia.c_str()];
}
Any idea?