Exemple #1
0
bool xmp_files_open(XmpFilePtr xf, const char *path, XmpOpenFileOptions options)
{
	CHECK_PTR(xf, false);
	RESET_ERROR;
	SXMPFiles *txf = (SXMPFiles*)xf;
	try {
		return txf->OpenFile(path, XMP_FT_UNKNOWN, options);
	}
	catch(const XMP_Error & e) {
		set_error(e);
	}
	return false;
}
Exemple #2
0
bool xmp_files_close(XmpFilePtr xf, XmpCloseFileOptions options)
{
	CHECK_PTR(xf, false);
	RESET_ERROR;
	try {
		SXMPFiles *txf = (SXMPFiles*)xf;
		txf->CloseFile(options);
	}
	catch(const XMP_Error & e) {
		set_error(e);
		return false;
	}
	return true;
}
Exemple #3
0
bool xmp_files_put_xmp(XmpFilePtr xf, XmpPtr xmp)
{
	CHECK_PTR(xf, false);
	CHECK_PTR(xmp, false);
	RESET_ERROR;
	SXMPFiles *txf = (SXMPFiles*)xf;
	
	try {
		txf->PutXMP(*(SXMPMeta*)xmp);
	}
	catch(const XMP_Error & e) {
		set_error(e);
		return false;
	}
	return true;
}
Exemple #4
0
bool xmp_files_can_put_xmp(XmpFilePtr xf, XmpPtr xmp)
{
	CHECK_PTR(xf, false);
	RESET_ERROR;
	SXMPFiles *txf = (SXMPFiles*)xf;
  bool result = false;

  try {
    result = txf->CanPutXMP(*(SXMPMeta*)xmp);
  }
	catch(const XMP_Error & e) {
		set_error(e);
		return false;
	}
  return result;
}
Exemple #5
0
bool xmp_files_get_xmp(XmpFilePtr xf, XmpPtr xmp)
{
	CHECK_PTR(xf, false);
	CHECK_PTR(xmp, false);
	RESET_ERROR;
	bool result = false;
	try {
		SXMPFiles *txf = (SXMPFiles*)xf;
		
		result = txf->GetXMP((SXMPMeta*)xmp);
	} 
	catch(const XMP_Error & e) {
		set_error(e);
	}
	return result;
}
Exemple #6
0
bool xmp_files_get_file_info(XmpFilePtr xf, XmpStringPtr filePath, XmpOpenFileOptions *options,
	XmpFileType * file_format, XmpFileFormatOptions *handler_flags)
{
	CHECK_PTR(xf, false);
	RESET_ERROR;
	
	bool result = false;	
	SXMPFiles *txf = (SXMPFiles*)xf;
	try {
		result = txf->GetFileInfo(STRING(filePath), (XMP_OptionBits *)options, 
			(XMP_FileFormat *)file_format, (XMP_OptionBits *)handler_flags);
	}
	catch(const XMP_Error & e) {
		set_error(e);
		return false;
	}
	
	return result;
}
Exemple #7
0
XmpPtr xmp_files_get_new_xmp(XmpFilePtr xf)
{
	CHECK_PTR(xf, NULL);
	RESET_ERROR;
	SXMPMeta *xmp = new SXMPMeta();
	SXMPFiles *txf = (SXMPFiles*)xf;

	bool result = false;
	try {
		result = txf->GetXMP(xmp);
		if(!result) {
			delete xmp;
			return NULL;
		}
	}
	catch(const XMP_Error & e) {
		set_error(e);
	}
	return (XmpPtr)xmp;
}
Exemple #8
0
static void
ProcessFile ( const char * fileName  )
{
    bool ok;
    char buffer [1000];

    SXMPMeta  xmpMeta;
    SXMPFiles xmpFile;
    XMP_FileFormat format;
    XMP_OptionBits openFlags, handlerFlags;
    XMP_PacketInfo xmpPacket;

    sprintf ( buffer, "Dumping main XMP for %s", fileName );
    WriteMinorLabel ( sLogFile, buffer );

    xmpFile.OpenFile ( fileName, kXMP_UnknownFile, kXMPFiles_OpenForRead );
    ok = xmpFile.GetFileInfo ( 0, &openFlags, &format, &handlerFlags );
    if ( ! ok ) return;

    fprintf ( sLogFile, "File info : format = \"%.4s\", handler flags = %.8X\n", &format, handlerFlags );
    fflush ( sLogFile );

    ok = xmpFile.GetXMP ( &xmpMeta, 0, &xmpPacket );
    if ( ! ok ) return;

    XMP_Int32 offset = (XMP_Int32)xmpPacket.offset;
    XMP_Int32 length = xmpPacket.length;
    fprintf ( sLogFile, "Packet info : offset = %d, length = %d\n", offset, length );
    fflush ( sLogFile );

    fprintf ( sLogFile, "\nInitial XMP from %s\n", fileName );
    xmpMeta.DumpObject ( DumpCallback, sLogFile );

    xmpFile.CloseFile();

}	// ProcessFile
Exemple #9
0
/**
* Initializes the toolkit and attempts to open a file for updating its metadata. Initially
* an attempt to open the file is done with a handler, if this fails then the file is opened with
* packet scanning. Once the file is open several properties are read and displayed in the console.
*
* Several properties are then modified, first by checking for their existence and then, if they 
* exist, by updating their values. The updated properties are then displayed again in the console. 
*
* Next a new XMP object is created from an RDF stream, the properties from the new XMP object are
* appended to the original XMP object and the updated properties are displayed in the console for
* last time.
*
* The updated XMP object is then serialized in different formats and written to text files.  Lastly,
* the modified XMP is written back to the resource file.
*/
int main ( int argc, const char * argv[] )
{
	if ( argc != 2 ) // 2 := command and 1 parameter
	{
		cout << "usage: ModifyingXMP (filename)" << endl;
		return 0;
	}

	string filename = string( argv[1] );

	if(!SXMPMeta::Initialize())
	{
		cout << "Could not initialize toolkit!";
		return -1;
	}
	
	XMP_OptionBits options = 0;
	#if UNIX_ENV
		options |= kXMPFiles_ServerMode;
	#endif
		
	// 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)
			{
				cout << status << endl;
				cout << filename << " is opened successfully" << endl;
				// Create the XMP object and get the XMP data
				SXMPMeta meta;
				myFile.GetXMP(&meta);

				// Display some properties in the console
				displayPropertyValues(&meta);
				
				///////////////////////////////////////////////////
				// Now modify the XMP
				if(meta.DoesPropertyExist(kXMP_NS_XMP, "CreatorTool"))
				{
					// Update xap:CreatorTool - we don't need to set any option bits
					meta.SetProperty(kXMP_NS_XMP, "CreatorTool", "Updated By XMP SDK", 0);
				}

				// Update the Metadata Date
				XMP_DateTime updatedTime;
				// Get the current time.  This is a UTC time automatically 
				// adjusted for the local time
				SXMPUtils::CurrentDateTime(&updatedTime);
				if(meta.DoesPropertyExist(kXMP_NS_XMP, "MetadataDate"))
				{
					meta.SetProperty_Date(kXMP_NS_XMP, "MetadataDate", updatedTime, 0);
				}
				
				// Add an item onto the dc:creator array
				// Note the options used, kXMP_PropArrayIsOrdered, if the array does not exist it will be created
				meta.AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Author Name", 0);
				meta.AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Another Author Name", 0);

				// Now update alt-text properties
				meta.SetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", "An English title");
				meta.SetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", "Un titre Francais");
				
				// Display the properties again to show changes
				cout << "After update:" << endl;
				displayPropertyValues(&meta);

				// Create a new XMP object from an RDF string
				SXMPMeta rdfMeta = createXMPFromRDF();

				// Append the newly created properties onto the original XMP object
				// This will:
				// a) Add ANY new TOP LEVEL properties in the source (rdfMeta) to the destination (meta)
				// b) Replace any top level properties in the source with the matching properties from the destination
				SXMPUtils::ApplyTemplate(&meta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties);

				// Display the properties again to show changes
				cout << "After Appending Properties:" << endl;
				displayPropertyValues(&meta);

				// Serialize the packet and write the buffer to a file
				// Let the padding be computed and use the default linefeed and indents without limits
				string metaBuffer;
				meta.SerializeToBuffer(&metaBuffer, 0, 0, "", "", 0);

				// Write the packet to a file as RDF
				writeRDFToFile(&metaBuffer, filename+"_XMP_RDF.txt");
								
				// Write the packet to a file but this time as compact RDF
				XMP_OptionBits outOpts = kXMP_OmitPacketWrapper | kXMP_UseCompactFormat;
				meta.SerializeToBuffer(&metaBuffer, outOpts);
				writeRDFToFile(&metaBuffer, filename+"_XMP_RDF_Compact.txt");

				// 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();
			}
			else
			{
				cout << "Unable to open " << filename << endl;
			}
		}
		catch(XMP_Error & e)
		{
			cout << "ERROR: " << e.GetErrMsg() << endl;
		}

		// Terminate the toolkit
		SXMPFiles::Terminate();
		SXMPMeta::Terminate();

	}
	else
	{
		cout << "Could not initialize SXMPFiles.";
		return -1;
	}
	
	return 0;
}
Exemple #10
0
/**
*	Initializes the toolkit and attempts to open a file for reading metadata.  Initially
* an attempt to open the file is done with a handler, if this fails then the file is opened with
* packet scanning. Once the file is open several properties are read and displayed in the console.  
* The XMP object is then dumped to a text file and the resource file is closed.
*/
int main ( int argc, const char * argv[] )
{
	if ( argc != 2 ) // 2 := command and 1 parameter
	{
		cout << "usage: ReadingXMP (filename)" << endl;
		return 0;
	}
	
	string filename = string( argv[1] );

	if(!SXMPMeta::Initialize())
	{
		cout << "Could not initialize toolkit!";
		return -1;
	}
	
	// Must initialize SXMPFiles before we use it
	if ( ! SXMPFiles::Initialize() )
	{
		cout << "Could not initialize SXMPFiles.";
		return -1;
	}
	
	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)
		{
			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
			string simpleValue;  //Stores the value for the property
			exists = meta.GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, NULL);
			if(exists)
				cout << "CreatorTool = " << simpleValue << endl;
			else
				simpleValue.clear();

			// Get the first element in the dc:creator array
			string elementValue;
			exists = meta.GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, NULL);
			if(exists)
				cout << "dc:creator = " << elementValue << endl;
			else
				elementValue.clear();

			// Get the the entire dc:subject array 
			string propValue;
			int arrSize = meta.CountArrayItems(kXMP_NS_DC, "subject");
			for(int i = 1; i <= arrSize;i++)
			{
				meta.GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0);
				cout << "dc:subject[" << i << "] = " << propValue << endl;
			}

			// Get the dc:title for English and French
			string itemValue;
			string actualLang;
			meta.GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", NULL, &itemValue, NULL);
			cout << "dc:title in English = " << itemValue << endl;

			meta.GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", NULL, &itemValue, NULL);
			cout << "dc:title in French = " << itemValue << endl;

			// Get dc:MetadataDate
			XMP_DateTime myDate;
			if(meta.GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, NULL))
			{
				// Convert the date struct into a convenient string and display it
				string myDateStr;
				SXMPUtils::ConvertFromDate(myDate, &myDateStr);
				cout << "meta:MetadataDate = " << myDateStr << endl;						 
			}

			// See if the flash struct exists and see if it was used
			string path, value;
			exists = meta.DoesStructFieldExist(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF,"Fired");
			if(exists)
			{
				bool flashFired;
				SXMPUtils::ComposeStructFieldPath(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Fired", &path);
				meta.GetProperty_Bool(kXMP_NS_EXIF, path.c_str(), &flashFired, NULL);
				string flash = (flashFired) ? "True" : "False";

				cout << "Flash Used = " << flash << endl;
			}

			// Dump the current xmp object to a file
			ofstream dumpFile;
			dumpFile.open("XMPDump.txt", ios::out);
			meta.DumpObject(DumpXMPToFile, &dumpFile);
			dumpFile.close();
			cout << endl << "XMP dumped to XMPDump.txt" << endl;

			// 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
		{
			cout << "Unable to open " << filename << endl;
		}
	}
	catch(XMP_Error & e)
	{
		cout << "ERROR: " << e.GetErrMsg() << endl;
	}

	// Terminate the toolkit
	SXMPFiles::Terminate();
	SXMPMeta::Terminate();

	return 0;
}
Exemple #11
0
/**
* Reads some metadata from a file and appends some custom XMP to it.  Then does several 
* iterations, using various iterators.  Each iteration is displayed in the console window.
*/
int main()
{
	if(SXMPMeta::Initialize())
	{
		XMP_OptionBits options = 0;
		#if UNIX_ENV
			options |= kXMPFiles_ServerMode;
		#endif
		if ( SXMPFiles::Initialize ( options ) ) {
			bool ok;
			SXMPFiles myFile;

			XMP_OptionBits opts = kXMPFiles_OpenForRead | kXMPFiles_OpenUseSmartHandler;
			ok = myFile.OpenFile("../../../testfiles/Image1.jpg", kXMP_UnknownFile, opts);
			if(ok)
			{
				SXMPMeta xmp;
				myFile.GetXMP(&xmp);

				// Add some custom metadata to the XMP object
				SXMPMeta custXMP(rdf, (XMP_StringLen) strlen(rdf));
				SXMPUtils::ApplyTemplate(&xmp, custXMP, kXMPTemplate_AddNewProperties);

				// Store any details from the iter.Next() call
				string schemaNS, propPath, propVal;

				// Only visit the immediate children that are leaf properties of the Dublin Core schema
				SXMPIterator dcLeafIter(xmp, kXMP_NS_DC, (kXMP_IterJustChildren | kXMP_IterJustLeafNodes));
				while(dcLeafIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit one property from the XMP Basic schema
				SXMPIterator xmpKeywordsIter(xmp, kXMP_NS_XMP, "Keywords", kXMP_IterJustLeafNodes);
				while(xmpKeywordsIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit the Dublin Core schema, omit any quailifiers and only
				// show the leaf properties
				SXMPIterator dcIter(xmp, kXMP_NS_DC, (kXMP_IterOmitQualifiers | kXMP_IterJustLeafNodes));
				while(dcIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit the Dublin Core schema, omit any quailifiers, 
				// show the leaf properties but only return the leaf name and not the full path
				SXMPIterator dcIter2(xmp, kXMP_NS_DC, (kXMP_IterOmitQualifiers | kXMP_IterJustLeafNodes | kXMP_IterJustLeafName));
				while(dcIter2.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Iterate over a single namespace.  Show all properties within
				// the Photoshop schema
				SXMPIterator exifIter(xmp, kXMP_NS_Photoshop);
				while(exifIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Just visit the leaf nodes of EXIF properties. That is just 
				// properties that may have values.
				SXMPIterator exifLeafIter(xmp, kXMP_NS_EXIF, kXMP_IterJustLeafNodes);
				while(exifLeafIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Iterate over all properties but skip the EXIF schema and skip the custom schema
				// and continue visiting nodes
				SXMPIterator skipExifIter (xmp);
				while(skipExifIter.Next(&schemaNS, &propPath, &propVal))
				{
					if(schemaNS == kXMP_NS_EXIF || schemaNS == kXMP_NS_SDK)
					{
						skipExifIter.Skip(kXMP_IterSkipSubtree);
					}
					else
					{ 
						cout << schemaNS << "  " << propPath << " = " << propVal << endl;
					}
				}

				cout << "----------------------------------" << endl;

				// Iterate over all properties but skip the EXIF schema
				// and any remaining siblings of the current node.
				SXMPIterator stopAfterExifIter ( xmp );
				while(stopAfterExifIter.Next(&schemaNS, &propPath, &propVal))
				{
					if(schemaNS == kXMP_NS_EXIF || schemaNS == kXMP_NS_SDK)
					{
						stopAfterExifIter.Skip(kXMP_IterSkipSiblings);
					}
					else
					{
						cout << schemaNS << "  " << propPath << " = " << propVal << endl;
					}
				}

				cout << "----------------------------------" << endl;

				//////////////////////////////////////////////////////////////////////////////////////

				// Iterate over the custom XMP

				// Visit the immediate children of this node. 
				// No qualifiers are visisted as they are below the property being visisted.
				SXMPIterator justChildrenIter(xmp, kXMP_NS_SDK, kXMP_IterJustChildren);
				while(justChildrenIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit the immediate children of this node but only those that may have values.
				// No qualifiers are visisted as they are below the property being visisted.
				SXMPIterator justChildrenAndLeafIter(xmp, kXMP_NS_SDK, (kXMP_IterJustChildren | kXMP_IterJustLeafNodes));
				while(justChildrenAndLeafIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit the leaf nodes of TopStructProperty
				SXMPIterator myTopStructIter(xmp, kXMP_NS_SDK, "MyTopStruct", kXMP_IterJustLeafNodes);
				while(myTopStructIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit the leaf nodes of the TopStructProperty but only return the names for 
				// the leaf components and not the full path
				SXMPIterator xmyTopStructIterShortNames(xmp, kXMP_NS_SDK, "MyTopStruct", (kXMP_IterJustLeafNodes | kXMP_IterJustLeafName));
				while(xmyTopStructIterShortNames.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit a property and all of the qualifiers
				SXMPIterator iterArrayProp (xmp, kXMP_NS_SDK, "ArrayWithStructures", kXMP_IterJustLeafNodes );
				while(iterArrayProp.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Visit a property and omit all of the qualifiers
				SXMPIterator iterArrayPropNoQual (xmp, kXMP_NS_SDK, "ArrayWithStructures", (kXMP_IterJustLeafNodes | kXMP_IterOmitQualifiers));
				while(iterArrayPropNoQual.Next(&schemaNS, &propPath, &propVal))
				{
					cout << propPath << " = " << propVal << endl;
				}

				cout << "----------------------------------" << endl;

				// Skip a subtree and continue onwards.  Once 'Item 4' is found then the we can skip all of the
				// siblings of the current node.  If the the current node were a top level node the iteration 
				// would be complete as all siblings would be skipped.  However, when 'Item 4' is found the current 
				// node is not at the top level so there are other nodes further up the tree that still need to be
				// visited.
				SXMPIterator skipIter (xmp, kXMP_NS_SDK, (kXMP_IterJustLeafNodes | kXMP_IterOmitQualifiers | kXMP_IterJustLeafName));
				while(skipIter.Next(&schemaNS, &propPath, &propVal))
				{
					if(propVal == "Item 4")
					{
						skipIter.Skip(kXMP_IterSkipSiblings);
					}
					else
					{
						cout << schemaNS << "  " << propPath << " = " << propVal << endl;
					}
				}

				/*
				// Visit all properties and qualifiers
				SXMPIterator allPropsIter(xmp);
				while(allPropsIter.Next(&schemaNS, &propPath, &propVal))
				{
					cout << schemaNS << "  " << propPath << " = " << propVal << endl;
				}
				*/
			}
		}
	}
	
	SXMPFiles::Terminate();
	SXMPMeta::Terminate();

	return 0;
}