summaryrefslogtreecommitdiff
path: root/samples/source
diff options
context:
space:
mode:
authorHubert Figuière <hub@figuiere.net>2016-12-07 00:03:00 -0500
committerHubert Figuière <hub@figuiere.net>2016-12-07 00:04:31 -0500
commit6071af09b5e263b63e57b28ab8a78484bc65e3fe (patch)
tree45f97ac82e5582684d889ede0fdacaf2c6eddf2e /samples/source
parent606a7df73750084a36fe69651e7b672333a76412 (diff)
Update to XMP SDK CC 2016.07
Diffstat (limited to 'samples/source')
-rw-r--r--samples/source/AML_AddComponent.cpp203
-rw-r--r--samples/source/AML_AddTimePartComponent.cpp191
-rw-r--r--samples/source/AML_SearchAndDeleteComponent.cpp205
-rw-r--r--samples/source/AML_Trackable.cpp164
-rw-r--r--samples/source/CustomSchema.cpp2
-rw-r--r--samples/source/CustomSchemaNewDOM.cpp196
-rw-r--r--samples/source/DumpMainXMP.cpp2
-rw-r--r--samples/source/DumpScannedXMP.cpp8
-rw-r--r--samples/source/ModifyingXMP.cpp2
-rw-r--r--samples/source/ModifyingXMPNewDOM.cpp429
-rw-r--r--samples/source/ReadingXMP.cpp5
-rw-r--r--samples/source/ReadingXMPNewDOM.cpp281
-rw-r--r--samples/source/UnicodeCorrectness.cpp2
-rw-r--r--samples/source/UnicodeParseSerialize.cpp2
-rw-r--r--samples/source/UnicodePerformance.cpp2
-rw-r--r--samples/source/XMPCoreCoverage.cpp2
-rw-r--r--samples/source/XMPFilesCoverage.cpp2
-rw-r--r--samples/source/XMPIterations.cpp2
-rw-r--r--samples/source/common/DumpFile.cpp308
-rw-r--r--samples/source/common/TagTree.cpp19
-rw-r--r--samples/source/common/TagTree.h3
-rw-r--r--samples/source/common/globals.h2
-rw-r--r--samples/source/dumpfile/main.cpp1
23 files changed, 1995 insertions, 38 deletions
diff --git a/samples/source/AML_AddComponent.cpp b/samples/source/AML_AddComponent.cpp
new file mode 100644
index 0000000..2713340
--- /dev/null
+++ b/samples/source/AML_AddComponent.cpp
@@ -0,0 +1,203 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the AssetRelationships.pdf. Creating generic parts, parts, AssetManager
+* for composed document. Demonstrate the use of AddComponent() for composite document and parts.
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 0
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+#include "XMPCore/Interfaces/IXMPDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IXMPDOMParser.h"
+#include "XMPCore/Interfaces/IXMPDOMSerializer.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPCore/Interfaces/IXMPSimpleNode.h"
+#include "XMPCore/Interfaces/IXMPStructureNode.h"
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+
+#include "XMPAssetManagement/XMPAssetManagementDefines.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPAssetManagement/XMPAssetManagement.h"
+#include "XMPAssetManagement/Interfaces/IAssetUtilities.h"
+#include "XMPAssetManagement/Interfaces/IAssetPart.h"
+#include "XMPAssetManagement/Interfaces/IComposedAssetManager.h"
+#include "XMPAssetManagement/Interfaces/ICompositionRelationship.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+
+using namespace std;
+
+static string GetStringFromFile(string& filename)
+{
+ string buffer;
+ string line;
+
+ ifstream in(filename);
+ if (in.is_open()) {
+ while (getline(in, line))
+ buffer = buffer + "\n" + line;
+ in.close();
+ }
+ return buffer;
+}
+
+void static SerializeIXMPMetadata(NS_XMPCORE::spIXMPMetadata imetadata, string outfile = "")
+{
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMSerializer DOMSerializer = DOMRegistry->CreateSerializer("rdf");
+ std::string targetfilebuffer = DOMSerializer->Serialize(imetadata)->c_str();
+
+ //std::cout << targetfilebuffer << std::endl;
+
+ //write into file
+ if (!outfile.empty()) {
+ ofstream out(outfile);
+ if (out.is_open()) {
+ out << targetfilebuffer;
+ out.close();
+ }
+ }
+}
+
+NS_XMPCORE::spIXMPMetadata static GetIXMPMetadataFromRDF(string filename)
+{
+ string buffer = GetStringFromFile(filename);
+
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMParser DOMParser = DOMRegistry->CreateParser("rdf");
+
+ NS_XMPCORE::spIXMPMetadata ixmpmeta = DOMParser->Parse(buffer.c_str());
+
+ return ixmpmeta;
+
+}
+
+
+/**
+* Initializes the toolkit (XMPCore, XMPFiles & XMPAssetManagement 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 opened, meta is obtained, from meta
+* ixmpmeta (DOM based Metadata object) is get. AssetManagement object is created from composed
+* ixmpmeta and a relationship is added into it. And later verifies for the same from ingredient
+* entry.
+*/
+
+int main ( int argc, const char * argv[] )
+{
+ string composed_file = "AddBasicPart_InSimpleDocument_input_composite_doc.xmp";
+ string component_file = "AddBasicPart_InSimpleDocument_input_component_doc.xmp";
+ string composed_out_file = "AddBasicPart_InSimpleDocument_OUTPUT_composite_doc.xmp";
+
+ if (!SXMPMeta::Initialize())
+ {
+ cout << "Could not initialize toolkit!";
+ return -1;
+ }
+
+ NS_XMPCORE::spIXMPMetadata& component_ixmp_meta = GetIXMPMetadataFromRDF(component_file);
+ NS_XMPCORE::spIXMPMetadata& composed_ixmp_meta = GetIXMPMetadataFromRDF(composed_file);
+ // Create the xmp object and get the xmp data
+ //componentFile.GetXMP(&component_sxmp_meta);
+
+ //Get IXMPMeta from SXMPMetadata
+ //component_ixmp_meta = component_sxmp_meta.GetIXMPMetadata();
+
+ //for both the files, metadata has been obtained, get IXMPMeta from SXMPMeta
+ NS_XMPCORE::pIXMPCoreObjectFactory factoryObj = NS_XMPCORE::IXMPCoreObjectFactory::GetInstance();
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientInitialize();
+
+ //create a standard generic part
+ NS_XMPASSETMANAGEMENT::spIAssetPart composedassetpart = NS_XMPASSETMANAGEMENT::IAssetPart::CreateStandardGenericPart(NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartComponentMetadata);
+
+ //create standard generic part
+ NS_XMPASSETMANAGEMENT::spIAssetPart componentassetpart = NS_XMPASSETMANAGEMENT::IAssetPart::CreateStandardGenericPart(NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartComponentContent);
+
+
+ //Check if composed / component is not trackable, make it
+ NS_XMPASSETMANAGEMENT::pIAssetUtilities utilityObj = NS_XMPASSETMANAGEMENT::IAssetUtilities::GetAssetUtilities();
+ if (utilityObj->IsTrackable(composed_ixmp_meta) == false)
+ utilityObj->MakeTrackable(composed_ixmp_meta);
+
+ if (utilityObj->IsTrackable(component_ixmp_meta) == false)
+ utilityObj->MakeTrackable(component_ixmp_meta);
+
+
+ //creating ComposedAssetManager
+ NS_XMPASSETMANAGEMENT::spIComposedAssetManager composedAsset = NS_XMPASSETMANAGEMENT::IComposedAssetManager::CreateComposedAssetManager(composed_ixmp_meta);
+
+ //call AddComponent API (toPart, from ixmpmeta, fromPart) to compose fromPart into composed doc at toPart
+ const NS_XMPCORE::spcIXMPStructureNode & component = component_ixmp_meta;
+
+ NS_XMPCORE::spcIXMPSimpleNode xmpMMInstanceIDNode = dynamic_pointer_cast<const NS_XMPCORE::IXMPSimpleNode>(component->GetNode(kXMP_NS_XMP_MM, "InstanceID"));
+
+ NS_XMPASSETMANAGEMENT::spICompositionRelationship relationshipNode = composedAsset->AddComponent(composedassetpart, component_ixmp_meta, componentassetpart);
+
+ //verify toPart and ComponentPart form Ingredients entry
+ NS_XMPASSETMANAGEMENT::spIXMPArrayNode spComposedIngredientsNode = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPArrayNode>(composed_ixmp_meta->GetNode(kXMP_NS_XMP_MM, "Ingredients"));
+ NS_XMPCORE::spIXMPStructureNode IngredientEntrynode = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPStructureNode>(spComposedIngredientsNode->GetNode(1));
+
+ NS_XMPCORE::spIXMPSimpleNode node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "toPart"));
+ std::string toPartString = node->GetValue()->c_str();
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "fromPart"));
+ std::string fromPartString = node->GetValue()->c_str();
+
+ //A relationship is mapping to a single entry in Ingredients. A relationship of composed assest's
+ //toPart, from ixmpmeta & fromPart has been created, add some more property using the relationship.
+ relationshipNode->SetComponentFilePath("/basefolder/subfolder/composedpath");
+ relationshipNode->SetMappingFunctionName("linear");
+ relationshipNode->SetMaskMarkersFlag(NS_XMPASSETMANAGEMENT::ICompositionRelationship::kCompositionMaskMarkersAll);
+
+ //Get the stRef:filePath
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "filePath"));
+ std::string filePathString = node->GetValue()->c_str();
+ cout << "stRef:filePath is " << filePathString.c_str() << endl;
+
+ //get the stRef:partMapping
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "partMapping"));
+ std::string partMappingString = node->GetValue()->c_str();
+ cout << "stRef:partMapping is " << partMappingString.c_str() << endl;
+
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "maskMarkers"));
+ std::string maskMarkersString = node->GetValue()->c_str();
+ cout << "stRef:makMarkers is " << maskMarkersString.c_str() << endl;
+
+ //verify the added node from pantry
+ SerializeIXMPMetadata(composed_ixmp_meta, composed_out_file);
+
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientTerminate();
+
+ // Terminate the toolkit
+ SXMPMeta::Terminate();
+
+
+ return 0;
+}
+
diff --git a/samples/source/AML_AddTimePartComponent.cpp b/samples/source/AML_AddTimePartComponent.cpp
new file mode 100644
index 0000000..dde904e
--- /dev/null
+++ b/samples/source/AML_AddTimePartComponent.cpp
@@ -0,0 +1,191 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the AssetRelationships.pdf. Demonstration of time part, how it's created,
+* it's values are set and how it is added into composed document using AddComponent.
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 0
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+#include "XMPCore/Interfaces/IXMPDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IXMPDOMParser.h"
+#include "XMPCore/Interfaces/IXMPDOMSerializer.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPCore/Interfaces/IXMPSimpleNode.h"
+#include "XMPCore/Interfaces/IXMPStructureNode.h"
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+#include "XMPAssetManagement/XMPAssetManagementDefines.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPAssetManagement/XMPAssetManagement.h"
+#include "XMPAssetManagement/Interfaces/IAssetUtilities.h"
+#include "XMPAssetManagement/Interfaces/IAssetPart.h"
+//time part
+#include "XMPAssetManagement/Interfaces/IAssetTimePart.h"
+
+#include "XMPAssetManagement/Interfaces/IComposedAssetManager.h"
+#include "XMPAssetManagement/Interfaces/ICompositionRelationship.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+
+using namespace std;
+
+static string GetStringFromFile(string& filename)
+{
+ string buffer;
+ string line;
+
+ ifstream in(filename);
+ if (in.is_open()) {
+ while (getline(in, line))
+ buffer = buffer + "\n" + line;
+ in.close();
+ }
+ return buffer;
+}
+
+void static SerializeIXMPMetadata(NS_XMPCORE::spIXMPMetadata imetadata, string outfile = "")
+{
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMSerializer DOMSerializer = DOMRegistry->CreateSerializer("rdf");
+ std::string targetfilebuffer = DOMSerializer->Serialize(imetadata)->c_str();
+
+ //std::cout << targetfilebuffer << std::endl;
+
+ //write into file
+ if (!outfile.empty()) {
+ ofstream out(outfile);
+ if (out.is_open()) {
+ out << targetfilebuffer;
+ out.close();
+ }
+ }
+}
+
+NS_XMPCORE::spIXMPMetadata static GetIXMPMetadataFromRDF(string filename)
+{
+ string buffer = GetStringFromFile(filename);
+
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMParser DOMParser = DOMRegistry->CreateParser("rdf");
+
+ NS_XMPCORE::spIXMPMetadata ixmpmeta = DOMParser->Parse(buffer.c_str());
+
+ return ixmpmeta;
+
+}
+
+
+
+/**
+* Initializes the toolkit (XMPCore, XMPFiles & XMPAssetManagement 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 opened, meta is obtained, from meta
+* ixmpmeta (DOM based Metadata object) is get. A time part is created, it's values are set,
+* and later used in AddComponent for composition.
+*/
+
+int main(int argc, const char * argv[])
+{
+ string composed_file = "AddBasicPart_InSimpleDocument_input_composite_doc.xmp";
+ string component_file = "AddBasicPart_InSimpleDocument_input_component_doc.xmp";
+ string outfilename = "AML_TimePartAddition_Sample_OutPut.xmp";
+
+ if (!SXMPMeta::Initialize())
+ {
+ cout << "Could not initialize toolkit!";
+ return -1;
+ }
+
+ NS_XMPCORE::spIXMPMetadata& composed_ixmp_meta = GetIXMPMetadataFromRDF(composed_file);
+ NS_XMPCORE::spIXMPMetadata& component_ixmp_meta = GetIXMPMetadataFromRDF(component_file);
+
+
+ //for both the files, metadata has been obtained, get IXMPMeta from SXMPMeta
+ NS_XMPCORE::pIXMPCoreObjectFactory factoryObj = NS_XMPCORE::IXMPCoreObjectFactory::GetInstance();
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientInitialize();
+
+ //Check if composed / component is not trackable, make it
+ NS_XMPASSETMANAGEMENT::pIAssetUtilities utilityObj = NS_XMPASSETMANAGEMENT::IAssetUtilities::GetAssetUtilities();
+ if (utilityObj->IsTrackable(composed_ixmp_meta) == false)
+ utilityObj->MakeTrackable(composed_ixmp_meta);
+ if (utilityObj->IsTrackable(component_ixmp_meta) == false)
+ utilityObj->MakeTrackable(component_ixmp_meta);
+
+ //create a time toPart
+ NS_XMPCOMMON::UInt64 toPartStartFrameCount = 0, toPartStartNumerator = 80, toPartStartBaseRate = 20;
+ NS_XMPCOMMON::UInt64 toPartDurationFrameCount = 2000, toPartDurationNumerator = 80, toPartDurationBaseRate = 20;
+ NS_XMPASSETMANAGEMENT::spIAssetTimePart composedassettimepart = NS_XMPASSETMANAGEMENT::IAssetTimePart::CreateStandardTimePart(NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartComponentMetadata);
+ composedassettimepart->SetFrameCountDuration(toPartStartFrameCount, toPartDurationFrameCount);
+ composedassettimepart->SetFrameRateForCountOfFrames(toPartStartNumerator, toPartStartBaseRate);
+ composedassettimepart->SetFrameRateForStartFrameCount(toPartDurationNumerator, toPartDurationBaseRate);
+
+ //component/fromPart
+ NS_XMPCOMMON::UInt64 fromPartStartFrameCount = 5000, fromPartStartNumerator = 80, fromPartStartBaseRate = 20;
+ NS_XMPCOMMON::UInt64 fromPartDurationFrameCount = 2000, fromPartDurationNumerator = 80, fromPartDurationBaseRate = 20;
+ NS_XMPASSETMANAGEMENT::spIAssetTimePart componentassettimepart = NS_XMPASSETMANAGEMENT::IAssetTimePart::CreateStandardTimePart(NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartComponentAudio);
+ componentassettimepart->SetFrameCountDuration(fromPartStartFrameCount, fromPartDurationFrameCount);
+ componentassettimepart->SetFrameRateForCountOfFrames(fromPartStartNumerator, fromPartStartBaseRate);
+ componentassettimepart->SetFrameRateForStartFrameCount(fromPartDurationNumerator, fromPartDurationBaseRate);
+
+ //creating ComposedAssetManager
+ NS_XMPASSETMANAGEMENT::spIComposedAssetManager composedAsset = NS_XMPASSETMANAGEMENT::IComposedAssetManager::CreateComposedAssetManager(composed_ixmp_meta);
+
+ //call AddComponent API (toPart, from ixmpmeta, fromPart) to compose fromPart into composed doc at toPart
+ //on calling the AddComponent, following will be entry in ingredient
+ //<stRef:toPart>/metadata/time:0f80s20d2000f80s80
+ //<stRef:fromPart>/content/audio/time:5000f80s20d2000f80s80
+ //for detail time format refer to XMP Specification Part 2 : Additional Properties sector 1.2.6.4 FrameRate
+ NS_XMPASSETMANAGEMENT::spICompositionRelationship relationshipNode = composedAsset->AddComponent(composedassettimepart, component_ixmp_meta, componentassettimepart);
+ //a mapping function
+ relationshipNode->SetMappingFunctionName("linear");
+
+ //assuming there are not ingredient entry, if there is fix the index, or iterate using iterator
+ //verify toPart and ComponentPart form Ingredients entry
+ NS_XMPASSETMANAGEMENT::spIXMPArrayNode spComposedIngredientsNode = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPArrayNode>(composed_ixmp_meta->GetNode(kXMP_NS_XMP_MM, "Ingredients"));
+ NS_XMPCORE::spIXMPStructureNode IngredientEntrynode = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPStructureNode>(spComposedIngredientsNode->GetNode(1));
+
+ NS_XMPCORE::spIXMPSimpleNode node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "toPart"));
+ std::string toPartString = node->GetValue()->c_str();
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(IngredientEntrynode->GetNode(kXMP_NS_XMP_ResourceRef, "fromPart"));
+ std::string fromPartString = node->GetValue()->c_str();
+
+ //verify the added node from pantry
+
+ SerializeIXMPMetadata(composed_ixmp_meta, outfilename);
+
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientTerminate();
+
+ SXMPMeta::Terminate();
+
+
+ return 0;
+}
+
diff --git a/samples/source/AML_SearchAndDeleteComponent.cpp b/samples/source/AML_SearchAndDeleteComponent.cpp
new file mode 100644
index 0000000..6fedcf7
--- /dev/null
+++ b/samples/source/AML_SearchAndDeleteComponent.cpp
@@ -0,0 +1,205 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the AssetRelationships.pdf. An AssetManagement Object is created from
+* composed metadata. Then a part is used for deleting all the relationship from composed Asset.
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 0
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+#include "XMPCore/Interfaces/IXMPDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IXMPDOMParser.h"
+#include "XMPCore/Interfaces/IXMPDOMSerializer.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPCore/Interfaces/IXMPSimpleNode.h"
+#include "XMPCore/Interfaces/IXMPStructureNode.h"
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+#include "XMPAssetManagement/XMPAssetManagementDefines.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPAssetManagement/XMPAssetManagement.h"
+#include "XMPAssetManagement/Interfaces/IAssetUtilities.h"
+#include "XMPAssetManagement/Interfaces/IAssetPart.h"
+#include "XMPAssetManagement/Interfaces/IComposedAssetManager.h"
+#include "XMPAssetManagement/Interfaces/ICompositionRelationship.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+
+using namespace std;
+
+static string GetStringFromFile(string filename)
+{
+ string buffer;
+ string line;
+
+ ifstream in(filename);
+ if (in.is_open()) {
+ while (getline(in, line))
+ buffer = buffer + "\n" + line;
+ in.close();
+ }
+ else {
+ cout << "Connot open file for converting into string\n";
+ }
+ return buffer;
+}
+
+void static SerializeIXMPMetadata(NS_XMPCORE::spIXMPMetadata imetadata, string outfile = "")
+{
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMSerializer DOMSerializer = DOMRegistry->CreateSerializer("rdf");
+ std::string targetfilebuffer = DOMSerializer->Serialize(imetadata)->c_str();
+
+ //std::cout << targetfilebuffer << std::endl;
+
+ //write into file
+ if (!outfile.empty()) {
+ ofstream out(outfile);
+ if (out.is_open()) {
+ out << targetfilebuffer;
+ out.close();
+ }
+ }
+}
+
+NS_XMPCORE::spIXMPMetadata static GetIXMPMetadataFromRDF(string filename)
+{
+ string buffer = GetStringFromFile(filename);
+
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMParser DOMParser = DOMRegistry->CreateParser("rdf");
+
+ NS_XMPCORE::spIXMPMetadata ixmpmeta = DOMParser->Parse(buffer.c_str());
+
+ return ixmpmeta;
+
+}
+
+
+/**
+* Initializes the toolkit (XMPCore, XMPFiles & XMPAssetManagement 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 opened, meta is obtained, from meta
+* ixmpmeta (DOM based Metadata object) is get. AssetManagement object is created from composed
+* ixmpmeta (the above ixmpmetadata). A part is created and used for search & deletion of that
+* part from relationship.
+*/
+
+int main(int argc, const char * argv[])
+{
+ string composed_file = "AML_SearchAndDelete_Sample_Input.xmp";
+ string composed_out_file = "AML_SearchAndDelete_Sample_Output.xmp";
+
+ if (!SXMPMeta::Initialize())
+ {
+ cout << "Could not initialize toolkit!";
+ return -1;
+ }
+ NS_XMPCORE::spIXMPMetadata& composed_ixmp_meta = GetIXMPMetadataFromRDF(composed_file);
+
+
+ //for both the files, metadata has been obtained, get IXMPMeta from SXMPMeta
+ NS_XMPCORE::pIXMPCoreObjectFactory factoryObj = NS_XMPCORE::IXMPCoreObjectFactory::GetInstance();
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientInitialize();
+
+ //Check if composed / component is not trackable, make it
+ NS_XMPASSETMANAGEMENT::pIAssetUtilities utilityObj = NS_XMPASSETMANAGEMENT::IAssetUtilities::GetAssetUtilities();
+ if (utilityObj->IsTrackable(composed_ixmp_meta) == false)
+ utilityObj->MakeTrackable(composed_ixmp_meta);
+
+ //composed/toPart
+ NS_XMPASSETMANAGEMENT::spIAssetPart composedassetpart = NS_XMPASSETMANAGEMENT::IAssetPart::CreateStandardGenericPart(NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartComponentMetadata);
+
+ //creating ComposedAssetManager
+ NS_XMPASSETMANAGEMENT::spIComposedAssetManager composedAsset = NS_XMPASSETMANAGEMENT::IComposedAssetManager::CreateComposedAssetManager(composed_ixmp_meta);
+
+ //Get list of all relationship and traverse it
+ NS_XMPASSETMANAGEMENT::spcICompositionRelationshipList relationshipNodes = composedAsset->GetAllRelationships();
+ for (NS_XMPASSETMANAGEMENT::cICompositionRelationshipList::iterator it = relationshipNodes->begin(); it != relationshipNodes->end(); ++it) {
+ //get part for part specific data
+ NS_XMPASSETMANAGEMENT::spcIAssetPart assetPart = (*it)->GetComponentPart();
+
+ switch (assetPart->GetType()) {
+ case NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeGeneric:
+ cout << "Part type is NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeGeneric";
+ break;
+ case NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeTime:
+ cout << "Part type is NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeTime";
+ break;
+ case NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeArtboard:
+ cout << "Part type is NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeArtboard";
+ break;
+ case NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeLayer:
+ cout << "Part type is NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypeLayer";
+ break;
+ case NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypePage:
+ cout << "Part type is NS_XMPASSETMANAGEMENT::IAssetPart_v1::kAssetPartTypePage";
+ break;
+ default:
+ ;
+ }
+ //get other relationship properties
+ NS_XMPCOMMON::spcIUTF8String filepath = (*it)->GetComponentFilePath();
+ }
+
+
+ //call GetRelationships(toPart) to get all relationship which matches a part value, and traverse it
+ relationshipNodes = composedAsset->GetRelationships(composedassetpart);
+ for (NS_XMPASSETMANAGEMENT::cICompositionRelationshipList::iterator it = relationshipNodes->begin(); it != relationshipNodes->end(); ++it) {
+ //get part for part specific data
+ NS_XMPASSETMANAGEMENT::spcIAssetPart assetPart = (*it)->GetComponentPart();
+
+ //get other relationship properties
+ NS_XMPCOMMON::spcIUTF8String filepath = (*it)->GetComponentFilePath();
+ }
+
+ ////// Remove relationship which maches the part
+ composedAsset->RemoveComponents(composedassetpart);
+
+ //Get all the relationship and check verify all the Relationship having the above part must not be present
+ relationshipNodes = composedAsset->GetAllRelationships();
+ for (NS_XMPASSETMANAGEMENT::cICompositionRelationshipList::iterator it = relationshipNodes->begin(); it != relationshipNodes->end(); ++it) {
+ //get part for part specific data
+ NS_XMPASSETMANAGEMENT::spcIAssetPart assetPart = (*it)->GetComponentPart();
+
+ //get other relationship properties
+ NS_XMPCOMMON::spcIUTF8String filepath = (*it)->GetComponentFilePath();
+ }
+
+ //verify the added node from pantry
+ SerializeIXMPMetadata(composed_ixmp_meta, composed_out_file);
+
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientTerminate();
+
+ SXMPMeta::Terminate();
+
+ return 0;
+}
+
diff --git a/samples/source/AML_Trackable.cpp b/samples/source/AML_Trackable.cpp
new file mode 100644
index 0000000..091b468
--- /dev/null
+++ b/samples/source/AML_Trackable.cpp
@@ -0,0 +1,164 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the Walkthrough 1 in the XMP Programmers Guide, Opening files and reading XMP.
+* Demonstrates the basic use of the XMPAssetManagement, obtaining XMP from a file and examining it
+* for tracking puropose. A document if trackable only if(xmpMM:OriginalDocumentID, xmpMM:DocumentID
+* and xmpMM:InstanceID) are present
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 0
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+#include "XMPCore/Interfaces/IXMPDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IXMPDOMParser.h"
+#include "XMPCore/Interfaces/IXMPDOMSerializer.h"
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCore/Interfaces/IXMPCoreObjectFactory.h"
+#include "XMPCore/Interfaces/IXMPSimpleNode.h"
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+#include "XMPCore/Interfaces/IXMPMetadata.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPAssetManagement/XMPAssetManagementFwdDeclarations.h"
+#include "XMPAssetManagement/XMPAssetManagement.h"
+#include "XMPAssetManagement/Interfaces/IAssetUtilities.h"
+
+using namespace std;
+
+void static SerializeIXMPMetadata(NS_XMPCORE::spIXMPMetadata imetadata, string outfile = "")
+{
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMSerializer DOMSerializer = DOMRegistry->CreateSerializer("rdf");
+ std::string targetfilebuffer = DOMSerializer->Serialize(imetadata)->c_str();
+
+ //std::cout << targetfilebuffer << std::endl;
+
+ //write into file
+ if (!outfile.empty()) {
+ ofstream out(outfile);
+ if (out.is_open()) {
+ out << targetfilebuffer;
+ out.close();
+ }
+ }
+}
+
+static string GetStringFromFile(string& filename)
+{
+ string buffer;
+ string line;
+
+ ifstream in(filename);
+ if (in.is_open()) {
+ while (getline(in, line))
+ buffer = buffer + "\n" + line;
+ in.close();
+ }
+ return buffer;
+}
+
+NS_XMPCORE::spIXMPMetadata static GetIXMPMetadataFromRDF(string filename)
+{
+ string buffer = GetStringFromFile(filename);
+
+ NS_XMPCORE::spIXMPDOMImplementationRegistry DOMRegistry = NS_XMPCORE::IXMPDOMImplementationRegistry::GetDOMImplementationRegistry();
+ NS_XMPCORE::spIXMPDOMParser DOMParser = DOMRegistry->CreateParser("rdf");
+
+ NS_XMPCORE::spIXMPMetadata ixmpmeta = DOMParser->Parse(buffer.c_str());
+
+ return ixmpmeta;
+
+}
+
+/**
+* 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, it's metadata is obtained. From which a check for IDs
+* is done, if missing these IDs are embedded.
+*/
+int main ( int argc, const char * argv[] )
+{
+ string input_file = "noids_source_input.xmp";
+ string output_file = "noids_source_output.xmp";
+
+ if (!SXMPMeta::Initialize())
+ {
+ cout << "Could not initialize toolkit!";
+ return -1;
+ }
+ XMP_OptionBits options = 0;
+
+ NS_XMPCORE::spIXMPMetadata ixmpmeta = GetIXMPMetadataFromRDF(input_file);
+
+ NS_XMPCORE::pIXMPCoreObjectFactory factoryObj = NS_XMPCORE::IXMPCoreObjectFactory::GetInstance();
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientInitialize();
+
+ NS_XMPASSETMANAGEMENT::pIAssetUtilities utilityObj = NS_XMPASSETMANAGEMENT::IAssetUtilities::GetAssetUtilities();
+ bool isTrackable = utilityObj->IsTrackable(ixmpmeta);
+
+ if (isTrackable) {
+ cout << "File " << input_file << " is Trackable" << endl;
+
+ NS_XMPCORE::spIXMPSimpleNode node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "OriginalDocumentID"));
+ if (node)
+ cout << "xmpMM:OriginalDocumentID is " << node->GetValue()->c_str() << endl;
+
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "DocumentID"));
+ if (node)
+ cout << "xmpMM:DocumentID is " << node->GetValue()->c_str() << endl;
+
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "InstanceID"));
+ if (node)
+ cout << "xmpMM:InstanceID is " << node->GetValue()->c_str() << endl;
+ }
+ else {
+ bool ret = utilityObj->MakeTrackable(ixmpmeta);
+
+ SerializeIXMPMetadata(ixmpmeta, output_file); //serialize ixmpmeta into o/p file
+
+ if (ret) {
+ NS_XMPCORE::spIXMPSimpleNode node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "OriginalDocumentID"));
+ if (node)
+ cout << "xmpMM:OriginalDocumentID is " << node->GetValue()->c_str() << endl;
+
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "DocumentID"));
+ if (node)
+ cout << "xmpMM:DocumentID is " << node->GetValue()->c_str() << endl;
+
+ node = NS_XMPCORE::dynamic_pointer_cast<NS_XMPCORE::IXMPSimpleNode>(ixmpmeta->GetNode(kXMP_NS_XMP_MM, "InstanceID"));
+ if (node)
+ cout << "xmpMM:InstanceID is " << node->GetValue()->c_str() << endl;
+ }
+ }
+
+ NS_XMPASSETMANAGEMENT::XMPAM_ClientTerminate();
+
+ SXMPMeta::Terminate();
+
+ return 0;
+}
+
diff --git a/samples/source/CustomSchema.cpp b/samples/source/CustomSchema.cpp
index 1cf0566..3e2beec 100644
--- a/samples/source/CustomSchema.cpp
+++ b/samples/source/CustomSchema.cpp
@@ -18,6 +18,8 @@
#include <string>
#include <cstring>
+//#define ENABLE_XMP_CPP_INTERFACE 1
+
// Must be defined to instantiate template classes
#define TXMP_STRING_TYPE std::string
diff --git a/samples/source/CustomSchemaNewDOM.cpp b/samples/source/CustomSchemaNewDOM.cpp
new file mode 100644
index 0000000..f8af1cc
--- /dev/null
+++ b/samples/source/CustomSchemaNewDOM.cpp
@@ -0,0 +1,196 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the Walkthrough 3 in the XMP Programmers Guide, Working with custom schema.
+*
+* Demonstrates how to work with a custom schema that has complex properties. It shows how to access
+* and modify properties with complex paths using the path composition utilities from the XMP API
+*/
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 0
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+
+#include "XMPCore/Interfaces/IDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IDOMParser.h"
+#include "XMPCore/Interfaces/IDOMSerializer.h"
+#include "XMPCore/Interfaces/IMetadata.h"
+#include "XMPCore/Interfaces/ICoreObjectFactory.h"
+#include "XMPCore/Interfaces/ISimpleNode.h"
+#include "XMPCore/Interfaces/IStructureNode.h"
+#include "XMPCore/Interfaces/IArrayNode.h"
+#include "XMPCore/Interfaces/INameSpacePrefixMap.h"
+//#include "XMPCore\Interfaces\IXMPCoreFwdDeclarations.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+
+
+// Made up namespace URI. Prefix will be xsdkEdit and xsdkUser
+const XMP_StringPtr kXMP_NS_SDK_EDIT = "http://ns.adobe/meta/sdk/Edit/";
+const XMP_StringPtr kXMP_NS_SDK_USERS = "http://ns.adobe/meta/sdk/User/";
+
+using namespace std;
+
+/**
+* Writes an XMP packet in XML format to a text file
+*
+* rdf - a pointer to the serialized XMP
+* filename - the name of the file to write to
+*/
+void writeRDFToFile(string * rdf, string filename)
+{
+ ofstream outFile;
+ outFile.open(filename.c_str(), ios::out);
+ outFile << *rdf;
+ outFile.close();
+}
+
+/**
+* Registers the namespaces that will be used with the custom schema. Then adds several new
+* properties to that schema. The properties are complex, containing nested arrays and structures.
+*
+* XMPFiles is not used in this sample, hence no external resource is updated with the metadata. The
+* created XMP object is serialized and written as RDF to a text file, the XMP object is dumped to
+* a text file and the registered namespaces are also dumped to a text file.*
+*
+*/
+int main(int argc, const char * argv[])
+{
+
+ if (!SXMPMeta::Initialize())
+ {
+ cout << "Could not initialize toolkit!";
+ return -1;
+ }
+
+ else
+ {
+ try
+ {
+ /*
+ AdobeXMPCore::spINameSpacePrefixMap map = AdobeXMPCore::INameSpacePrefixMap::CreateNameSpacePrefixMap();
+ map->Insert("xsdkEdit", AdobeXMPCommon::npos, kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos);
+ map->Insert("xsdkUser", AdobeXMPCommon::npos, kXMP_NS_SDK_USERS, AdobeXMPCommon::npos);
+ */
+
+ SXMPMeta::RegisterNamespace(kXMP_NS_SDK_EDIT, "xsdkEdit", NULL);
+ SXMPMeta::RegisterNamespace(kXMP_NS_SDK_USERS,"xsdkUser", NULL);
+
+ // 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 a top Level array node of DocumentUsers.
+ AdobeXMPCore::spIMetadata metaNode = AdobeXMPCore::IMetadata::CreateMetadata();
+ AdobeXMPCore::spIArrayNode DUarrayNode = AdobeXMPCore::IArrayNode::CreateUnorderedArrayNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "DocumentUsers", AdobeXMPCommon::npos);
+
+ // Append the UserDetails struct node as child of DocumentUsers array node
+ AdobeXMPCore::spIStructureNode DUstructNode1 = AdobeXMPCore::IStructureNode::CreateStructureNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "UserDetails", AdobeXMPCommon::npos);
+ DUarrayNode->AppendNode(DUstructNode1);
+
+ // Create simple nodes with property User and DUID as fields of UserDetails struct node
+ AdobeXMPCore::spINode UDsimpleNode1 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "User", AdobeXMPCommon::npos, "John Smith", AdobeXMPCommon::npos);
+ AdobeXMPCore::spINode UDsimpleNode2 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "DUID", AdobeXMPCommon::npos, "2", AdobeXMPCommon::npos);
+
+ // Create a structure ContactDetails as field of UserDetails structure
+ AdobeXMPCore::spIStructureNode UDstructNode3 = AdobeXMPCore::IStructureNode::CreateStructureNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "ContactDetails", AdobeXMPCommon::npos);
+
+ // Append all created fields as child of UserDetails struct node
+ DUstructNode1->AppendNode(UDsimpleNode1);
+ DUstructNode1->AppendNode(UDsimpleNode2);
+ DUstructNode1->AppendNode(UDstructNode3);
+
+ // Create an alternative Array E-mail as field of ContactDetails structure
+ AdobeXMPCore::spIArrayNode CDarrayNode1 = AdobeXMPCore::IArrayNode::CreateAlternativeArrayNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "E-Mail", AdobeXMPCommon::npos);
+
+ // Create an unordered Array Telephone as field of ContactDetails structure
+ AdobeXMPCore::spIArrayNode CDarrayNode2 = AdobeXMPCore::IArrayNode::CreateUnorderedArrayNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "Telephone", AdobeXMPCommon::npos);
+
+ // Create simple node with property BaseLocation
+ AdobeXMPCore::spINode CDsimpleNode3 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "BaseLocation", AdobeXMPCommon::npos, "London", AdobeXMPCommon::npos);
+
+ // Append all created fields as child of ContactDetails structure
+ UDstructNode3->AppendNode(CDarrayNode1);
+ UDstructNode3->AppendNode(CDarrayNode2);
+ UDstructNode3->AppendNode(CDsimpleNode3);
+
+ //Append items to E-Mail array
+ CDarrayNode1->AppendNode(AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "Mail1", AdobeXMPCommon::npos, "js@adobe.xmp.com", AdobeXMPCommon::npos));
+ CDarrayNode1->AppendNode(AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "Mail2", AdobeXMPCommon::npos, "js@adobe.home.com", AdobeXMPCommon::npos));
+
+ //Append items to Telephone array
+ CDarrayNode2->AppendNode(AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "Phone1", AdobeXMPCommon::npos, "89112", AdobeXMPCommon::npos));
+ CDarrayNode2->AppendNode(AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_USERS, AdobeXMPCommon::npos, "Phone2", AdobeXMPCommon::npos, "84432", AdobeXMPCommon::npos));
+
+ metaNode->AppendNode(DUarrayNode);
+
+ // Create unordered array DocumentEdit
+ AdobeXMPCore::spIArrayNode DEarrayNode = AdobeXMPCore::IArrayNode::CreateUnorderedArrayNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "DocumentEdit", AdobeXMPCommon::npos);
+
+ // Create structure EditDetails as arrayitem of DocumentEdit array
+ AdobeXMPCore::spIStructureNode DEstructNode1 = AdobeXMPCore::IStructureNode::CreateStructureNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "EditDetails", AdobeXMPCommon::npos);
+ DEarrayNode->AppendNode(DEstructNode1);
+
+ // Obtaining current date and time
+ XMP_DateTime dt;
+ SXMPUtils::CurrentDateTime(&dt);
+ string date;
+ SXMPUtils::ConvertFromDate(dt, &date);
+
+ // Creating simple node as field of EditDetails structure which will hold the current date
+ AdobeXMPCore::spINode EDsimpleNode1 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "EditDate", AdobeXMPCommon::npos, date.c_str(), AdobeXMPCommon::npos);
+
+ // Creating simple node Edittool as field of EditDetails structre
+ AdobeXMPCore::spINode EDsimpleNode2 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_SDK_EDIT, AdobeXMPCommon::npos, "EditTool", AdobeXMPCommon::npos, "FrameXML", AdobeXMPCommon::npos);
+
+ // Appending fields as child of EditDetails structure node
+ DEstructNode1->AppendNode(EDsimpleNode1);
+ DEstructNode1->AppendNode(EDsimpleNode2);
+ metaNode->AppendNode(DEarrayNode);
+
+ // Write the RDF to a file
+ cout << "writing RDF to file CS_RDF.txt" << endl;
+ AdobeXMPCore::spIDOMImplementationRegistry DOMRegistry = AdobeXMPCore::IDOMImplementationRegistry::GetDOMImplementationRegistry();
+ AdobeXMPCore::spIDOMSerializer serializer = DOMRegistry->GetSerializer("rdf");
+ std::string serializedPacket = serializer->Serialize(metaNode)->c_str();
+ writeRDFToFile(&serializedPacket, "CS_RDF.txt");
+
+ }
+ catch (XMP_Error & e)
+ {
+ cout << "ERROR: " << e.GetErrMsg();
+ }
+
+ }
+
+ return 0;
+
+}
diff --git a/samples/source/DumpMainXMP.cpp b/samples/source/DumpMainXMP.cpp
index 313665b..abd2604 100644
--- a/samples/source/DumpMainXMP.cpp
+++ b/samples/source/DumpMainXMP.cpp
@@ -21,6 +21,8 @@
#include <stdexcept>
#include <cerrno>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
#if XMP_WinBuild
#pragma warning ( disable : 4127 ) // conditional expression is constant
#pragma warning ( disable : 4996 ) // '...' was declared deprecated
diff --git a/samples/source/DumpScannedXMP.cpp b/samples/source/DumpScannedXMP.cpp
index 1acbc82..3df2019 100644
--- a/samples/source/DumpScannedXMP.cpp
+++ b/samples/source/DumpScannedXMP.cpp
@@ -21,6 +21,8 @@
#include <stdexcept>
#include <cerrno>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
#if XMP_WinBuild
#pragma warning ( disable : 4127 ) // conditional expression is constant
#pragma warning ( disable : 4996 ) // '...' was declared deprecated
@@ -31,7 +33,11 @@
#include "public/include/XMP.hpp"
#include "public/include/XMP.incl_cpp"
-#include "samples/source/common/XMPScanner.hpp"
+
+#include "XMPFiles/source/FormatSupport/XMPScanner.hpp"
+#include "XMPFiles/source/FormatSupport/XMPScanner.cpp"
+
+
using namespace std;
// =================================================================================================
diff --git a/samples/source/ModifyingXMP.cpp b/samples/source/ModifyingXMP.cpp
index 67d6f35..b334e70 100644
--- a/samples/source/ModifyingXMP.cpp
+++ b/samples/source/ModifyingXMP.cpp
@@ -16,6 +16,8 @@
#include <string>
#include <cstring>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
// Must be defined to instantiate template classes
#define TXMP_STRING_TYPE std::string
diff --git a/samples/source/ModifyingXMPNewDOM.cpp b/samples/source/ModifyingXMPNewDOM.cpp
new file mode 100644
index 0000000..23b9ff4
--- /dev/null
+++ b/samples/source/ModifyingXMPNewDOM.cpp
@@ -0,0 +1,429 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for Walkthrough 2 in the XMP Programmers Guide, Modifying XMP
+* Demonstrates how to open a file for update, and modifying the contained XMP before writing it back to the file.
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 1
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+#include "XMPCore/Interfaces/IDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IDOMParser.h"
+#include "XMPCore/Interfaces/IDOMSerializer.h"
+#include "XMPCore/Interfaces/IMetadata.h"
+#include "XMPCore/Interfaces/ICoreObjectFactory.h"
+#include "XMPCore/Interfaces/ISimpleNode.h"
+#include "XMPCore/Interfaces/IStructureNode.h"
+#include "XMPCore/Interfaces/IArrayNode.h"
+#include "XMPCore/Interfaces/INameSpacePrefixMap.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPCore/Interfaces/INodeIterator.h"
+
+
+using namespace std;
+using namespace AdobeXMPCore;
+
+void GetLocalizedText(spIArrayNode titleNode, const char* specificLang, const char* genericLang, string lang)
+{
+ AdobeXMPCore::spINode currItem;
+ const size_t itemLim = titleNode->ChildCount();
+ size_t itemNum;
+
+ spISimpleNode xmlLangQualifierNode, currItemNode;
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum)
+ {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ if (currItem != NULL)
+ {
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ if (!strcmp(xmlLangQualifierNode->GetValue()->c_str(), specificLang)) {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" << " " << lang << " " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+ }
+
+ if (*genericLang != 0)
+ {
+ // Look for the first partial match with the generic language.
+ const size_t genericLen = strlen(genericLang);
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum) {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ XMP_StringPtr currLang = xmlLangQualifierNode->GetValue()->c_str();
+ const size_t currLangSize = xmlLangQualifierNode->GetValue()->size();
+ if ((currLangSize >= genericLen) &&
+ !strncmp(currLang, genericLang, genericLen) &&
+ ((currLangSize == genericLen) || (currLang[genericLen] == '-')))
+ {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" << " " << lang << " " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+ }
+
+ // Look for an 'x-default' item.
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum) {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ if (!strcmp(xmlLangQualifierNode->GetValue()->c_str(), "x-default")) {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" << " " << lang << " " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+
+ // Everything failed, choose the first item.
+ currItem = titleNode->GetNodeAtIndex(1);
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" << " " << lang << " " << currItemNode->GetValue() << endl;
+ return;
+
+}
+
+
+
+/**
+* Display some property values to the console
+*
+* meta - a pointer to the XMP object that will have the properties read
+*/
+void displayPropertyValues(AdobeXMPCore::spIMetadata metaNode)
+{
+ // Read a simple property
+ AdobeXMPCore::spISimpleNode simpleNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "CreatorTool", AdobeXMPCommon::npos);
+ if (simpleNode != NULL)
+ {
+ string simpleNodeValue = simpleNode->GetValue()->c_str();
+ cout << "CreatorTool = " << simpleNodeValue << endl;
+ }
+
+ // Get the first element in the dc:creator array
+ AdobeXMPCore::spIArrayNode arrayNode = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "creator", AdobeXMPCommon::npos);
+ if (arrayNode != NULL)
+ {
+ AdobeXMPCore::spISimpleNode arrayNodeChild = arrayNode->GetSimpleNodeAtIndex(1);
+ if (arrayNodeChild != NULL)
+ {
+ string arrayNodeChildValue = arrayNodeChild->GetValue()->c_str();
+ cout << "dc:creator[1] = " << arrayNodeChildValue << endl;
+ }
+
+ AdobeXMPCore::spISimpleNode arrayNodeChild1 = arrayNode->GetSimpleNodeAtIndex(2);
+ if (arrayNodeChild1 != NULL)
+ {
+ string arrayNodeChildValue1 = arrayNodeChild1->GetValue()->c_str();
+ cout << "dc:creator[2] = " << arrayNodeChildValue1 << endl;
+ }
+ }
+
+ // Get the the entire dc:subject array
+ AdobeXMPCore::spIArrayNode subjectArray = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "subject", AdobeXMPCommon::npos);
+ if (subjectArray != NULL)
+ {
+ int arraySize = subjectArray->ChildCount();
+ for (int i = 1; i <= arraySize; i++)
+ {
+ AdobeXMPCore::spISimpleNode subjectChild = subjectArray->GetSimpleNodeAtIndex(i);
+ if (subjectChild != NULL)
+ {
+ string propValue = subjectChild->GetValue()->c_str();
+ cout << "dc:subject[" << i << "] = " << propValue << endl;
+ }
+ }
+ }
+ // Get the dc:title for English and French
+ AdobeXMPCore::spIArrayNode titleNode = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "title", AdobeXMPCommon::npos);
+ if (titleNode != NULL)
+ {
+ GetLocalizedText(titleNode, "en-US", "en", "English");
+ GetLocalizedText(titleNode, "fr-FR", "fr", "French");
+ }
+
+ // Get dc:MetadataDate
+ AdobeXMPCore::spISimpleNode dateNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "MetadataDate", AdobeXMPCommon::npos);
+ string date = dateNode->GetValue()->c_str();
+ cout << "meta:MetadataDate = " << date << endl;
+
+
+ // See if the flash struct exists and see if it was used
+ AdobeXMPCore::spIStructureNode flashNode = metaNode->GetStructureNode(kXMP_NS_EXIF, AdobeXMPCommon::npos, "Flash", AdobeXMPCommon::npos);
+ if (flashNode != NULL)
+ {
+ AdobeXMPCore::spISimpleNode field = flashNode->GetSimpleNode(kXMP_NS_EXIF, AdobeXMPCommon::npos, "Fired", AdobeXMPCommon::npos);
+ if (field != NULL)
+ {
+ string fieldValue = field->GetValue()->c_str();
+ cout << "Flash Used = " << fieldValue << endl;
+ }
+ }
+
+
+ cout << "----------------------------------------" << endl;
+}
+
+/**
+* Creates an XMP object from an RDF string. The string is used to
+* to simulate creating and XMP object from multiple input buffers.
+* The last call to ParseFromBuffer has no kXMP_ParseMoreBuffers options,
+* thereby indicating this is the last input buffer.
+*/
+SXMPMeta createXMPFromRDF()
+{
+ const char * rdf =
+ "<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>"
+ "<rdf:Description rdf:about='' xmlns:dc='http://purl.org/dc/elements/1.1/'>"
+ "<dc:subject>"
+ "<rdf:Bag>"
+ "<rdf:li>XMP</rdf:li>"
+ "<rdf:li>SDK</rdf:li>"
+ "<rdf:li>Sample</rdf:li>"
+ "</rdf:Bag>"
+ "</dc:subject>"
+ "<dc:format>image/tiff</dc:format>"
+ "</rdf:Description>"
+ "</rdf:RDF>";
+
+ SXMPMeta meta;
+ // Loop over the rdf string and create the XMP object
+ // 10 characters at a time
+ int i;
+ for (i = 0; i < (long)strlen(rdf) - 10; i += 10)
+ {
+ meta.ParseFromBuffer(&rdf[i], 10, kXMP_ParseMoreBuffers);
+ }
+
+ // The last call has no kXMP_ParseMoreBuffers options, signifying
+ // this is the last input buffer
+ meta.ParseFromBuffer(&rdf[i], (XMP_StringLen)strlen(rdf) - i);
+ return meta;
+
+}
+
+
+/**
+* Writes an XMP packet in XML format to a text file
+*
+* rdf - a pointer to the serialized XMP
+* filename - the name of the file to write to
+*/
+void writeRDFToFile(string * rdf, string filename)
+{
+ ofstream outFile;
+ outFile.open(filename.c_str(), ios::out);
+ outFile << *rdf;
+ outFile.close();
+}
+
+/**
+* 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);
+ string buffer;
+ meta.SerializeToBuffer(&buffer);
+ AdobeXMPCore::spIDOMImplementationRegistry DOMRegistry = AdobeXMPCore::IDOMImplementationRegistry::GetDOMImplementationRegistry();
+ AdobeXMPCore::spIDOMParser parser = DOMRegistry->GetParser("rdf");
+ AdobeXMPCore::spIMetadata metaNode = parser->Parse(buffer.c_str(), buffer.size());
+
+ // Display some properties in the console
+ displayPropertyValues(metaNode);
+
+ ///////////////////////////////////////////////////
+ // Now modify the XMP
+ AdobeXMPCore::spISimpleNode simpleNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "CreatorTool", AdobeXMPCommon::npos);
+
+ if (simpleNode!=NULL)
+ simpleNode->SetValue("Updated By XMP SDK", AdobeXMPCommon::npos);
+
+ // Update the MetadataDate
+ XMP_DateTime dt;
+ SXMPUtils::CurrentDateTime(&dt);
+ string date;
+ SXMPUtils::ConvertFromDate(dt, &date);
+ AdobeXMPCore::spISimpleNode dateNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "MetadataDate", AdobeXMPCommon::npos);
+ dateNode->SetValue(date.c_str(), AdobeXMPCommon::npos);
+
+ // Add an item onto the dc:creator array
+ AdobeXMPCore::spIArrayNode arrayNode = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "creator", AdobeXMPCommon::npos);
+
+ // If the array does not exist, it will be created
+ if (arrayNode == NULL)
+ {
+ AdobeXMPCore::spIArrayNode arrayNode = AdobeXMPCore::IArrayNode::CreateUnorderedArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "creator", AdobeXMPCommon::npos);
+ AdobeXMPCore::spINode creatorChild1 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_DC, AdobeXMPCommon::npos, "AuthorName", AdobeXMPCommon::npos, "abc", AdobeXMPCommon::npos);
+ AdobeXMPCore::spINode creatorChild2 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_DC, AdobeXMPCommon::npos, "AnotherAuthorName", AdobeXMPCommon::npos, "xyz", AdobeXMPCommon::npos);
+ arrayNode->AppendNode(creatorChild1);
+ arrayNode->AppendNode(creatorChild2);
+
+ }
+ // If it exists, then just append the nodes to array node
+ else
+ {
+ AdobeXMPCore::spINode creatorChild1 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_DC, AdobeXMPCommon::npos, "AuthorName", AdobeXMPCommon::npos, "abc", AdobeXMPCommon::npos);
+ AdobeXMPCore::spINode creatorChild2 = AdobeXMPCore::ISimpleNode::CreateSimpleNode(kXMP_NS_DC, AdobeXMPCommon::npos, "AnotherAuthorName", AdobeXMPCommon::npos, "xyz", AdobeXMPCommon::npos);
+ arrayNode->AppendNode(creatorChild1);
+ arrayNode->AppendNode(creatorChild2);
+ }
+
+ // Display the properties again to show changes
+ cout << "After update:" << endl;
+ displayPropertyValues(metaNode);
+
+ AdobeXMPCore::spIDOMSerializer serializer = DOMRegistry->GetSerializer("rdf");
+ AdobeXMPCore:: spcINameSpacePrefixMap defaultMap = AdobeXMPCore::INameSpacePrefixMap::GetDefaultNameSpacePrefixMap();
+ std::string serializedPacket = serializer->Serialize(metaNode, defaultMap)->c_str();
+ SXMPMeta fileMeta;
+ fileMeta.ParseFromBuffer(serializedPacket.c_str(), serializedPacket.length());
+
+ // 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 (fileMeta)
+ // b) Replace any top level properties in the source with the matching properties from the destination
+ SXMPUtils::ApplyTemplate(&fileMeta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties);
+
+ // 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 newBuffer;
+ fileMeta.SerializeToBuffer(&newBuffer);
+
+ // Display the properties again to show changes
+ cout << "After Appending Properties:" << endl;
+ AdobeXMPCore::spIMetadata newMetaNode = parser->Parse(newBuffer.c_str(), newBuffer.size());
+ displayPropertyValues(newMetaNode);
+
+ // Write the packet to a file as RDF
+ writeRDFToFile(&newBuffer, filename + "_XMP_RDF.txt");
+
+ // Check we can put the XMP packet back into the file
+ if (myFile.CanPutXMP(fileMeta))
+ {
+ // If so then update the file with the modified XMP
+ myFile.PutXMP(fileMeta);
+ }
+
+ // 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;
+}
+
+
diff --git a/samples/source/ReadingXMP.cpp b/samples/source/ReadingXMP.cpp
index bfcf56c..fd6da47 100644
--- a/samples/source/ReadingXMP.cpp
+++ b/samples/source/ReadingXMP.cpp
@@ -17,6 +17,8 @@
#include <string>
#include <cstring>
+//#define ENABLE_XMP_CPP_INTERFACE 1
+
// Must be defined to instantiate template classes
#define TXMP_STRING_TYPE std::string
@@ -34,6 +36,7 @@
using namespace std;
+
/**
* Client defined callback function to dump XMP to a file. In this case an output file stream is used
* to write a buffer, of length bufferSize, to a text file. This callback is called multiple
@@ -180,6 +183,8 @@ int main ( int argc, const char * argv[] )
cout << "Flash Used = " << flash << endl;
}
+
+
// Dump the current xmp object to a file
ofstream dumpFile;
dumpFile.open("XMPDump.txt", ios::out);
diff --git a/samples/source/ReadingXMPNewDOM.cpp b/samples/source/ReadingXMPNewDOM.cpp
new file mode 100644
index 0000000..86b603e
--- /dev/null
+++ b/samples/source/ReadingXMPNewDOM.cpp
@@ -0,0 +1,281 @@
+// =================================================================================================
+// Copyright 2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+/**
+* Tutorial solution for the Walkthrough 1 in the XMP Programmers Guide, Opening files and reading XMP.
+* Demonstrates the basic use of the XMPFiles and XMPCore components, obtaining read-only XMP from a file
+* and examining it through the XMP object.
+*/
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
+// Must be defined to instantiate template classes
+#define TXMP_STRING_TYPE std::string
+
+// Must be defined to give access to XMPFiles
+#define XMP_INCLUDE_XMPFILES 1
+
+#define ENABLE_NEW_DOM_MODEL 1
+
+// Ensure XMP templates are instantiated
+#include "public/include/XMP.incl_cpp"
+
+// Provide access to the API
+#include "public/include/XMP.hpp"
+
+#include "XMPCore/Interfaces/IDOMImplementationRegistry.h"
+#include "XMPCore/Interfaces/IDOMParser.h"
+#include "XMPCore/Interfaces/IDOMSerializer.h"
+#include "XMPCore/Interfaces/IMetadata.h"
+#include "XMPCore/Interfaces/ICoreObjectFactory.h"
+#include "XMPCore/Interfaces/ISimpleNode.h"
+#include "XMPCore/Interfaces/IStructureNode.h"
+#include "XMPCore/Interfaces/IArrayNode.h"
+#include "XMPCore/Interfaces/INameSpacePrefixMap.h"
+#include "XMPCommon/Interfaces/IUTF8String.h"
+#include "XMPCore/Interfaces/INodeIterator.h"
+
+using namespace std;
+using namespace AdobeXMPCore;
+
+
+void GetLocalizedText(spIArrayNode titleNode, const char* specificLang, const char* genericLang, string lang)
+{
+ AdobeXMPCore::spINode currItem;
+ const size_t itemLim = titleNode->ChildCount();
+ size_t itemNum;
+
+ spISimpleNode xmlLangQualifierNode, currItemNode;
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum)
+ {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ if (currItem != NULL)
+ {
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ if (!strcmp(xmlLangQualifierNode->GetValue()->c_str(), specificLang)) {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" <<" " << lang <<" " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+ }
+
+ if (*genericLang != 0)
+ {
+ // Look for the first partial match with the generic language.
+ const size_t genericLen = strlen(genericLang);
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum) {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ XMP_StringPtr currLang = xmlLangQualifierNode->GetValue()->c_str();
+ const size_t currLangSize = xmlLangQualifierNode->GetValue()->size();
+ if ((currLangSize >= genericLen) &&
+ !strncmp(currLang, genericLang, genericLen) &&
+ ((currLangSize == genericLen) || (currLang[genericLen] == '-')))
+ {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" <<" " << lang << " " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+ }
+
+ // Look for an 'x-default' item.
+ for (itemNum = 1; itemNum <= itemLim; ++itemNum) {
+ currItem = titleNode->GetNodeAtIndex(itemNum);
+ xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode();
+ if (!strcmp(xmlLangQualifierNode->GetValue()->c_str(), "x-default")) {
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" <<" " << lang <<" " << currItemNode->GetValue()->c_str() << endl;
+ return;
+ }
+ }
+
+ // Everything failed, choose the first item.
+ currItem = titleNode->GetNodeAtIndex(1);
+ currItemNode = currItem->ConvertToSimpleNode();
+ cout << "dc:title in" <<" " <<lang << " "<< currItemNode->GetValue() << endl;
+ return;
+
+}
+
+
+
+void writeRDFToFile(string * rdf, string filename)
+{
+ ofstream outFile;
+ outFile.open(filename.c_str(), ios::out);
+ outFile << *rdf;
+ outFile.close();
+}
+
+
+/**
+* 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;
+ }
+ XMP_OptionBits options = 0;
+#if UNIX_ENV
+ options |= kXMPFiles_ServerMode;
+#endif
+ // Must initialize SXMPFiles before we use it
+ if (!SXMPFiles::Initialize(options))
+ {
+ 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);
+ string buffer;
+ meta.SerializeToBuffer(&buffer);
+ writeRDFToFile(&buffer, "Image1RDF.txt");
+ AdobeXMPCore::spIDOMImplementationRegistry DOMRegistry = AdobeXMPCore::IDOMImplementationRegistry::GetDOMImplementationRegistry();
+ AdobeXMPCore:: spIDOMParser parser = DOMRegistry->GetParser("rdf");
+ AdobeXMPCore ::spIMetadata metaNode = parser->Parse(buffer.c_str(), buffer.size());
+
+ // Read a simple property
+ AdobeXMPCore::spISimpleNode simpleNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "CreatorTool", AdobeXMPCommon::npos);
+ if (simpleNode != NULL)
+ {
+ string simpleNodeValue = simpleNode->GetValue()->c_str();
+ cout << "CreatorTool = " << simpleNodeValue << endl;
+ }
+
+ // Get the first element in the dc:creator array
+ AdobeXMPCore::spIArrayNode arrayNode = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "creator", AdobeXMPCommon::npos);
+ if (arrayNode != NULL)
+ {
+ AdobeXMPCore::spISimpleNode arrayNodeChild = arrayNode->GetSimpleNodeAtIndex(1);
+ if (arrayNodeChild != NULL)
+ {
+ string arrayNodeChildValue = arrayNodeChild->GetValue()->c_str();
+ cout << "dc:creator = " << arrayNodeChildValue << endl;
+ }
+ }
+
+ // Get the the entire dc:subject array
+ AdobeXMPCore::spIArrayNode subjectArray = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "subject", AdobeXMPCommon::npos);
+ if (subjectArray != NULL)
+ {
+ int arraySize = subjectArray->ChildCount();
+ for (int i = 1; i <= arraySize; i++)
+ {
+ AdobeXMPCore::spISimpleNode subjectChild = subjectArray->GetSimpleNodeAtIndex(i);
+ if (subjectChild != NULL)
+ {
+ string propValue = subjectChild->GetValue()->c_str();
+ cout << "dc:subject[" << i << "] = " << propValue << endl;
+ }
+ }
+ }
+
+ // Get the dc:title for English and French
+
+
+ AdobeXMPCore::spIArrayNode titleNode = metaNode->GetArrayNode(kXMP_NS_DC, AdobeXMPCommon::npos, "title", AdobeXMPCommon::npos);
+ if (titleNode != NULL)
+ {
+ GetLocalizedText(titleNode, "en-US", "en", "English");
+ GetLocalizedText(titleNode, "fr-FR", "fr", "French");
+ }
+
+
+
+ // Get dc:MetadataDate
+ AdobeXMPCore::spISimpleNode dateNode = metaNode->GetSimpleNode(kXMP_NS_XMP, AdobeXMPCommon::npos, "MetadataDate", AdobeXMPCommon::npos);
+ string date = dateNode->GetValue()->c_str();
+ cout << "meta:MetadataDate = " << date << endl;
+
+
+ // See if the flash struct exists and see if it was used
+ AdobeXMPCore::spIStructureNode flashNode = metaNode->GetStructureNode(kXMP_NS_EXIF, AdobeXMPCommon::npos, "Flash", AdobeXMPCommon::npos);
+ if (flashNode != NULL)
+ {
+ AdobeXMPCore::spISimpleNode field = flashNode->GetSimpleNode(kXMP_NS_EXIF, AdobeXMPCommon::npos, "Fired", AdobeXMPCommon::npos);
+ if (field != NULL)
+ {
+ string fieldValue = field->GetValue()->c_str();
+ cout << "Flash Used = " << fieldValue << 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;
+}
diff --git a/samples/source/UnicodeCorrectness.cpp b/samples/source/UnicodeCorrectness.cpp
index 56f121a..2864358 100644
--- a/samples/source/UnicodeCorrectness.cpp
+++ b/samples/source/UnicodeCorrectness.cpp
@@ -10,6 +10,8 @@
#include <cerrno>
#include <stdexcept>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
using namespace std;
#if WIN_ENV
diff --git a/samples/source/UnicodeParseSerialize.cpp b/samples/source/UnicodeParseSerialize.cpp
index c3c9865..5f0d463 100644
--- a/samples/source/UnicodeParseSerialize.cpp
+++ b/samples/source/UnicodeParseSerialize.cpp
@@ -27,6 +27,8 @@
#include "source/UnicodeConversions.hpp"
#include "source/UnicodeConversions.cpp"
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
using namespace std;
#if WIN_ENV
diff --git a/samples/source/UnicodePerformance.cpp b/samples/source/UnicodePerformance.cpp
index d11185c..dac4ecd 100644
--- a/samples/source/UnicodePerformance.cpp
+++ b/samples/source/UnicodePerformance.cpp
@@ -11,6 +11,8 @@
#include <cerrno>
#include <stdexcept>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
using namespace std;
#if WIN_ENV
diff --git a/samples/source/XMPCoreCoverage.cpp b/samples/source/XMPCoreCoverage.cpp
index fd1e65a..e1dc30c 100644
--- a/samples/source/XMPCoreCoverage.cpp
+++ b/samples/source/XMPCoreCoverage.cpp
@@ -27,6 +27,8 @@
#include "public/include/XMP.hpp"
#include "public/include/XMP.incl_cpp"
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
using namespace std;
#if WIN_ENV
diff --git a/samples/source/XMPFilesCoverage.cpp b/samples/source/XMPFilesCoverage.cpp
index 326b19a..c482694 100644
--- a/samples/source/XMPFilesCoverage.cpp
+++ b/samples/source/XMPFilesCoverage.cpp
@@ -24,6 +24,8 @@
#include "public/include/XMP.hpp"
#include "public/include/XMP.incl_cpp"
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
using namespace std;
#if WIN_ENV
diff --git a/samples/source/XMPIterations.cpp b/samples/source/XMPIterations.cpp
index f93b7d7..7a02a24 100644
--- a/samples/source/XMPIterations.cpp
+++ b/samples/source/XMPIterations.cpp
@@ -15,6 +15,8 @@
#include <string>
#include <cstring>
+//#define ENABLE_XMP_CPP_INTERFACE 1;
+
// Must be defined to instantiate template classes
#define TXMP_STRING_TYPE std::string
diff --git a/samples/source/common/DumpFile.cpp b/samples/source/common/DumpFile.cpp
index 32dd253..4d1e59f 100644
--- a/samples/source/common/DumpFile.cpp
+++ b/samples/source/common/DumpFile.cpp
@@ -28,7 +28,11 @@
//
// DumpFile does depend on XMPCore and the packetscanner from XMPFiles.
+
#include <stdarg.h>
+
+#include "source/ExpatAdapter.hpp"
+
#include "samples/source/common/globals.h"
#include "samples/source/common/DumpFile.h"
#include "samples/source/common/LargeFileAccess.hpp"
@@ -297,12 +301,12 @@ struct JpegMarker {
};
typedef std::vector<JpegMarker> JpegMarkers;
-static void DumpTIFF ( XMP_Uns8 * tiffContent, XMP_Uns32 tiffLen, XMP_Uns32 fileOffset, const char * label, std::string path );
+static void DumpTIFF ( XMP_Uns8 * tiffContent, XMP_Uns32 tiffLen, XMP_Uns32 fileOffset, const char * label, std::string path, bool isHeaderAbsent = false );
static void DumpTIFF ( const JpegMarkers& psirMarkers, XMP_Uns8 * dataStart, const char * label, std::string path );
static void DumpIPTC ( XMP_Uns8 * iptcOrigin, XMP_Uns32 iptcLen, XMP_Uns32 fileOffset, const char * label );
static void DumpImageResources ( XMP_Uns8 * psirOrigin, XMP_Uns32 psirLen, XMP_Uns32 fileOffset, const char * label );
static void DumpImageResources ( const JpegMarkers& psirMarkers, XMP_Uns8 * dataStart, const char * label );
-static void DumpIFDChain ( XMP_Uns8 * startPtr, XMP_Uns8 * endPtr, XMP_Uns8 * tiffContent, XMP_Uns32 fileOffset, const char * label, std::string path );
+static void DumpIFDChain ( XMP_Uns8 * startPtr, XMP_Uns8 * endPtr, XMP_Uns8 * tiffContent, XMP_Uns32 fileOffset, const char * label, std::string path, bool isHeaderAbsent = false );
// =================================================================================================
@@ -416,10 +420,11 @@ enum {
kTIFF_SRational = 10,
kTIFF_Float = 11,
kTIFF_Double = 12,
- kTIFF_TypeEnd
+ kTIFF_IFD = 13,
+ kTIFF_TypeEnd = kTIFF_IFD
};
-static const int sTIFF_TypeSizes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 };
+static const int sTIFF_TypeSizes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4 };
static const char * sTIFF_TypeNames[] = { "", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL",
"SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL",
"FLOAT", "DOUBLE" };
@@ -958,6 +963,12 @@ static const XMP_Uns32 kISOBrand_mp41 = 0x6D703431UL;
static const XMP_Uns32 kISOBrand_mp42 = 0x6D703432UL;
static const XMP_Uns32 kISOBrand_avc1 = 0x61766331UL;
static const XMP_Uns32 kISOBrand_f4v = 0x66347620UL;
+static const XMP_Uns32 kISOBrand_isom = 0x69736F6DUL;
+static const XMP_Uns32 kISOBrand_3gp4 = 0x33677034UL;
+static const XMP_Uns32 kISOBrand_3g2a = 0x33673261UL;
+static const XMP_Uns32 kISOBrand_3g2b = 0x33673262UL;
+static const XMP_Uns32 kISOBrand_3g2c = 0x33673263UL;
+
static const XMP_Uns32 kQTTag_XMP_ = 0x584D505FUL;
@@ -1047,6 +1058,11 @@ CheckFileFormat ( const char * filePath, XMP_Uns8 * fileContent, XMP_Int64 fileS
case kISOBrand_mp41:
case kISOBrand_mp42:
case kISOBrand_avc1:
+ case kISOBrand_isom:
+ case kISOBrand_3gp4:
+ case kISOBrand_3g2a:
+ case kISOBrand_3g2b:
+ case kISOBrand_3g2c:
return kXMP_MPEG4File;
break;
@@ -1071,6 +1087,11 @@ CheckFileFormat ( const char * filePath, XMP_Uns8 * fileContent, XMP_Int64 fileS
if ( LookupFileExtMapping (filePath) == kXMP_MPEGFile ) return kXMP_MPEGFile;
if ( LookupFileExtMapping (filePath) == kXMP_MOVFile ) return kXMP_MOVFile;
+ std::string fileData = (char*)fileContent;
+ if ( (fileSize > 30) && (int)fileData.find ( "<svg" ) >= 0 ) {
+ return kXMP_SVGFile;
+ }
+
return kXMP_UnknownFile;
} // CheckFileFormat
@@ -1676,6 +1697,14 @@ DumpOneIFD (int ifdIndex, XMP_Uns8 * ifdPtr, XMP_Uns8 * endPtr,
case kTIFF_Double :
break;
+ case kTIFF_IFD:
+ if ( valueCount == 1 ) {
+ value32 = TIFF_GetUns32 ( valuePtr );
+ tree->addComment ( "hex value = 0x%.8X", value32 );
+ tree->changeValue ( "%u", value32 );
+ }
+ break;
+
default :
tree->addComment("** unknown type **");
break;
@@ -1732,11 +1761,14 @@ DumpOneIFD (int ifdIndex, XMP_Uns8 * ifdPtr, XMP_Uns8 * endPtr,
static void
DumpIFDChain (XMP_Uns8 * startPtr, XMP_Uns8 * endPtr,
- XMP_Uns8 * tiffContent, XMP_Uns32 fileOrigin, const char * label, std::string path)
+ XMP_Uns8 * tiffContent, XMP_Uns32 fileOrigin, const char * label, std::string path, bool isHeaderAbsent )
{
XMP_Uns8 * ifdPtr = startPtr;
XMP_Uns32 ifdOffset = startPtr - tiffContent;
+ if (isHeaderAbsent) // It's a kind of hack to iterate all the ifdboxes at least once.
+ ifdOffset = 1;
+
for (size_t ifdIndex = 0; ifdOffset != 0; ++ifdIndex) {
if ((ifdPtr < tiffContent) || (ifdPtr >= endPtr)) {
@@ -1757,7 +1789,7 @@ DumpIFDChain (XMP_Uns8 * startPtr, XMP_Uns8 * endPtr,
// =================================================================================================
static void
-DumpTIFF (XMP_Uns8 * tiffContent, XMP_Uns32 tiffLen, XMP_Uns32 fileOffset, const char * label, std::string path)
+DumpTIFF (XMP_Uns8 * tiffContent, XMP_Uns32 tiffLen, XMP_Uns32 fileOffset, const char * label, std::string path, bool isHeaderAbsent)
{
tree->pushNode("TIFF content from %s", label);
// ! TIFF can be nested because of the Photoshop 6 weiredness. Save and restore the procs.
@@ -1765,27 +1797,43 @@ DumpTIFF (XMP_Uns8 * tiffContent, XMP_Uns32 tiffLen, XMP_Uns32 fileOffset, const
GetUns32_Proc save_GetUns32 = TIFF_GetUns32;
GetUns64_Proc save_GetUns64 = TIFF_GetUns64;
- if (CheckBytes(tiffContent,"II\x2A\x00",4)) {
+ XMP_Uns32 ifdOffset = 0;
+
+ if (!isHeaderAbsent)
+ {
+ if (CheckBytes(tiffContent, "II\x2A\x00", 4)) {
+ beTIFF = false;
+ TIFF_GetUns16 = GetUns16LE;
+ TIFF_GetUns32 = GetUns32LE;
+ TIFF_GetUns64 = GetUns64LE;
+ tree->addComment("Little endian ");
+ }
+ else if (CheckBytes(tiffContent, "MM\x00\x2A", 4)) {
+ beTIFF = true;
+ TIFF_GetUns16 = GetUns16BE;
+ TIFF_GetUns32 = GetUns32BE;
+ TIFF_GetUns64 = GetUns64BE;
+ tree->addComment("Big endian ");
+ }
+ else {
+ tree->comment("** Missing TIFF image file header tree.");
+ return;
+ }
+
+ tree->addComment("TIFF from %s, offset %d (0x%X), size %d", label, fileOffset, fileOffset, tiffLen);
+
+ ifdOffset = TIFF_GetUns32(tiffContent + 4);
+ }
+ else
+ {
beTIFF = false;
TIFF_GetUns16 = GetUns16LE;
TIFF_GetUns32 = GetUns32LE;
TIFF_GetUns64 = GetUns64LE;
tree->addComment("Little endian ");
- } else if (CheckBytes(tiffContent,"MM\x00\x2A",4)) {
- beTIFF = true;
- TIFF_GetUns16 = GetUns16BE;
- TIFF_GetUns32 = GetUns32BE;
- TIFF_GetUns64 = GetUns64BE;
- tree->addComment("Big endian ");
- } else {
- tree->comment("** Missing TIFF image file header tree.");
- return;
}
- tree->addComment("TIFF from %s, offset %d (0x%X), size %d", label, fileOffset, fileOffset, tiffLen);
-
- XMP_Uns32 ifdOffset = TIFF_GetUns32 (tiffContent+4);
- DumpIFDChain (tiffContent+ifdOffset, tiffContent+tiffLen, tiffContent, fileOffset, label, path);
+ DumpIFDChain(tiffContent + ifdOffset, tiffContent + tiffLen, tiffContent, fileOffset, label, path, isHeaderAbsent);
TIFF_GetUns16 = save_GetUns16;
TIFF_GetUns32 = save_GetUns32;
@@ -2017,7 +2065,6 @@ static const XMP_Uns8 kUUID_IPTC[16] =
{ 0x09, 0xA1, 0x4E, 0x97, 0xC0, 0xB4, 0x42, 0xE0, 0xBE, 0xBF, 0x36, 0xDF, 0x6F, 0x0C, 0xE3, 0x6F };
static const XMP_Uns8 kUUID_PSIR[16] =
{ 0x2C, 0x4C, 0x01, 0x00, 0x85, 0x04, 0x40, 0xB9, 0xA0, 0x3E, 0x56, 0x21, 0x48, 0xD6, 0xDF, 0xEB };
-
// -------------------------------------------------------------------------------------------------
/**
@@ -2077,13 +2124,13 @@ DumpISOBoxes ( LFA_FileRef file, XMP_Uns32 maxBoxLen, std::string _isoPath )
// or, uhm, something garbage-ish...
if ( LFA_Tell(file) + boxHeaderSize > endOfThisLevel )
{
- XMP_Int64 numUnusedBytes = (LFA_Tell(file) + boxHeaderSize - endOfThisLevel);
+ XMP_Int64 numUnusedBytes = (endOfThisLevel - LFA_Tell(file));
tree->digestString( file, isoPath+"unused", numUnusedBytes, false );
tree->addComment( "'free' since too small for a box" );
bool ok;
- LFA_Seek( file, maxBoxLen, SEEK_CUR, &ok );
- assertMsg("skippind to-small space failed (truncated file?)", ok );
+ LFA_Seek( file, endOfThisLevel, SEEK_SET, &ok );
+ assertMsg("skippind to-small space failed (truncated file?)", ok );
continue; // could just as well: return
}
@@ -2106,21 +2153,27 @@ DumpISOBoxes ( LFA_FileRef file, XMP_Uns32 maxBoxLen, std::string _isoPath )
break;
}
- XMP_Uns32 tempBoxType = GetUns32LE(&boxType);
- std::string boxString( fromArgs( "%.4s" , &tempBoxType) );
+ XMP_Uns32 tempBoxType = GetUns32LE(&boxType);
+ std::string boxString( fromArgs( "%.4s" , &tempBoxType) );
- // substitute mac-copyright signs with an easier-to-handle "(c)"
+ if(boxString.size() != 0)
+ {
+ // substitute mac-copyright signs with an easier-to-handle "(c)"
#if !IOS_ENV
- if ( boxString.at(0) == 0xa9 )
+ if ( boxString.at(0) == 0xa9 )
#else
- if ( boxString.at(0) == 0xffffffa9 )
+ if ( boxString.at(0) == 0xffffffa9 )
#endif
- boxString = std::string("(c)") + boxString.substr(1);
+ boxString = std::string("(c)") + boxString.substr(1);
+ }
+ else
+ break;
+
isoPath = origIsoPath + boxString + "/";
// TEMP
// Log::info("pushing %s, endOfThisLevel: 0x%X", isoPath.c_str(), endOfThisLevel );
- // printf ("%s \n", isoPath.c_str());
+ // printf ("%s \n", isoPath.c_str());
tree->pushNode( isoPath );
tree->addComment("offset 0x%I64X, size 0x%I64X", boxPos , boxSize);
@@ -2317,9 +2370,9 @@ DumpISOBoxes ( LFA_FileRef file, XMP_Uns32 maxBoxLen, std::string _isoPath )
XMP_Int64 endOfTrailingBoxes = LFA_Tell(file) + remainingSize;
while ( LFA_Tell(file) < endOfTrailingBoxes )
{
- LFA_Tell( file );
- DumpISOBoxes( file, entrySize, isoPath );
- LFA_Tell( file );
+ LFA_Tell(file);
+ DumpISOBoxes( file, entrySize, isoPath );
+ LFA_Tell(file);
}
assertMsg( "did not boil down to zero", LFA_Tell(file) == endOfTrailingBoxes );
@@ -2385,7 +2438,7 @@ DumpISOBoxes ( LFA_FileRef file, XMP_Uns32 maxBoxLen, std::string _isoPath )
}
case 0x74727063: // cprt, FULLBOX
- if ( isoPath == "moov/udta/cprt/")
+ if ( isoPath == "moov/udta/cprt/" || isoPath == "moov/uuid/udta/cprt/" )
{
digestISOFullBoxExtension( file, isoPath, remainingSize, version, flags );
@@ -2421,6 +2474,18 @@ DumpISOBoxes ( LFA_FileRef file, XMP_Uns32 maxBoxLen, std::string _isoPath )
// (c)-style quicktime boxes and boxes of no interest:
default:
+ if ( (boxType & 0xA9) == 0xA9) // (c)something
+ {
+ if ( 0 == isoPath.compare( 0 , 10, "moov/udta/" ))
+ { // => Quicktime metadata "international text sequence" ( size, language code, value )
+ digestInternationalTextSequence( file, isoPath, &remainingSize );
+ } else
+ {
+ tree->addComment("WARNING: unknown flavor of (c)*** boxes, neither QT nor iTunes");
+ }
+ break;
+ }
+ //boxes of no interest:
break;
}
@@ -3385,6 +3450,10 @@ DumpRIFFChunk ( LFA_FileRef file, XMP_Int64 parentEnd, std::string origChunkPath
isXMPchunk = true;
}
+ bool isIDITChunk =
+ ( ( origChunkPath == "RIFF:AVI/LIST:hdrl" || origChunkPath == "RIFF:AVI /LIST:hdrl" )
+ && idString == "IDIT" );
+
// deal with chunks of interest /////////////////////////////////////////////
// a little prelude for disp chunk
if ( isDispChunk )
@@ -3399,7 +3468,7 @@ DumpRIFFChunk ( LFA_FileRef file, XMP_Int64 parentEnd, std::string origChunkPath
chunkSize -= 4;
}
- if ( isListInfo || isListTdat || isDispChunk )
+ if (isListInfo || isListTdat || isDispChunk || isIDITChunk)
{
// dump that string:
std::string value;
@@ -3501,6 +3570,10 @@ DumpRIFFChunk ( LFA_FileRef file, XMP_Int64 parentEnd, std::string origChunkPath
// parse till first \0
std::string description( descriptionBuffer );
+ // Dumping the iXML chunk. Needed for testing
+ // Add iXML chunk as a node to tree
+ tree->setKeyValue( chunkPath+".ValueOfIXMLChunk", description );
+
delete[] descriptionBuffer;
tree->addComment("packet end: 0x%llX", LFA_Tell( file ) );
@@ -3940,6 +4013,93 @@ DumpInDesign (LFA_FileRef file, XMP_Uns32 inddLen)
// =================================================================================================
+static void
+DumpSVGTag ( std::string basePath, XML_NodePtr currentNode )
+{
+ if ( currentNode )
+ {
+ tree->pushNode ( basePath + currentNode->name );
+
+ // Iterating over all XML children.
+ XML_NodeVector currNodeVector = currentNode->content;
+ for ( int i = 0; i < currNodeVector.size ( ); i++ )
+ {
+ // Dump all children who are element nodes.
+ if ( currNodeVector[i]->kind == kElemNode )
+ DumpSVGTag ( basePath + currentNode->name + "/", currNodeVector[i] );
+
+ // Extract the value from datanodes and put in TagMap if it's not yet available.
+ if ( currNodeVector[i]->kind == kCDataNode && tree->getValue ( basePath + currentNode->name ) == "" )
+ tree->updateKeyValue ( basePath + currentNode->name, currNodeVector[i]->value );
+ }
+ }
+
+} // DumpSVGTag
+
+// =================================================================================================
+
+static void
+DumpSVG ( LFA_FileRef file, XMP_Uns32 svgLen )
+{
+ // SVG is an XML based format.We consider any file as SVG file if the given file contains a SVG tag.
+ // Hence CheckFileFormat looks for presence of "<svg" in the file.
+ //
+ // For Dumping SVG elements we are using ExpatAdapter. Below code will parse given file using this
+ // adapter and add different tags in the TagMap tree.
+ //
+ // Below is the currently supported structure of known tags for this format.
+ // <svg>
+ // <title/>
+ // <desc/>
+ // <metadata>
+ // <x:xmpmeta/>
+ // <...>
+ // <...>
+ // </metadata>
+ // <...>
+ // <...>
+ // </svg>
+
+ ExpatAdapter * pExpatAdapter = XMP_NewExpatAdapter ( false );
+
+ if ( pExpatAdapter == 0 )
+ {
+ tree->comment ( "ExpatAdapter initialization failed. Cann't parse SVG file." );
+ return;
+ }
+
+ // Allocating big enough memory on heap to read file contents.
+ XMP_Uns8 *fileContent = new XMP_Uns8[svgLen + 1];
+ memset ( fileContent, 0, (svgLen + 1)*sizeof ( XMP_Uns8 ) );
+
+ // Reading total file in buffer (fileContent)
+ LFA_Seek ( file, 0, SEEK_SET );
+ LFA_Read ( file, fileContent, svgLen + 1, false );
+
+ // Parsing the file with ExpatAdapter
+ pExpatAdapter->ParseBuffer ( fileContent, svgLen + 1, false /* not the end */ );
+
+ // Finding <svg> element and adding to TagMap tree.
+ XML_NodePtr svgNode = pExpatAdapter->tree.GetNamedElement ( "http://www.w3.org/2000/svg", "svg" );
+ DumpSVGTag ( "", svgNode );
+
+ // De-allocating all the resources.
+ if ( fileContent )
+ {
+ delete[] fileContent;
+ fileContent = NULL;
+ }
+
+ if ( pExpatAdapter )
+ {
+ delete pExpatAdapter;
+ pExpatAdapter = NULL;
+ }
+
+} // DumpSVG
+
+// =================================================================================================
+
#define kSWF_FileAttributesTag 69
#define kSWF_MetadataTag 77
@@ -4788,6 +4948,7 @@ static void DumpID3v22Frames ( LFA_FileRef file, XMP_Uns8 vMajor, XMP_Uns32 fram
static void DumpID3v23Frames ( LFA_FileRef file, XMP_Uns8 vMajor, XMP_Uns32 framePos, XMP_Uns32 frameEnd ) {
// Dump the frames in an ID3 v2.3 or v2.4 tag.
+ int iIterator = 0;
while ( (framePos < frameEnd) && ((frameEnd - framePos) >= 10) ) {
@@ -4879,9 +5040,76 @@ static void DumpID3v23Frames ( LFA_FileRef file, XMP_Uns8 vMajor, XMP_Uns32 fram
}
}
+
+ else if ( CheckBytes ( frameHead.id , "APIC" , 4 ) ) {
- framePos += (sizeof(frameHead) + frameHead.size);
+ ++iIterator;
+ unsigned int iOffset = 0;
+ CaptureFileData ( file , 0 , frameHead.size );
+
+ char encoding[2];
+ memset ( encoding , 0x0 , 2 );
+ encoding[0] = sDataPtr[iOffset++];
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-encodingType_%d" , iIterator ) , encoding );
+ char * mimeType = ( char* ) (sDataPtr + iOffset);
+ iOffset += strlen ( mimeType ) + 1; //1 is for null termination
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-mimeType_%d" , iIterator ) , mimeType );
+
+ char pictureType[2];
+ memset ( pictureType , 0x0 , 2 );
+ pictureType[0] = sDataPtr[iOffset++];
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-pictureType_%1d" , iIterator ) , pictureType );
+
+ bool bigEndian = PrintID3Encoding ( encoding[0] , (sDataPtr + iOffset) );
+ if ( encoding[0] == 0x00 ) {
+
+ XMP_Uns8 * descrPtr = sDataPtr + iOffset;
+ XMP_Uns8 * valuePtr = descrPtr;
+
+ while ( *valuePtr != 0 ) ++valuePtr;
+ ++valuePtr; //Null termination
+
+ size_t descrBytes = valuePtr - descrPtr;
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-descr_%d" , iIterator ) , convert8Bit ( descrPtr , false , descrBytes - 1 ).c_str ( ) );
+ iOffset += descrBytes;
+ }
+ else if ( encoding[0] == 0x01 ) {
+
+ XMP_Uns16 * descrPtr = ( XMP_Uns16* ) (sDataPtr + iOffset);
+ XMP_Uns16 * valuePtr = descrPtr;
+
+ while ( *valuePtr != 0 ) ++valuePtr;
+ ++valuePtr; //Null termination
+
+ size_t descrBytes = 2 * (valuePtr - descrPtr);
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-descr_%d" , iIterator ) , convert16Bit ( bigEndian , ( XMP_Uns8* ) (descrPtr + 1) , false , descrBytes - 4 ).c_str ( ) );
+ iOffset += descrBytes;
+ }
+
+ XMP_Uns8 *picPtr = (sDataPtr + iOffset);
+ unsigned long size_PictureData = frameHead.size - iOffset;
+
+ char picDataSize[8];
+ memset ( picDataSize , 0x0 , 8 );
+ sprintf ( picDataSize, "%d", size_PictureData );
+
+ std::string picData;
+ picData.assign ( ( char* ) picPtr , size_PictureData );
+
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-pictureData_%d" , iIterator ) , picData );
+ tree->setKeyValue ( fromArgs ( "ID3v2:APIC-pictureDataSize_%d" , iIterator ) , picDataSize );
+ }
+
+ framePos += (sizeof(frameHead) + frameHead.size);
+
+ }
+
+ if ( iIterator ) {
+ char noOfAPICs[2];
+ memset ( noOfAPICs , 0x0 , 2 );
+ sprintf ( noOfAPICs , "%d" , iIterator );
+ tree->setKeyValue ( "ID3v2:NoOfAPIC" , noOfAPICs );
}
if ( framePos < frameEnd ) {
@@ -5328,6 +5556,12 @@ void DumpFile::Scan (std::string filename, TagTree &tagTree, bool resetTree)
DumpPS ( fileRef, fileLen );
tagTree.popNode();
+ } else if ( format == kXMP_SVGFile ) {
+
+ tagTree.pushNode ( "Dumping SVG file" );
+ tagTree.addComment ( "size %lld (0x%llx)", fileLen, fileLen );
+ DumpSVG ( fileRef, fileLen );
+ tagTree.popNode ( );
} else if ( format == kXMP_UnknownFile ) {
tagTree.pushNode ( "Unknown format. packet scanning, size %d (0x%X)", fileLen, fileLen );
diff --git a/samples/source/common/TagTree.cpp b/samples/source/common/TagTree.cpp
index aa8ca12..761ab22 100644
--- a/samples/source/common/TagTree.cpp
+++ b/samples/source/common/TagTree.cpp
@@ -118,6 +118,25 @@ void TagTree::setKeyValue(const std::string key,const std::string value, const s
Log::info( " setKeyValue( %s |-> %s) [%s]", key.c_str(), value.c_str(), _comment.c_str() );
}
+void TagTree::updateKeyValue ( const std::string key, const std::string value, const std::string _comment )
+{
+ Node* pCurNode = *nodeStack.rbegin ( ); //current Node
+ pCurNode->children.push_back ( Node ( key, value, _comment ) );
+
+ if ( key.size ( ) == 0 ) { // standalone comment?
+ if ( value.size ( ) != 0 ) // must have no value
+ Log::error ( "no key but value found." );
+ return; // ==> do not add to tag-map
+ }
+
+ //add to Map -----------------------------------
+ lastNode = &*(pCurNode->children.rbegin ( ));
+ tagMap[key] = lastNode;
+
+ if ( verbose )
+ Log::info ( " setKeyValue( %s |-> %s) [%s]", key.c_str ( ), value.c_str ( ), _comment.c_str ( ) );
+}
+
void TagTree::digest(LFA_FileRef file,const std::string key /*=NULL*/,
void* returnValue /*=""*/,
XMP_Int32 numOfBytes /*=0*/ )
diff --git a/samples/source/common/TagTree.h b/samples/source/common/TagTree.h
index 857b141..9bd46d3 100644
--- a/samples/source/common/TagTree.h
+++ b/samples/source/common/TagTree.h
@@ -107,6 +107,9 @@ public:
//sets a key-value pair and optinal comment. value is also optional and may be set at a later time
//can also be used to set pure, standalone comments (using key==value=="")
void setKeyValue(const std::string key,const std::string value="", const std::string comment="");
+
+ //updates the value of key without creating new key, value pairs.
+ void updateKeyValue ( const std::string key, const std::string value, const std::string comment = "" );
// convenience functions //////////////////////////////////////////////////////////////////
// these functions read bytes (assert in file-length), dump them to screen (as hex or as number)
diff --git a/samples/source/common/globals.h b/samples/source/common/globals.h
index 8b0d09c..3998476 100644
--- a/samples/source/common/globals.h
+++ b/samples/source/common/globals.h
@@ -69,8 +69,10 @@
const char AEOEUE_UTF8_CSTRING[]={0xC3, 0x84, 0xC3, 0x96, 0xC3, 0x9C,'\0'};
const std::string AEOEUE_UTF8(AEOEUE_UTF8_CSTRING);
const std::string AEOEUE_UTF8_BUGINESE("<C3 84 C3 96 C3 9C>");
+ const std::string AEOEUE_UTF8_BUGINESE_EVEN ( "<C3 84 C3 96 C3 9C 00>" );
const std::string AEOEUE_WIN_LOCAL_BUGINESE("<C4 D6 DC>");
+ const std::string AEOEUE_WIN_LOCAL_BUGINESE_EVEN ( "<C4 D6 DC 00>" );
const std::string AEOEUE_MAC_LOCAL_BUGINESE("<80 85 86>");
const std::string AEOEUE_WIN_MOJIBAKE_BUGINESE("<E2 82 AC E2 80 A6 E2 80 A0>");
diff --git a/samples/source/dumpfile/main.cpp b/samples/source/dumpfile/main.cpp
index bd11b05..c18f6d7 100644
--- a/samples/source/dumpfile/main.cpp
+++ b/samples/source/dumpfile/main.cpp
@@ -41,6 +41,7 @@ const int DUMPFILEVERSION=2;
#include "public/include/XMP.hpp" //NB: no XMP.incl_cpp here on purpose, gets compiled in main...
#include "public/include/XMP.incl_cpp" //include in EXACTLY one source file (i.e. main, in Action gets you trouble...)
#include "public/include/XMP_Const.h"
+#include "source/XML_Node.cpp"
//utils
#include "samples/source/common/Log.h"