tags:

views:

285

answers:

0

I use XMPkit to write custom meta data for any kind of images. the source is as shown below:

-(IBAction)AddKeyword:(id)sender {

SXMPMeta::Initialize();
SXMPFiles::Initialize();
string actualPrefix;

SXMPMeta::RegisterNamespace(kXMP_NS_SDK_EDIT, "xsdkEdit", &actualPrefix);
SXMPMeta::RegisterNamespace(kXMP_NS_SDK_USERS, "xsdkUser",&actualPrefix);

const char *theString=[@"/Users/administrator/Desktop/Sample Applications/images/Blue_Lagoon-poster.jpg" UTF8String];
string filename=theString;
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);
}
cout << status << endl;
cout << filename << " is opened successfully" << endl;
// Create the xmp object and get the xmp data
//SXMPMeta meta;
//myFile.GetXMP(&meta);

string elementValue;


if(ok)
 {
 if(!SXMPMeta::Initialize())
 {
  cout << "Could not initialize Toolkit!";
 }
 else
 {
  try
  {
   // Register the namespaces


   SXMPMeta meta;

   // Adds a user of the document
   // 1.  Add a new item onto the DocumentUsers array - 
   // 2.  Compose a path to the last element of DocumentUsers array
   // 3.  Add a value for the User field of the UserDetails structure
   // 4.  Add a qualifier to the User field.  Compose the path and set the value
   // 5.  Add a value for the DUID field of the UserDetails structure
   // 6.  Add a Contact property for the ContactDetails field of the UserDetails structure
   // 7.  Compose a path to the ContactDetails field of the UserDetails structure.
   // 8.  Create the fields of the ContactDetails structure and provide values

   // Create/Append the top level DocumentUsers array. If the array exists a new item will be added
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, "DocumentUsers", kXMP_PropValueIsArray, 0, kXMP_PropValueIsStruct);

   // Compose a path to the last item in the DocumentUsers array, this will point to a UserDetails structure
   string userItemPath;
   SXMPUtils::ComposeArrayItemPath(kXMP_NS_SDK_EDIT, "DocumentUsers", kXMP_ArrayLastItem, &userItemPath);


   // We now have a path to the structure, so we can set the field values
   meta.SetStructField(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "User", "John Smith", 0);
   // Add a qualifier to the User field, first compose the path to the field and then add the qualifier

   string userFieldPath;
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "User", &userFieldPath);
   meta.SetQualifier(kXMP_NS_SDK_EDIT, userFieldPath.c_str(), kXMP_NS_SDK_USERS, "Role", "Dev Engineer");

   // Compose a path to the DUID and set field value
   string duidPath;
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "DUID", &duidPath);
   meta.SetProperty_Int(kXMP_NS_SDK_EDIT, duidPath.c_str(), 2, 0);

   // Add the ContactDetails field, this field is a Contact structure
   meta.SetStructField(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "ContactDetails", 0, kXMP_PropValueIsStruct);

   // Compose a path to the field that has the ContactDetails structure
   string contactStructPath;
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "ContactDetails", &contactStructPath);

   // Now add the fields - all empty initially
   meta.SetStructField(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "Email", 0, kXMP_PropArrayIsAlternate); 
   meta.SetStructField(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "Telephone", 0, kXMP_PropValueIsArray);
   meta.SetStructField(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "BaseLocation", "", 0);

   // Add some values for the fields
   // Email: Get the path to the field named 'Email' in the ContactDetails structure and use it to append items
   string path;
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "Email", &path);
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, path.c_str(), 0, "[email protected]", 0);
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, path.c_str(), 0, "[email protected]", 0);

   // Telephone
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "Telephone", &path);
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, path.c_str(), 0, "89112", 0);
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, path.c_str(), 0, "84432", 0);

   // BaseLocation
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, contactStructPath.c_str(), kXMP_NS_SDK_USERS, "BaseLocation", &path);
   meta.SetProperty(kXMP_NS_SDK_EDIT, path.c_str(), "London", 0);

   // Add a user edit
   // 1.  Add an item (a structure) to the DocumentEdit array
   // 2.  Compose a path to the last item in the DocumentEdit array
   // 3.  Add fields and values to the EditDetails structure

   // Create the array
   meta.AppendArrayItem(kXMP_NS_SDK_EDIT, "DocumentEdit", kXMP_PropArrayIsOrdered, 0, kXMP_PropValueIsStruct);

   // Compose a path to the last item of the DocumentEdit array, this gives the path to the structure
   string lastItemPath;
   SXMPUtils::ComposeArrayItemPath(kXMP_NS_SDK_EDIT, "DocumentEdit", kXMP_ArrayLastItem, &lastItemPath);

   // Add the Date field
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, lastItemPath.c_str(), kXMP_NS_SDK_EDIT, "EditDate", &path);
   XMP_DateTime dt;
   SXMPUtils::CurrentDateTime(&dt);
   meta.SetProperty_Date(kXMP_NS_SDK_EDIT, path.c_str(), dt, 0);

   // Add the DUID field
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, lastItemPath.c_str(), kXMP_NS_SDK_EDIT, "DUID", &path);
   meta.SetProperty_Int(kXMP_NS_SDK_EDIT, path.c_str(), 2, 0);

   // Add the EditComments field
   SXMPUtils::ComposeStructFieldPath(kXMP_NS_SDK_EDIT, lastItemPath.c_str(), kXMP_NS_SDK_EDIT, "EditComments", &path);
   meta.SetLocalizedText(kXMP_NS_SDK_EDIT, path.c_str(), "en", "en-US", "Document created.", 0);

   // Add the EditTool field
   meta.SetStructField(kXMP_NS_SDK_EDIT, lastItemPath.c_str(), kXMP_NS_SDK_EDIT, "EditTool", "FrameXML", 0);

   // Write the RDF to a file
   cout << "writing RDF to file CS_RDF.txt" << endl;
   string metaBuffer;
   meta.SerializeToBuffer(&metaBuffer);
   writeRDFToFile(&metaBuffer, "CS_RDF.txt");

   SXMPMeta rdfMeta = createXMPFromRDF();
   SXMPUtils::AppendProperties(rdfMeta, &meta, (kXMPUtil_DoAllProperties | kXMPUtil_ReplaceOldValues ));

   string metaBuffer1;

   // Write the packet to a file but this time as compact RDF
   XMP_OptionBits outOpts = kXMP_OmitPacketWrapper | kXMP_UseCompactFormat;

   meta.SerializeToBuffer(&metaBuffer1, outOpts);

   // 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);
   }

   // 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();



   // Dump the XMP object
   cout << "dumping XMP object to file XMPDump1.txt" << endl;
   ofstream dumpFile;
   dumpFile.open("XMPDumpTest.txt", ios::out);
   meta.DumpObject(DumpXMPToFile, &dumpFile);
   dumpFile.close();

   // Dump the namespaces to a file
   cout << "dumping namespaces to file NameDump.txt" << endl;
   dumpFile.open("NameDumpTest.txt", ios::out);
   meta.DumpNamespaces(XMPFileDump, &dumpFile);
   dumpFile.close();

  }
  catch(XMP_Error & e)
  {
   cout << "ERROR: " << e.GetErrMsg();
  }

  SXMPMeta::Terminate();
 }

}



[arr addObject:t3];
[tableView reloadData]; }

Now to retrieve the meta data I use this code:

-(void)sourceFileValues_READ_Custom {

NSString  * pathOfTheFile  = @"/Users/administrator/Desktop/Sample Applications/images/Blue_Lagoon-poster.jpg";

[indicator setHidden:NO];
[indicator startAnimation:nil];

NSString *path=pathOfTheFile;
const char *theString=[path UTF8String];
string filename=theString;

// Must initialize SXMPFiles before we use it
if ( ! SXMPFiles::Initialize() )
{
 cout << "Could not initialize SXMPFiles.";
}

try{
 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)
 {
  cout << status << endl;
  cout << filename << " is opened successfully" << endl;
  // Create the xmp object and get the xmp data
  SXMPMeta meta;
  myFile.GetXMP(&meta);

  //bool exists;

  // Read a simple property

  //exists=meta.CountArrayItems(kXMP_NS_SDK_USERS, "User");

   string userFieldPath;
   string userItemPath;
   string elementValue;
   //meta.GetQualifier(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "User", &elementValue, 0);
  meta.GetStructField(kXMP_NS_SDK_EDIT, userItemPath.c_str(), kXMP_NS_SDK_USERS, "User", &elementValue, 0);


  const char *elementValue1= elementValue.c_str();
  NSString *elementvalue  = [NSString stringWithUTF8String:elementValue1];

     //[customkeyword addObject:@"User"];
    //[customvalue addObject:elementvalue];
  NSLog(@"The Value is:",elementvalue);
 } 

}
catch(XMP_Error & e)
{
 cout << "ERROR: " << e.GetErrMsg() << endl;
}

SXMPFiles::Terminate();
SXMPMeta::Terminate();
[indicator setHidden:YES];  }

But I get this as the output:

/Users/administrator/Desktop/Sample Applications/images/Blue_Lagoon-poster.jpg is opened successfully

ERROR: Empty struct name