⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reconcileiptc.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 2 页
字号:
						ImportIPTC_SubjectCode ( iptc, xmp, digestState, thisDS.xmpNS, thisDS.xmpProp );					} else if ( thisDS.id == kIPTC_DateCreated ) {						ImportIPTC_DateCreated ( iptc, xmp, digestState, thisDS.xmpNS, thisDS.xmpProp );					} 					break;				}		} catch ( ... ) {				// Do nothing, let other imports proceed.			// ? Notify client?			}	}	}	// ReconcileUtils::ImportIPTC;// =================================================================================================// ReconcileUtils::ImportPSIR// ==========================//// There are only 2 standalone Photoshop image resources for XMP properties://    1034 - Copyright Flag - 0/1 Boolean mapped to xmpRights:Marked.//    1035 - Copyright URL - Local OS text mapped to xmpRights:WebStatement.// ! Photoshop does not use a true/false/missing model for PSIR 1034. Instead it essentially uses a// ! yes/don't-know model when importing. A missing or 0 value for PSIR 1034 cause xmpRights:Marked// ! to be deleted.// **** What about 1008 and 1020?void ReconcileUtils::ImportPSIR ( const PSIR_Manager & psir, SXMPMeta * xmp, int digestState ){	PSIR_Manager::ImgRsrcInfo rsrcInfo;	bool import;		if ( digestState == kDigestMatches ) return;		if ( digestState == kDigestDiffers ) {		// Delete the mapped XMP. This forces replacement and catches legacy deletions.		xmp->DeleteProperty ( kXMP_NS_XMP_Rights, "Marked" );		xmp->DeleteProperty ( kXMP_NS_XMP_Rights, "WebStatement" );	}		try {	// Don't let errors with one stop the others.		import = psir.GetImgRsrc ( kPSIR_CopyrightFlag, &rsrcInfo );		if ( import ) import = (! xmp->DoesPropertyExist ( kXMP_NS_XMP_Rights, "Marked" ));		if ( import && (rsrcInfo.dataLen == 1) && (*((XMP_Uns8*)rsrcInfo.dataPtr) != 0) ) {			xmp->SetProperty_Bool ( kXMP_NS_XMP_Rights, "Marked", true );		}	} catch ( ... ) {		// Do nothing, let other imports proceed.		// ? Notify client?	}		try {	// Don't let errors with one stop the others.		import = psir.GetImgRsrc ( kPSIR_CopyrightURL, &rsrcInfo );		if ( import ) import = (! xmp->DoesPropertyExist ( kXMP_NS_XMP_Rights, "WebStatement" ));		if ( import ) {			std::string utf8;			ReconcileUtils::LocalToUTF8 ( rsrcInfo.dataPtr, rsrcInfo.dataLen, &utf8 );			xmp->SetProperty ( kXMP_NS_XMP_Rights, "WebStatement", utf8.c_str() );		}	} catch ( ... ) {		// Do nothing, let other imports proceed.		// ? Notify client?	}	}	// ReconcileUtils::ImportPSIR;// =================================================================================================// =================================================================================================// =================================================================================================// ExportIPTC_Simple// =================static void ExportIPTC_Simple ( 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, &value, &xmpFlags );	if ( ! found ) {		iptc->DeleteDataSet ( id );		return;	}		if ( ! XMP_PropIsSimple ( xmpFlags ) ) return;	// ? Complain? Delete the DataSet?		NormalizeToCR ( &value );		size_t iptcCount = iptc->GetDataSet ( id, 0 );	if ( iptcCount > 1 ) iptc->DeleteDataSet ( id );	iptc->SetDataSet_UTF8 ( id, value.c_str(), value.size(), 0 );	// ! Don't append a 2nd DataSet!}	// ExportIPTC_Simple// =================================================================================================// ExportIPTC_LangAlt// ==================static void ExportIPTC_LangAlt ( 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(), value.size(), 0 );	// ! Don't append a 2nd DataSet!}	// ExportIPTC_LangAlt// =================================================================================================// ExportIPTC_Array// ================//// Array exporting needs a bit of care to preserve the detection of XMP-only updates. If the current// XMP and IPTC array sizes differ, delete the entire IPTC and append all new values. If they match,// set the individual values in order - which lets SetDataSet apply its no-change optimization.static void ExportIPTC_Array ( 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?	size_t xmpCount  = xmp->CountArrayItems ( xmpNS, xmpProp );	size_t iptcCount = iptc->GetDataSet ( id, 0 );		if ( xmpCount != iptcCount ) iptc->DeleteDataSet ( id );	for ( size_t 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(), value.size(), ds );	// ! Appends if necessary.	}}	// ExportIPTC_Array// =================================================================================================// ExportIPTC_IntellectualGenre// ============================//// Export DataSet 2:04. In the IIM this is a 3 digit number, a colon, and a text name. Even though// the number is the more formal part, the IPTC4XMP rule is that the name is imported to XMP and the// number is dropped. Also, even though IIMv4.1 says that 2:04 is repeatable, the XMP property to// which it is mapped is simple. Look up the XMP value in a list of known genres to get the number.static void ExportIPTC_IntellectualGenre ( SXMPMeta * xmp, IPTC_Manager * iptc,										   const char * xmpNS, const char * xmpProp ){	std::string    xmpValue;	XMP_OptionBits xmpFlags;	bool found = xmp->GetProperty ( xmpNS, xmpProp, &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(), iimValue.size(), 0 );	// ! Don't append a 2nd DataSet!}	// ExportIPTC_IntellectualGenre// =================================================================================================// ExportIPTC_SubjectCode// ======================//// Export 2:12 DataSets from an unordered array. In the IIM each DataSet is composed of 5 colon// separated sections: a provider name, an 8 digit reference number, and 3 optional names for the// levels of the reference number hierarchy. The IPTC4XMP mapping rule is that only the reference// number is imported to XMP. We export with a fixed provider of "IPTC" and no optional names.static void ExportIPTC_SubjectCode ( SXMPMeta * xmp, IPTC_Manager * iptc,									 const char * xmpNS, const char * xmpProp ){	std::string    xmpValue, iimValue;	XMP_OptionBits xmpFlags;	bool found = xmp->GetProperty ( xmpNS, xmpProp, 0, &xmpFlags );	if ( ! found ) {		iptc->DeleteDataSet ( kIPTC_SubjectCode );		return;	}	if ( ! XMP_PropIsArray ( xmpFlags ) ) return;	// ? Complain? Delete the DataSet?	size_t xmpCount  = xmp->CountArrayItems ( xmpNS, xmpProp );	size_t iptcCount = iptc->GetDataSet ( kIPTC_SubjectCode, 0 );		if ( xmpCount != iptcCount ) iptc->DeleteDataSet ( kIPTC_SubjectCode );	for ( size_t ds = 0; ds < xmpCount; ++ds ) {	// ! XMP arrays are indexed from 1, IPTC from 0.		(void) xmp->GetArrayItem ( xmpNS, xmpProp, 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(), iimValue.size(), ds );	// ! Appends if necessary.	}}	// ExportIPTC_SubjectCode// =================================================================================================// ExportIPTC_DateCreated// ======================//// The IPTC date and time are "YYYYMMDD" and "HHMMSSxHHMM" where 'x' is '+' or '-'. Export the IPTC// time only if already present, or if the XMP has a time portion.static void ExportIPTC_DateCreated ( SXMPMeta * xmp, IPTC_Manager * iptc,									 const char * xmpNS, const char * xmpProp ){	std::string    xmpStr;	XMP_DateTime   xmpValue;	XMP_OptionBits xmpFlags;	bool xmpHasTime = false;	bool found = xmp->GetProperty ( xmpNS, xmpProp, &xmpStr, &xmpFlags );	if ( found ) {		SXMPUtils::ConvertToDate ( xmpStr.c_str(), &xmpValue );		if ( xmpStr.size() > 10 ) xmpHasTime = true;	// Date-only values are up to "YYYY-MM-DD".	} else {		iptc->DeleteDataSet ( kIPTC_DateCreated );		iptc->DeleteDataSet ( kIPTC_TimeCreated );		return;	}	char iimValue[16];		// Set the IIM date portion.		snprintf ( iimValue, sizeof(iimValue), "%.4d%.2d%.2d",	// AUDIT: Use of sizeof(iimValue) is safe.			   xmpValue.year, xmpValue.month, xmpValue.day );	if ( iimValue[8] != 0 ) return;	// ? Complain? Delete the DataSet?		size_t iptcCount = iptc->GetDataSet ( kIPTC_DateCreated, 0 );	if ( iptcCount > 1 ) iptc->DeleteDataSet ( kIPTC_DateCreated );	iptc->SetDataSet_UTF8 ( kIPTC_DateCreated, iimValue, 8, 0 );	// ! Don't append a 2nd DataSet!		// Set the IIM time portion.	iptcCount = iptc->GetDataSet ( kIPTC_TimeCreated, 0 );		if ( (iptcCount > 0) || xmpHasTime ) {			snprintf ( iimValue, sizeof(iimValue), "%.2d%.2d%.2d%c%.2d%.2d",	// AUDIT: Use of sizeof(iimValue) is safe.				   xmpValue.hour, xmpValue.minute, xmpValue.second,				   ((xmpValue.tzSign == kXMP_TimeWestOfUTC) ? '-' : '+'), xmpValue.tzHour, xmpValue.tzMinute );		if ( iimValue[11] != 0 ) return;	// ? Complain? Delete the DataSet?				if ( iptcCount > 1 ) iptc->DeleteDataSet ( kIPTC_TimeCreated );			iptc->SetDataSet_UTF8 ( kIPTC_TimeCreated, iimValue, 11, 0 );	// ! Don't append a 2nd DataSet!		}}	// ExportIPTC_DateCreated// =================================================================================================// ReconcileUtils::ExportIPTC// ==========================void ReconcileUtils::ExportIPTC ( SXMPMeta * xmp, IPTC_Manager * iptc ){		for ( size_t i = 0; kKnownDataSets[i].id != 255; ++i ) {			try {	// Don't let errors with one stop the others.				const DataSetCharacteristics & thisDS = kKnownDataSets[i];						switch ( thisDS.mapForm ) {					case kIPTC_MapSimple :					ExportIPTC_Simple ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp, thisDS.id );					break;					case kIPTC_MapLangAlt :					ExportIPTC_LangAlt ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp, thisDS.id );					break;					case kIPTC_MapArray :					ExportIPTC_Array ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp, thisDS.id );					break;					case kIPTC_MapSpecial :					if ( thisDS.id == kIPTC_IntellectualGenre ) {						ExportIPTC_IntellectualGenre ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp );					} else if ( thisDS.id == kIPTC_SubjectCode ) {						ExportIPTC_SubjectCode ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp );					} else if ( thisDS.id == kIPTC_DateCreated ) {						ExportIPTC_DateCreated ( xmp, iptc, thisDS.xmpNS, thisDS.xmpProp );					} 					break;				}		} catch ( ... ) {				// Do nothing, let other exports proceed.			// ? Notify client?			}	}	}	// ReconcileUtils::ExportIPTC;// =================================================================================================// ReconcileUtils::ExportPSIR// ==========================//// There are only 2 standalone Photoshop image resources for XMP properties://    1034 - Copyright Flag - 0/1 Boolean mapped to xmpRights:Marked.//    1035 - Copyright URL - Local OS text mapped to xmpRights:WebStatement.// ! Photoshop does not use a true/false/missing model for PSIR 1034. Instead it is always written,// ! a missing xmpRights:Marked results in 0 for PSIR 1034.// ! We don't bother with the CR<->LF normalization for xmpRights:WebStatement. Very little chance// ! of having a raw CR character in a URI.void ReconcileUtils::ExportPSIR ( const SXMPMeta & xmp, PSIR_Manager * psir ){	bool found;	std::string utf8Value;		try {	// Don't let errors with one stop the others.		bool copyrighted = false;		found = xmp.GetProperty ( kXMP_NS_XMP_Rights, "Marked", &utf8Value, 0 );		if ( found ) copyrighted = SXMPUtils::ConvertToBool ( utf8Value );		psir->SetImgRsrc ( kPSIR_CopyrightFlag, &copyrighted, 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 {			std::string localValue;			ReconcileUtils::UTF8ToLocal ( utf8Value.c_str(), utf8Value.size(), &localValue );			psir->SetImgRsrc ( kPSIR_CopyrightURL, localValue.c_str(), localValue.size() );		}	} catch ( ... ) {		// Do nothing, let other exports proceed.		// ? Notify client?	}}	// ReconcileUtils::ExportPSIR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -