1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
// =================================================================================================
// 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 <string>
// 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
// Ensure XMP templates are instantiated
#include "XMP.incl_cpp"
// Provide access to the API
#include "XMP.hpp"
#include <iostream>
#include <fstream>
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
* times during the DumpObject() operation. See the XMP API reference for details of
* XMP_TextOutputProc() callbacks.
*/
XMP_Status DumpXMPToFile(void * refCon, XMP_StringPtr buffer, XMP_StringLen bufferSize)
{
XMP_Status status = 0;
try
{
ofstream * outFile = static_cast<ofstream*>(refCon);
(*outFile).write(buffer, bufferSize);
}
catch(XMP_Error & e)
{
cout << e.GetErrMsg() << endl;
return -1; // Return a bad status
}
return status;
}
/**
* 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);
bool exists;
// Read a simple property
string simpleValue; //Stores the value for the property
exists = meta.GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, NULL);
if(exists)
cout << "CreatorTool = " << simpleValue << endl;
else
simpleValue.clear();
// Get the first element in the dc:creator array
string elementValue;
exists = meta.GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, NULL);
if(exists)
cout << "dc:creator = " << elementValue << endl;
else
elementValue.clear();
// Get the the entire dc:subject array
string propValue;
int arrSize = meta.CountArrayItems(kXMP_NS_DC, "subject");
for(int i = 1; i <= arrSize;i++)
{
meta.GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0);
cout << "dc:subject[" << i << "] = " << propValue << endl;
}
// Get the dc:title for English and French
string itemValue;
string actualLang;
meta.GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", NULL, &itemValue, NULL);
cout << "dc:title in English = " << itemValue << endl;
meta.GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", NULL, &itemValue, NULL);
cout << "dc:title in French = " << itemValue << endl;
// Get dc:MetadataDate
XMP_DateTime myDate;
if(meta.GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, NULL))
{
// Convert the date struct into a convenient string and display it
string myDateStr;
SXMPUtils::ConvertFromDate(myDate, &myDateStr);
cout << "meta:MetadataDate = " << myDateStr << endl;
}
// See if the flash struct exists and see if it was used
string path, value;
exists = meta.DoesStructFieldExist(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF,"Fired");
if(exists)
{
bool flashFired;
SXMPUtils::ComposeStructFieldPath(kXMP_NS_EXIF, "Flash", kXMP_NS_EXIF, "Fired", &path);
meta.GetProperty_Bool(kXMP_NS_EXIF, path.c_str(), &flashFired, NULL);
string flash = (flashFired) ? "True" : "False";
cout << "Flash Used = " << flash << endl;
}
// Dump the current xmp object to a file
ofstream dumpFile;
dumpFile.open("XMPDump.txt", ios::out);
meta.DumpObject(DumpXMPToFile, &dumpFile);
dumpFile.close();
cout << endl << "XMP dumped to XMPDump.txt" << endl;
// Close the SXMPFile. The resource file is already closed if it was
// opened as read only but this call must still be made.
myFile.CloseFile();
}
else
{
cout << "Unable to open " << filename << endl;
}
}
catch(XMP_Error & e)
{
cout << "ERROR: " << e.GetErrMsg() << endl;
}
// Terminate the toolkit
SXMPFiles::Terminate();
SXMPMeta::Terminate();
return 0;
}
|