bool xmp_get_localized_text(XmpPtr xmp, const char *schema, const char *name, const char *genericLang, const char *specificLang, XmpStringPtr actualLang, XmpStringPtr itemValue, uint32_t *propsBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; try { SXMPMeta *txmp = (SXMPMeta *)xmp; XMP_OptionBits optionBits; ret = txmp->GetLocalizedText(schema, name, genericLang, specificLang, STRING(actualLang), STRING(itemValue), &optionBits); if(propsBits) { *propsBits = optionBits; } } catch(const XMP_Error & e) { set_error(e); ret = false; } return ret; }
static void ExportIPTC_Array ( const SXMPMeta & xmp, IPTC_Manager * iptc, const char * xmpNS, const char * xmpProp, XMP_Uns8 id ) { std::string value; XMP_OptionBits xmpFlags; bool found = xmp.GetProperty ( xmpNS, xmpProp, 0, &xmpFlags ); if ( ! found ) { iptc->DeleteDataSet ( id ); return; } if ( ! XMP_PropIsArray ( xmpFlags ) ) return; // ? Complain? Delete the DataSet? XMP_Index xmpCount = xmp.CountArrayItems ( xmpNS, xmpProp ); XMP_Index iptcCount = (XMP_Index) iptc->GetDataSet ( id, 0 ); if ( xmpCount != iptcCount ) iptc->DeleteDataSet ( id ); for ( XMP_Index ds = 0; ds < xmpCount; ++ds ) { // ! XMP arrays are indexed from 1, IPTC from 0. (void) xmp.GetArrayItem ( xmpNS, xmpProp, ds+1, &value, &xmpFlags ); if ( ! XMP_PropIsSimple ( xmpFlags ) ) continue; // ? Complain? NormalizeToCR ( &value ); iptc->SetDataSet_UTF8 ( id, value.c_str(), (XMP_Uns32)value.size(), ds ); // ! Appends if necessary. } } // ExportIPTC_Array
static void ExportIPTC_SubjectCode ( const SXMPMeta & xmp, IPTC_Manager * iptc ) { std::string xmpValue, iimValue; XMP_OptionBits xmpFlags; bool found = xmp.GetProperty ( kXMP_NS_IPTCCore, "SubjectCode", 0, &xmpFlags ); if ( ! found ) { iptc->DeleteDataSet ( kIPTC_SubjectCode ); return; } if ( ! XMP_PropIsArray ( xmpFlags ) ) return; // ? Complain? Delete the DataSet? XMP_Index xmpCount = xmp.CountArrayItems ( kXMP_NS_IPTCCore, "SubjectCode" ); XMP_Index iptcCount = (XMP_Index) iptc->GetDataSet ( kIPTC_SubjectCode, 0 ); if ( xmpCount != iptcCount ) iptc->DeleteDataSet ( kIPTC_SubjectCode ); for ( XMP_Index ds = 0; ds < xmpCount; ++ds ) { // ! XMP arrays are indexed from 1, IPTC from 0. (void) xmp.GetArrayItem ( kXMP_NS_IPTCCore, "SubjectCode", ds+1, &xmpValue, &xmpFlags ); if ( ! XMP_PropIsSimple ( xmpFlags ) ) continue; // ? Complain? if ( xmpValue.size() != 8 ) continue; // ? Complain? iimValue = "IPTC:"; iimValue += xmpValue; iimValue += ":::"; // Add the separating colons for the empty name portions. iptc->SetDataSet_UTF8 ( kIPTC_SubjectCode, iimValue.c_str(), (XMP_Uns32)iimValue.size(), ds ); // ! Appends if necessary. } } // ExportIPTC_SubjectCode
static void FullUnicodeParse ( FILE * log, const char * encoding, size_t bufferSize, const std::string & packet, const std::string & fullUnicode ) { if ( bufferSize > sizeof(sU32) ) { fprintf ( log, "#ERROR: FullUnicodeParse buffer overrun for %s, %d byte buffers\n", encoding, bufferSize ); return; } SXMPMeta meta; try { memset ( sU32, -1, sizeof(sU32) ); for ( size_t i = 0; i < packet.size(); i += bufferSize ) { size_t count = bufferSize; if ( count > (packet.size() - i) ) count = packet.size() - i; memcpy ( sU32, &packet[i], count ); meta.ParseFromBuffer ( XMP_StringPtr(sU32), count, kXMP_ParseMoreBuffers ); } meta.ParseFromBuffer ( XMP_StringPtr(sU32), 0 ); } catch ( XMP_Error& excep ) { char message [200]; sprintf ( message, "#ERROR: Full Unicode parsing error for %s, %d byte buffers", encoding, bufferSize ); PrintXMPErrorInfo ( excep, message ); return; } std::string value; bool found = meta.GetProperty ( kNS1, "FullUnicode", &value, 0 ); if ( (! found) || (value != fullUnicode) ) fprintf ( log, "#ERROR: Failed to get full Unicode value for %s, %d byte buffers\n", encoding, bufferSize ); } // FullUnicodeParse
/** * 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; }
bool xmp_set_property(XmpPtr xmp, const char *schema, const char *name, const char *value, uint32_t optionBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; SXMPMeta *txmp = (SXMPMeta *)xmp; // see bug #16030 // when it is a struct or an array, get prop return an empty string // but it fail if passed an empty string if ((optionBits & (XMP_PROP_VALUE_IS_STRUCT | XMP_PROP_VALUE_IS_ARRAY)) && (*value == 0)) { value = NULL; } try { txmp->SetProperty(schema, name, value, optionBits); ret = true; } catch(const XMP_Error & e) { set_error(e); } catch(...) { } return ret; }
static void ExportIPTC_LangAlt ( const SXMPMeta & xmp, IPTC_Manager * iptc, const char * xmpNS, const char * xmpProp, XMP_Uns8 id ) { std::string value; XMP_OptionBits xmpFlags; bool found = xmp.GetProperty ( xmpNS, xmpProp, 0, &xmpFlags ); if ( ! found ) { iptc->DeleteDataSet ( id ); return; } if ( ! XMP_ArrayIsAltText ( xmpFlags ) ) return; // ? Complain? Delete the DataSet? found = xmp.GetLocalizedText ( xmpNS, xmpProp, "", "x-default", 0, &value, 0 ); if ( ! found ) { iptc->DeleteDataSet ( id ); return; } NormalizeToCR ( &value ); size_t iptcCount = iptc->GetDataSet ( id, 0 ); if ( iptcCount > 1 ) iptc->DeleteDataSet ( id ); iptc->SetDataSet_UTF8 ( id, value.c_str(), (XMP_Uns32)value.size(), 0 ); // ! Don't append a 2nd DataSet! } // ExportIPTC_LangAlt
void exportAndRemoveProperties ( RIFF_MetaHandler* handler ) { SXMPMeta xmpObj = handler->xmpObj; exportXMPtoCr8rChunk ( handler, &handler->cr8rChunk ); // 1/4 BWF Bext extension chunk ----------------------------------------------- if ( handler->parent->format == kXMP_WAVFile ) { // applies only to WAV exportXMPtoBextChunk ( handler, &handler->bextChunk ); } // 2/4 DISP chunk if ( handler->parent->format == kXMP_WAVFile ) { // create for WAVE only std::string actualLang, xmpValue; bool r = xmpObj.GetLocalizedText ( kXMP_NS_DC, "title", "" , "x-default" , &actualLang, &xmpValue, 0 ); if ( r && ( actualLang == "x-default" ) ) { // prop exists? // the 'right' DISP is lead by a 32 bit low endian 0x0001 std::string dispValue = std::string( "\x1\0\0\0", 4 ); dispValue.append ( xmpValue ); if ( handler->dispChunk == 0 ) { handler->dispChunk = new RIFF::ValueChunk ( handler->riffChunks.at(0), std::string(), kChunk_DISP ); } // ! The NUL is optional in WAV to avoid a parsing bug in Audition 3 - can't handle implicit pad byte. handler->dispChunk->SetValue ( dispValue, ValueChunk::kNULisOptional ); } else { // remove Disp Chunk.. if ( handler->dispChunk != 0 ) { // ..if existing ContainerChunk* mainChunk = handler->riffChunks.at(0); Chunk* needle = handler->dispChunk; chunkVectIter iter = mainChunk->getChild ( needle ); if ( iter != mainChunk->children.end() ) { mainChunk->replaceChildWithJunk ( *iter ); handler->dispChunk = 0; mainChunk->hasChange = true; } } } } // 3/4 LIST:INFO exportXMPtoListChunk ( kChunk_LIST, kType_INFO, handler, &handler->listInfoChunk, listInfoProps ); // 4/4 LIST:Tdat exportXMPtoListChunk ( kChunk_LIST, kType_Tdat, handler, &handler->listTdatChunk, listTdatProps ); }
bool xmp_parse(XmpPtr xmp, const char *buffer, size_t len) { CHECK_PTR(xmp, false); CHECK_PTR(buffer, false); SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->ParseFromBuffer(buffer, len, kXMP_RequireXMPMeta ); } catch(const XMP_Error & e) { set_error(e); return false; } return true; }
static void ExportIPTC_IntellectualGenre ( const SXMPMeta & xmp, IPTC_Manager * iptc ) { std::string xmpValue; XMP_OptionBits xmpFlags; bool found = xmp.GetProperty ( kXMP_NS_IPTCCore, "IntellectualGenre", &xmpValue, &xmpFlags ); if ( ! found ) { iptc->DeleteDataSet ( kIPTC_IntellectualGenre ); return; } if ( ! XMP_PropIsSimple ( xmpFlags ) ) return; // ? Complain? Delete the DataSet? NormalizeToCR ( &xmpValue ); int i; XMP_StringPtr namePtr = xmpValue.c_str(); for ( i = 0; kIntellectualGenreMappings[i].name != 0; ++i ) { if ( strcmp ( namePtr, kIntellectualGenreMappings[i].name ) == 0 ) break; } if ( kIntellectualGenreMappings[i].name == 0 ) return; // Not a known genre, don't export it. std::string iimValue = kIntellectualGenreMappings[i].refNum; iimValue += ':'; iimValue += xmpValue; size_t iptcCount = iptc->GetDataSet ( kIPTC_IntellectualGenre, 0 ); if ( iptcCount > 1 ) iptc->DeleteDataSet ( kIPTC_IntellectualGenre ); iptc->SetDataSet_UTF8 ( kIPTC_IntellectualGenre, iimValue.c_str(), (XMP_Uns32)iimValue.size(), 0 ); // ! Don't append a 2nd DataSet! } // ExportIPTC_IntellectualGenre
bool xmp_has_property(XmpPtr xmp, const char *schema, const char *name) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = true; SXMPMeta *txmp = (SXMPMeta *)xmp; try { ret = txmp->DoesPropertyExist(schema, name); } catch(const XMP_Error & e) { set_error(e); ret = false; } catch(...) { ret = false; } return ret; }
bool xmp_set_array_item(XmpPtr xmp, const char *schema, const char *name, int32_t index, const char *value, uint32_t optionBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->SetArrayItem(schema, name, index, value, optionBits); ret = true; } catch(const XMP_Error & e) { set_error(e); } catch(...) { } return ret; }
bool xmp_set_property_int64(XmpPtr xmp, const char *schema, const char *name, int64_t value, uint32_t optionBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->SetProperty_Int64(schema, name, value, optionBits); ret = true; } catch(const XMP_Error & e) { set_error(e); } catch(...) { } return ret; }
bool xmp_serialize_and_format(XmpPtr xmp, XmpStringPtr buffer, uint32_t options, uint32_t padding, const char *newline, const char *tab, int32_t indent) { CHECK_PTR(xmp, false); CHECK_PTR(buffer, false); RESET_ERROR; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->SerializeToBuffer(STRING(buffer), options, padding, newline, tab, indent); } catch(const XMP_Error & e) { set_error(e); return false; } return true; }
bool xmp_get_property_int64(XmpPtr xmp, const char *schema, const char *name, int64_t * property, uint32_t *propsBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; try { SXMPMeta *txmp = (SXMPMeta *)xmp; XMP_OptionBits optionBits; ret = txmp->GetProperty_Int64(schema, name, property, &optionBits); if(propsBits) { *propsBits = optionBits; } } catch(const XMP_Error & e) { set_error(e); } return ret; }
static void ProcessPacket ( const char * fileName, FILE * inFile, size_t offset, size_t length ) { std::string xmlString; xmlString.append ( length, ' ' ); fseek ( inFile, offset, SEEK_SET ); fread ( (void*)xmlString.data(), 1, length, inFile ); char title [1000]; sprintf ( title, "// Dumping raw input for \"%s\" (%d..%d)", fileName, offset, (offset + length - 1) ); printf ( "// " ); for ( size_t i = 3; i < strlen(title); ++i ) printf ( "=" ); printf ( "\n\n%s\n\n%.*s\n\n", title, length, xmlString.c_str() ); fflush ( stdout ); SXMPMeta xmpObj; try { xmpObj.ParseFromBuffer ( xmlString.c_str(), length ); } catch ( ... ) { printf ( "## Parse failed\n\n" ); return; } xmpObj.DumpObject ( DumpCallback, stdout ); fflush ( stdout ); string xmpString; xmpObj.SerializeToBuffer ( &xmpString, kXMP_OmitPacketWrapper ); printf ( "\nPretty serialization, %d bytes :\n\n%s\n", xmpString.size(), xmpString.c_str() ); fflush ( stdout ); xmpObj.SerializeToBuffer ( &xmpString, (kXMP_OmitPacketWrapper | kXMP_UseCompactFormat) ); printf ( "Compact serialization, %d bytes :\n\n%s\n", xmpString.size(), xmpString.c_str() ); fflush ( stdout ); } // ProcessPacket
bool xmp_set_property_date(XmpPtr xmp, const char *schema, const char *name, const XmpDateTime *value, uint32_t optionBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; SXMPMeta *txmp = (SXMPMeta *)xmp; try { XMP_DateTime dt; ASSIGN(dt, (*value)); txmp->SetProperty_Date(schema, name, dt, optionBits); ret = true; } catch(const XMP_Error & e) { set_error(e); } catch(...) { } return ret; }
bool xmp_delete_localized_text(XmpPtr xmp, const char *schema, const char *name, const char *genericLang, const char *specificLang) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = true; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->DeleteLocalizedText(schema, name, genericLang, specificLang); } catch(const XMP_Error & e) { set_error(e); ret = false; } catch(...) { ret = false; } return ret; }
bool xmp_get_property_int32(XmpPtr xmp, const char *schema, const char *name, int32_t * property, uint32_t *propsBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; try { SXMPMeta *txmp = (SXMPMeta *)xmp; XMP_OptionBits optionBits; // the long converstion is needed until XMPCore is fixed it use proper types. ret = txmp->GetProperty_Int(schema, name, property, &optionBits); if(propsBits) { *propsBits = optionBits; } } catch(const XMP_Error & e) { set_error(e); } return ret; }
bool xmp_get_array_item(XmpPtr xmp, const char *schema, const char *name, int32_t index, XmpStringPtr property, uint32_t *propsBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; try { SXMPMeta *txmp = (SXMPMeta *)xmp; XMP_OptionBits optionBits; ret = txmp->GetArrayItem(schema, name, index, STRING(property), &optionBits); if(propsBits) { *propsBits = optionBits; } } catch(const XMP_Error & e) { set_error(e); } return ret; }
bool xmp_set_localized_text(XmpPtr xmp, const char *schema, const char *name, const char *genericLang, const char *specificLang, const char *value, uint32_t optionBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = true; SXMPMeta *txmp = (SXMPMeta *)xmp; try { txmp->SetLocalizedText(schema, name, genericLang, specificLang, value, optionBits); } catch(const XMP_Error & e) { set_error(e); ret = false; } catch(...) { ret = false; } return ret; }
AssetMediaInfoPtr AssetMediaInfo::Create( AssetMediaType inType, ASL::Guid const& inGuid, ASL::String const& inMediaPath, XMPText inXMP, ASL::String const& inFileContent, ASL::String const& inCustomMetadata, ASL::String const& inCreateTime, ASL::String const& inLastModifyTime, ASL::String const& inTimeBase, ASL::String const& inNtsc, ASL::String const& inAliasName, bool inNeedSavePreCheck) { XMPText xmp = inXMP; if (inXMP == NULL || inXMP->empty() || !TestValidXMPString(inXMP)) { SXMPMeta metadata; XMPText fileXMPBuffer(new ASL::StdString); metadata.SerializeToBuffer(fileXMPBuffer.get(), kXMP_OmitPacketWrapper); xmp = fileXMPBuffer; } return AssetMediaInfoPtr(new AssetMediaInfo( inType, inGuid, inMediaPath, xmp, inFileContent, inCustomMetadata, inCreateTime, inLastModifyTime, inTimeBase, inNtsc, inAliasName, inNeedSavePreCheck)); }
void PhotoDataUtils::ExportPSIR ( const SXMPMeta & xmp, PSIR_Manager * psir ) { bool found; std::string utf8Value; try { // Don't let errors with one stop the others. found = xmp.GetProperty ( kXMP_NS_XMP_Rights, "Marked", &utf8Value, 0 ); if ( ! found ) { psir->DeleteImgRsrc ( kPSIR_CopyrightFlag ); } else { bool copyrighted = SXMPUtils::ConvertToBool ( utf8Value ); psir->SetImgRsrc ( kPSIR_CopyrightFlag, ©righted, 1 ); } } catch ( ... ) { // Do nothing, let other exports proceed. // ? Notify client? } try { // Don't let errors with one stop the others. found = xmp.GetProperty ( kXMP_NS_XMP_Rights, "WebStatement", &utf8Value, 0 ); if ( ! found ) { psir->DeleteImgRsrc ( kPSIR_CopyrightURL ); } else if ( ! ignoreLocalText ) { std::string localValue; ReconcileUtils::UTF8ToLocal ( utf8Value.c_str(), utf8Value.size(), &localValue ); psir->SetImgRsrc ( kPSIR_CopyrightURL, localValue.c_str(), (XMP_Uns32)localValue.size() ); } else if ( ReconcileUtils::IsASCII ( utf8Value.c_str(), utf8Value.size() ) ) { psir->SetImgRsrc ( kPSIR_CopyrightURL, utf8Value.c_str(), (XMP_Uns32)utf8Value.size() ); } else { psir->DeleteImgRsrc ( kPSIR_CopyrightURL ); } } catch ( ... ) { // Do nothing, let other exports proceed. // ? Notify client? } } // PhotoDataUtils::ExportPSIR;
static void ExportIPTC_Date ( XMP_Uns8 dateID, const SXMPMeta & xmp, IPTC_Manager * iptc ) { XMP_Uns8 timeID; XMP_StringPtr xmpNS, xmpProp; if ( dateID == kIPTC_DateCreated ) { timeID = kIPTC_TimeCreated; xmpNS = kXMP_NS_Photoshop; xmpProp = "DateCreated"; } else if ( dateID == kIPTC_DigitalCreateDate ) { timeID = kIPTC_DigitalCreateTime; xmpNS = kXMP_NS_XMP; xmpProp = "CreateDate"; } else { XMP_Throw ( "Unrecognized dateID", kXMPErr_BadParam ); } iptc->DeleteDataSet ( dateID ); // ! Either the XMP does not exist and we want to iptc->DeleteDataSet ( timeID ); // ! delete the IPTC, or we're replacing the IPTC. XMP_DateTime xmpValue; bool found = xmp.GetProperty_Date ( xmpNS, xmpProp, &xmpValue, 0 ); if ( ! found ) return; char iimValue[16]; // AUDIT: Big enough for "YYYYMMDD" (8) and "HHMMSS+HHMM" (11). // Set the IIM date portion as YYYYMMDD with zeroes for unknown parts. snprintf ( iimValue, sizeof(iimValue), "%04d%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.year, xmpValue.month, xmpValue.day ); iptc->SetDataSet_UTF8 ( dateID, iimValue, 8 ); // Set the IIM time portion as HHMMSS+HHMM (or -HHMM). Allow a missing time zone. if ( xmpValue.hasTimeZone ) { snprintf ( iimValue, sizeof(iimValue), "%02d%02d%02d%c%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.hour, xmpValue.minute, xmpValue.second, ((xmpValue.tzSign == kXMP_TimeWestOfUTC) ? '-' : '+'), xmpValue.tzHour, xmpValue.tzMinute ); iptc->SetDataSet_UTF8 ( timeID, iimValue, 11 ); } else if ( xmpValue.hasTime ) { snprintf ( iimValue, sizeof(iimValue), "%02d%02d%02d", // AUDIT: Use of sizeof(iimValue) is safe. xmpValue.hour, xmpValue.minute, xmpValue.second ); iptc->SetDataSet_UTF8 ( timeID, iimValue, 6 ); } else { iptc->DeleteDataSet ( timeID ); } } // ExportIPTC_Date
static void ProcessFile ( const char * fileName ) { bool ok; char buffer [1000]; SXMPMeta xmpMeta; SXMPFiles xmpFile; XMP_FileFormat format; XMP_OptionBits openFlags, handlerFlags; XMP_PacketInfo xmpPacket; sprintf ( buffer, "Dumping main XMP for %s", fileName ); WriteMinorLabel ( sLogFile, buffer ); xmpFile.OpenFile ( fileName, kXMP_UnknownFile, kXMPFiles_OpenForRead ); ok = xmpFile.GetFileInfo ( 0, &openFlags, &format, &handlerFlags ); if ( ! ok ) return; fprintf ( sLogFile, "File info : format = \"%.4s\", handler flags = %.8X\n", &format, handlerFlags ); fflush ( sLogFile ); ok = xmpFile.GetXMP ( &xmpMeta, 0, &xmpPacket ); if ( ! ok ) return; XMP_Int32 offset = (XMP_Int32)xmpPacket.offset; XMP_Int32 length = xmpPacket.length; fprintf ( sLogFile, "Packet info : offset = %d, length = %d\n", offset, length ); fflush ( sLogFile ); fprintf ( sLogFile, "\nInitial XMP from %s\n", fileName ); xmpMeta.DumpObject ( DumpCallback, sLogFile ); xmpFile.CloseFile(); } // ProcessFile
bool xmp_get_property_date(XmpPtr xmp, const char *schema, const char *name, XmpDateTime *property, uint32_t *propsBits) { CHECK_PTR(xmp, false); RESET_ERROR; bool ret = false; try { SXMPMeta *txmp = (SXMPMeta *)xmp; XMP_OptionBits optionBits; XMP_DateTime dt; // memset((void*)&dt, 1, sizeof(XMP_DateTime)); ret = txmp->GetProperty_Date(schema, name, &dt, &optionBits); ASSIGN((*property), dt); if(propsBits) { *propsBits = optionBits; } } catch(const XMP_Error & e) { set_error(e); } return ret; }
bool ASF_LegacyManager::CheckDigest ( const SXMPMeta& xmp ) { bool ret = false; if ( ! digestComputed ) this->ComputeDigest(); std::string oldDigest; if ( xmp.GetProperty ( kXMP_NS_ASF, "NativeDigest", &oldDigest, 0 ) ) { ret = (digestStr == oldDigest); } return ret; }
static bool CreatorAtom_SetProperties ( SXMPMeta& xmpObj, const MOV_MetaHandler::CreatorAtomStrings& creatorAtomStrings ) { if ( ! creatorAtomStrings.posixProjectPath.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "macAtom", kXMP_NS_CreatorAtom, "posixProjectPath", creatorAtomStrings.posixProjectPath, 0 ); } if ( ! creatorAtomStrings.uncProjectPath.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "windowsAtom", kXMP_NS_CreatorAtom, "uncProjectPath", creatorAtomStrings.uncProjectPath, 0 ); } if ( ! creatorAtomStrings.projectRefType.empty() ) { xmpObj.SetStructField ( kXMP_NS_DM, "projectRef", kXMP_NS_DM, "type", creatorAtomStrings.projectRefType.c_str()); } if ( ! creatorAtomStrings.applicationCode.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "macAtom", kXMP_NS_CreatorAtom, "applicationCode", creatorAtomStrings.applicationCode, 0 ); } if ( ! creatorAtomStrings.invocationAppleEvent.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "macAtom", kXMP_NS_CreatorAtom, "invocationAppleEvent", creatorAtomStrings.invocationAppleEvent, 0 ); } if ( ! creatorAtomStrings.extension.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "windowsAtom", kXMP_NS_CreatorAtom, "extension", creatorAtomStrings.extension, 0 ); } if ( ! creatorAtomStrings.invocationFlags.empty() ) { xmpObj.SetStructField ( kXMP_NS_CreatorAtom, "windowsAtom", kXMP_NS_CreatorAtom, "invocationFlags", creatorAtomStrings.invocationFlags, 0 ); } if ( ! creatorAtomStrings.creatorTool.empty() ) { xmpObj.SetProperty ( kXMP_NS_XMP, "CreatorTool", creatorAtomStrings.creatorTool, 0 ); } return ok; }
int XmpParser::encode( std::string& xmpPacket, const XmpData& xmpData, uint16_t formatFlags, uint32_t padding) { try { if (xmpData.empty()) { xmpPacket.clear(); return 0; } if (!initialize()) { #ifndef SUPPRESS_WARNINGS std::cerr << "XMP Toolkit initialization failed.\n"; #endif return 2; } SXMPMeta meta; for (XmpData::const_iterator i = xmpData.begin(); i != xmpData.end(); ++i) { const std::string ns = XmpProperties::ns(i->groupName()); XMP_OptionBits options = 0; if (i->typeId() == langAlt) { // Encode Lang Alt property const LangAltValue* la = dynamic_cast<const LangAltValue*>(&i->value()); if (la == 0) throw Error(43, i->key()); int idx = 1; // write the default first LangAltValue::ValueType::const_iterator k = la->value_.find("x-default"); if (k != la->value_.end()) { #ifdef DEBUG printNode(ns, i->tagName(), k->second, 0); #endif meta.AppendArrayItem(ns.c_str(), i->tagName().c_str(), kXMP_PropArrayIsAlternate, k->second.c_str()); const std::string item = i->tagName() + "[" + toString(idx++) + "]"; meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", k->first.c_str()); } for (k = la->value_.begin(); k != la->value_.end(); ++k) { if (k->first == "x-default") continue; #ifdef DEBUG printNode(ns, i->tagName(), k->second, 0); #endif meta.AppendArrayItem(ns.c_str(), i->tagName().c_str(), kXMP_PropArrayIsAlternate, k->second.c_str()); const std::string item = i->tagName() + "[" + toString(idx++) + "]"; meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", k->first.c_str()); } continue; } // Todo: Xmpdatum should have an XmpValue, not a Value const XmpValue* val = dynamic_cast<const XmpValue*>(&i->value()); assert(val); options = xmpArrayOptionBits(val->xmpArrayType()) | xmpArrayOptionBits(val->xmpStruct()); if ( i->typeId() == xmpBag || i->typeId() == xmpSeq || i->typeId() == xmpAlt) { #ifdef DEBUG printNode(ns, i->tagName(), "", options); #endif meta.SetProperty(ns.c_str(), i->tagName().c_str(), 0, options); for (int idx = 0; idx < i->count(); ++idx) { const std::string item = i->tagName() + "[" + toString(idx + 1) + "]"; #ifdef DEBUG printNode(ns, item, i->toString(idx), 0); #endif meta.SetProperty(ns.c_str(), item.c_str(), i->toString(idx).c_str()); } continue; } if (i->typeId() == xmpText) { if (i->count() == 0) { #ifdef DEBUG printNode(ns, i->tagName(), "", options); #endif meta.SetProperty(ns.c_str(), i->tagName().c_str(), 0, options); } else { #ifdef DEBUG printNode(ns, i->tagName(), i->toString(0), options); #endif meta.SetProperty(ns.c_str(), i->tagName().c_str(), i->toString(0).c_str(), options); } continue; } // Don't let any Xmpdatum go by unnoticed throw Error(38, i->tagName(), TypeInfo::typeName(i->typeId())); } std::string tmpPacket; meta.SerializeToBuffer(&tmpPacket, xmpFormatOptionBits(static_cast<XmpFormatFlags>(formatFlags)), padding); // throws xmpPacket = tmpPacket; return 0; } catch (const XMP_Error& e) { #ifndef SUPPRESS_WARNINGS std::cerr << Error(40, e.GetID(), e.GetErrMsg()) << "\n"; #endif return 3; }} // XmpParser::decode
/** * Initializes the toolkit and attempts to open a file for updating its metadata. Initially * an attempt to open the file is done with a handler, if this fails then the file is opened with * packet scanning. Once the file is open several properties are read and displayed in the console. * * Several properties are then modified, first by checking for their existence and then, if they * exist, by updating their values. The updated properties are then displayed again in the console. * * Next a new XMP object is created from an RDF stream, the properties from the new XMP object are * appended to the original XMP object and the updated properties are displayed in the console for * last time. * * The updated XMP object is then serialized in different formats and written to text files. Lastly, * the modified XMP is written back to the resource file. */ int main ( int argc, const char * argv[] ) { if ( argc != 2 ) // 2 := command and 1 parameter { cout << "usage: ModifyingXMP (filename)" << endl; return 0; } string filename = string( argv[1] ); if(!SXMPMeta::Initialize()) { cout << "Could not initialize toolkit!"; return -1; } XMP_OptionBits options = 0; #if UNIX_ENV options |= kXMPFiles_ServerMode; #endif // Must initialize SXMPFiles before we use it if(SXMPFiles::Initialize(options)) { try { // Options to open the file with - open for editing and use a smart handler XMP_OptionBits opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler; bool ok; SXMPFiles myFile; std::string status = ""; // First we try and open the file ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts); if( ! ok ) { status += "No smart handler available for " + filename + "\n"; status += "Trying packet scanning.\n"; // Now try using packet scanning opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning; ok = myFile.OpenFile(filename, kXMP_UnknownFile, opts); } // If the file is open then read get the XMP data if(ok) { cout << status << endl; cout << filename << " is opened successfully" << endl; // Create the XMP object and get the XMP data SXMPMeta meta; myFile.GetXMP(&meta); // Display some properties in the console displayPropertyValues(&meta); /////////////////////////////////////////////////// // Now modify the XMP if(meta.DoesPropertyExist(kXMP_NS_XMP, "CreatorTool")) { // Update xap:CreatorTool - we don't need to set any option bits meta.SetProperty(kXMP_NS_XMP, "CreatorTool", "Updated By XMP SDK", 0); } // Update the Metadata Date XMP_DateTime updatedTime; // Get the current time. This is a UTC time automatically // adjusted for the local time SXMPUtils::CurrentDateTime(&updatedTime); if(meta.DoesPropertyExist(kXMP_NS_XMP, "MetadataDate")) { meta.SetProperty_Date(kXMP_NS_XMP, "MetadataDate", updatedTime, 0); } // Add an item onto the dc:creator array // Note the options used, kXMP_PropArrayIsOrdered, if the array does not exist it will be created meta.AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Author Name", 0); meta.AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Another Author Name", 0); // Now update alt-text properties meta.SetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", "An English title"); meta.SetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", "Un titre Francais"); // Display the properties again to show changes cout << "After update:" << endl; displayPropertyValues(&meta); // Create a new XMP object from an RDF string SXMPMeta rdfMeta = createXMPFromRDF(); // Append the newly created properties onto the original XMP object // This will: // a) Add ANY new TOP LEVEL properties in the source (rdfMeta) to the destination (meta) // b) Replace any top level properties in the source with the matching properties from the destination SXMPUtils::ApplyTemplate(&meta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties); // Display the properties again to show changes cout << "After Appending Properties:" << endl; displayPropertyValues(&meta); // Serialize the packet and write the buffer to a file // Let the padding be computed and use the default linefeed and indents without limits string metaBuffer; meta.SerializeToBuffer(&metaBuffer, 0, 0, "", "", 0); // Write the packet to a file as RDF writeRDFToFile(&metaBuffer, filename+"_XMP_RDF.txt"); // Write the packet to a file but this time as compact RDF XMP_OptionBits outOpts = kXMP_OmitPacketWrapper | kXMP_UseCompactFormat; meta.SerializeToBuffer(&metaBuffer, outOpts); writeRDFToFile(&metaBuffer, filename+"_XMP_RDF_Compact.txt"); // Check we can put the XMP packet back into the file if(myFile.CanPutXMP(meta)) { // If so then update the file with the modified XMP myFile.PutXMP(meta); } // Close the SXMPFile. This *must* be called. The XMP is not // actually written and the disk file is not closed until this call is made. myFile.CloseFile(); } else { cout << "Unable to open " << filename << endl; } } catch(XMP_Error & e) { cout << "ERROR: " << e.GetErrMsg() << endl; } // Terminate the toolkit SXMPFiles::Terminate(); SXMPMeta::Terminate(); } else { cout << "Could not initialize SXMPFiles."; return -1; } return 0; }