00001 // ***************************************************************** -*- C++ -*- 00002 // xmpsample.cpp, $Rev: 1305 $ 00003 // Sample/test for high level XMP classes. See also addmoddel.cpp 00004 00005 #include <exiv2/xmp.hpp> 00006 #include <exiv2/error.hpp> 00007 00008 #include <string> 00009 #include <iostream> 00010 #include <iomanip> 00011 00012 int main() 00013 try { 00014 // The XMP property container 00015 Exiv2::XmpData xmpData; 00016 00017 // ------------------------------------------------------------------------- 00018 // Teaser: Setting XMP properties doesn't get much easier than this: 00019 00020 xmpData["Xmp.dc.source"] = "xmpsample.cpp"; // a simple text value 00021 xmpData["Xmp.dc.subject"] = "Palmtree"; // an array item 00022 xmpData["Xmp.dc.subject"] = "Rubbertree"; // add a 2nd array item 00023 // a language alternative with two entries and without default 00024 xmpData["Xmp.dc.title"] = "lang=de-DE Sonnenuntergang am Strand"; 00025 xmpData["Xmp.dc.title"] = "lang=en-US Sunset on the beach"; 00026 00027 // ------------------------------------------------------------------------- 00028 // Any properties can be set provided the namespace is known. Values of any 00029 // type can be assigned to an Xmpdatum, if they have an output operator. The 00030 // default XMP value type for unknown properties is a simple text value. 00031 00032 xmpData["Xmp.dc.one"] = -1; 00033 xmpData["Xmp.dc.two"] = 3.1415; 00034 xmpData["Xmp.dc.three"] = Exiv2::Rational(5, 7); 00035 xmpData["Xmp.dc.four"] = uint16_t(255); 00036 xmpData["Xmp.dc.five"] = int32_t(256); 00037 xmpData["Xmp.dc.six"] = false; 00038 00039 // In addition, there is a dedicated assignment operator for Exiv2::Value 00040 Exiv2::XmpTextValue val("Seven"); 00041 xmpData["Xmp.dc.seven"] = val; 00042 00043 // ------------------------------------------------------------------------- 00044 // Exiv2 has specialized values for simple XMP properties, arrays of simple 00045 // properties and language alternatives. 00046 00047 // Add a simple XMP property in a known namespace 00048 Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::xmpText); 00049 v->read("image/jpeg"); 00050 xmpData.add(Exiv2::XmpKey("Xmp.dc.format"), v.get()); 00051 00052 // Add an ordered array of text values. 00053 v = Exiv2::Value::create(Exiv2::xmpSeq); // or xmpBag or xmpAlt. 00054 v->read("1) The first creator"); // The sequence in which the array 00055 v->read("2) The second creator"); // elements are added is their 00056 v->read("3) And another one"); // order in the array. 00057 xmpData.add(Exiv2::XmpKey("Xmp.dc.creator"), v.get()); 00058 00059 // Add a language alternative property 00060 v = Exiv2::Value::create(Exiv2::langAlt); 00061 v->read("lang=de-DE Hallo, Welt"); // The default doesn't need a 00062 v->read("Hello, World"); // qualifier 00063 xmpData.add(Exiv2::XmpKey("Xmp.dc.description"), v.get()); 00064 00065 // According to the XMP specification, Xmp.tiff.ImageDescription is an 00066 // alias for Xmp.dc.description. Exiv2 treats an alias just like any 00067 // other property and leaves it to the application to implement specific 00068 // behaviour if desired. 00069 xmpData["Xmp.tiff.ImageDescription"] = "TIFF image description"; 00070 xmpData["Xmp.tiff.ImageDescription"] = "lang=de-DE TIFF Bildbeschreibung"; 00071 00072 // ------------------------------------------------------------------------- 00073 // Register a namespace which Exiv2 doesn't know yet. This is only needed 00074 // when properties are added manually. If the XMP metadata is read from an 00075 // image, namespaces are decoded and registered at the same time. 00076 Exiv2::XmpProperties::registerNs("myNamespace/", "ns"); 00077 00078 // ------------------------------------------------------------------------- 00079 // There are no specialized values for structures, qualifiers and nested 00080 // types. However, these can be added by using an XmpTextValue and a path as 00081 // the key. 00082 00083 // Add a structure 00084 Exiv2::XmpTextValue tv("16"); 00085 xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:w"), &tv); 00086 tv.read("9"); 00087 xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:h"), &tv); 00088 tv.read("inch"); 00089 xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:unit"), &tv); 00090 00091 // Add an element with a qualifier (using the namespace registered above) 00092 xmpData["Xmp.dc.publisher"] = "James Bond"; // creates an unordered array 00093 xmpData["Xmp.dc.publisher[1]/?ns:role"] = "secret agent"; 00094 00095 // Add a qualifer to an array element of Xmp.dc.creator (added above) 00096 tv.read("programmer"); 00097 xmpData.add(Exiv2::XmpKey("Xmp.dc.creator[2]/?ns:role"), &tv); 00098 00099 // Add an array of structures 00100 tv.read(""); // Clear the value 00101 tv.setXmpArrayType(Exiv2::XmpValue::xaBag); 00102 xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef"), &tv); // Set the array type. 00103 00104 tv.setXmpArrayType(Exiv2::XmpValue::xaNone); 00105 tv.read("Birthday party"); 00106 xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[1]/stJob:name"), &tv); 00107 tv.read("Photographer"); 00108 xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[1]/stJob:role"), &tv); 00109 00110 tv.read("Wedding ceremony"); 00111 xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[2]/stJob:name"), &tv); 00112 tv.read("Best man"); 00113 xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[2]/stJob:role"), &tv); 00114 00115 // ------------------------------------------------------------------------- 00116 // Output XMP properties 00117 for (Exiv2::XmpData::const_iterator md = xmpData.begin(); 00118 md != xmpData.end(); ++md) { 00119 std::cout << std::setfill(' ') << std::left 00120 << std::setw(44) 00121 << md->key() << " " 00122 << std::setw(9) << std::setfill(' ') << std::left 00123 << md->typeName() << " " 00124 << std::dec << std::setw(3) 00125 << std::setfill(' ') << std::right 00126 << md->count() << " " 00127 << std::dec << md->value() 00128 << std::endl; 00129 } 00130 00131 // ------------------------------------------------------------------------- 00132 // Serialize the XMP data and output the XMP packet 00133 std::string xmpPacket; 00134 if (0 != Exiv2::XmpParser::encode(xmpPacket, xmpData)) { 00135 throw Exiv2::Error(1, "Failed to serialize XMP data"); 00136 } 00137 std::cout << xmpPacket << "\n"; 00138 00139 // Cleanup 00140 Exiv2::XmpParser::terminate(); 00141 00142 return 0; 00143 } 00144 catch (Exiv2::AnyError& e) { 00145 std::cout << "Caught Exiv2 exception '" << e << "'\n"; 00146 return -1; 00147 }