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

📄 reconcileiptc.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// =================================================================================================// ADOBE SYSTEMS INCORPORATED// Copyright 2006-2007 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.// =================================================================================================#include "XMP_Environment.h"	// ! This must be the first include.#include "Reconcile_Impl.hpp"#if XMP_WinBuild	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)	#pragma warning ( disable : 4996 )	// '...' was declared deprecated#endif// =================================================================================================/// \file ReconcileIPTC.cpp/// \brief Utilities to reconcile between XMP and legacy IPTC and PSIR metadata.///// =================================================================================================// =================================================================================================// NormalizeToCR// =============static inline void NormalizeToCR ( std::string * value ){	char * strPtr = (char*) value->data();	char * strEnd = strPtr + value->size();		for ( ; strPtr < strEnd; ++strPtr ) {		if ( *strPtr == kLF ) *strPtr = kCR;	}	}	// NormalizeToCR// =================================================================================================// NormalizeToLF// =============static inline void NormalizeToLF ( std::string * value ){	char * strPtr = (char*) value->data();	char * strEnd = strPtr + value->size();		for ( ; strPtr < strEnd; ++strPtr ) {		if ( *strPtr == kCR ) *strPtr = kLF;	}	}	// NormalizeToLF// =================================================================================================// ComputeIPTCDigest// =================//// Compute a 128 bit (16 byte) MD5 digest of the full IPTC block.static inline void ComputeIPTCDigest ( IPTC_Manager * iptc, MD5_Digest * digest ){	MD5_CTX    context;	void *     iptcData;	XMP_Uns32  iptcLen;	iptcLen = iptc->UpdateMemoryDataSets ( &iptcData );		MD5Init ( &context );	MD5Update ( &context, (XMP_Uns8*)iptcData, iptcLen );	MD5Final ( *digest, &context );}	// ComputeIPTCDigest;// =================================================================================================// ReconcileUtils::CheckIPTCDigest// ===============================int ReconcileUtils::CheckIPTCDigest ( IPTC_Manager * iptc, const PSIR_Manager & psir ){	MD5_Digest newDigest;	PSIR_Manager::ImgRsrcInfo ir1061;		ComputeIPTCDigest ( iptc, &newDigest );	bool found = psir.GetImgRsrc ( kPSIR_IPTCDigest, &ir1061 );	if ( ! found ) return kDigestMissing;	if ( ir1061.dataLen != 16 ) return kDigestMissing;		if ( memcmp ( newDigest, ir1061.dataPtr, 16 ) == 0 ) return kDigestMatches;	return kDigestDiffers;	}	// ReconcileUtils::CheckIPTCDigest// =================================================================================================// ReconcileUtils::SetIPTCDigest// ===============================void ReconcileUtils::SetIPTCDigest ( IPTC_Manager * iptc, PSIR_Manager * psir ){	MD5_Digest newDigest;		ComputeIPTCDigest ( iptc, &newDigest );	psir->SetImgRsrc ( kPSIR_IPTCDigest, &newDigest, sizeof(newDigest) );	}	// ReconcileUtils::SetIPTCDigest// =================================================================================================// =================================================================================================// =================================================================================================// ImportIPTC_Simple// =================static void ImportIPTC_Simple ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,								XMP_Uns8 id, const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		xmp->DeleteProperty ( xmpNS, xmpProp );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	}	std::string utf8Str;	size_t count = iptc.GetDataSet_UTF8 ( id, &utf8Str );	if ( count != 0 ) {		NormalizeToLF ( &utf8Str );		xmp->SetProperty ( xmpNS, xmpProp, utf8Str.c_str() );	}}	// ImportIPTC_Simple// =================================================================================================// ImportIPTC_LangAlt// ==================static void ImportIPTC_LangAlt ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,								 XMP_Uns8 id, const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		std::string xdItemPath = xmpProp;	// Delete just the x-default item, not the whole array.		xdItemPath += "[?xml:lang='x-default']";		xmp->DeleteProperty ( xmpNS, xdItemPath.c_str() );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	// Check the entire array here.	}	std::string utf8Str;	size_t count = iptc.GetDataSet_UTF8 ( id, &utf8Str );		if ( count != 0 ) {		NormalizeToLF ( &utf8Str );		xmp->SetLocalizedText ( xmpNS, xmpProp, "", "x-default", utf8Str.c_str() );	}}	// ImportIPTC_LangAlt// =================================================================================================// ImportIPTC_Array// ================static void ImportIPTC_Array ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,							   XMP_Uns8 id, const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		xmp->DeleteProperty ( xmpNS, xmpProp );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	}	std::string utf8Str;	size_t count = iptc.GetDataSet ( id, 0 );	for ( size_t ds = 0; ds < count; ++ds ) {		(void) iptc.GetDataSet_UTF8 ( id, &utf8Str, ds );		NormalizeToLF ( &utf8Str );		xmp->AppendArrayItem ( xmpNS, xmpProp, kXMP_PropArrayIsUnordered, utf8Str.c_str() );	}}	// ImportIPTC_Array// =================================================================================================// ImportIPTC_IntellectualGenre// ============================//// Import DataSet 2:04. In the IIM this is a 3 digit number, a colon, and an optional 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.static void ImportIPTC_IntellectualGenre ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,										   const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		xmp->DeleteProperty ( xmpNS, xmpProp );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	}	std::string utf8Str;	size_t count = iptc.GetDataSet_UTF8 ( kIPTC_IntellectualGenre, &utf8Str );	if ( count == 0 ) return;	NormalizeToLF ( &utf8Str );		XMP_StringPtr namePtr = utf8Str.c_str() + 4;		if ( utf8Str.size() <= 4 ) {		// No name in the IIM. Look up the number in our list of known genres.		int i;		XMP_StringPtr numPtr = utf8Str.c_str();		for ( i = 0; kIntellectualGenreMappings[i].refNum != 0; ++i ) {			if ( strncmp ( numPtr, kIntellectualGenreMappings[i].refNum, 3 ) == 0 ) break;		}		if ( kIntellectualGenreMappings[i].refNum == 0 ) return;		namePtr = kIntellectualGenreMappings[i].name;	}	xmp->SetProperty ( xmpNS, xmpProp, namePtr );}	// ImportIPTC_IntellectualGenre// =================================================================================================// ImportIPTC_SubjectCode// ======================//// Import all 2:12 DataSets into 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.static void ImportIPTC_SubjectCode ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,									 const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		xmp->DeleteProperty ( xmpNS, xmpProp );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	}	std::string utf8Str;	size_t count = iptc.GetDataSet_UTF8 ( kIPTC_SubjectCode, 0 );		for ( size_t ds = 0; ds < count; ++ds ) {		(void) iptc.GetDataSet_UTF8 ( kIPTC_SubjectCode, &utf8Str, ds );		char * refNumPtr = (char*) utf8Str.c_str();		for ( ; (*refNumPtr != ':') && (*refNumPtr != 0); ++refNumPtr ) {}		if ( *refNumPtr == 0 ) continue;	// This DataSet is ill-formed.		char * refNumEnd = refNumPtr + 1;		for ( ; (*refNumEnd != ':') && (*refNumEnd != 0); ++refNumEnd ) {}		if ( (refNumEnd - refNumPtr) != 8 ) continue;	// This DataSet is ill-formed.		*refNumEnd = 0;	// Ensure a terminating nul for the reference number portion.		xmp->AppendArrayItem ( xmpNS, xmpProp, kXMP_PropArrayIsUnordered, refNumPtr );	}}	// ImportIPTC_SubjectCode// =================================================================================================// ImportIPTC_DateCreated// ======================//// An IPTC (IIM) date is 8 charcters YYYYMMDD. Include the time portion from 2:60 if it is present.// The IPTC time is HHMMSSxHHMM, where 'x' is '+' or '-'. Be tolerant of some ill-formed dates and// times. Apparently some non-Adobe apps put strings like "YYYY-MM-DD" or "HH:MM:SSxHH:MM" in the// IPTC. Allow a missing time zone portion to mean UTC.static void ImportIPTC_DateCreated ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState,									 const char * xmpNS, const char * xmpProp ){	if ( digestState == kDigestDiffers ) {		xmp->DeleteProperty ( xmpNS, xmpProp );	} else {		XMP_Assert ( digestState == kDigestMissing );		if ( xmp->DoesPropertyExist ( xmpNS, xmpProp ) ) return;	}	// First gather the date portion.		IPTC_Manager::DataSetInfo dsInfo;	size_t count = iptc.GetDataSet ( kIPTC_DateCreated, &dsInfo );	if ( count == 0 ) return;		size_t chPos, digits;	XMP_DateTime xmpDate;	memset ( &xmpDate, 0, sizeof(xmpDate) );		for ( chPos = 0, digits = 0; digits < 4; ++digits, ++chPos ) {		if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;		xmpDate.year = (xmpDate.year * 10) + (dsInfo.dataPtr[chPos] - '0');	}		if ( dsInfo.dataPtr[chPos] == '-' ) ++chPos;	for ( digits = 0; digits < 2; ++digits, ++chPos ) {		if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;		xmpDate.month = (xmpDate.month * 10) + (dsInfo.dataPtr[chPos] - '0');	}	if ( xmpDate.month < 1 ) xmpDate.month = 1;	if ( xmpDate.month > 12 ) xmpDate.month = 12;		if ( dsInfo.dataPtr[chPos] == '-' ) ++chPos;	for ( digits = 0; digits < 2; ++digits, ++chPos ) {		if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;		xmpDate.day = (xmpDate.day * 10) + (dsInfo.dataPtr[chPos] - '0');	}	if ( xmpDate.day < 1 ) xmpDate.day = 1;	if ( xmpDate.day > 31 ) xmpDate.day = 28;	// Close enough.		if ( chPos != dsInfo.dataLen ) return;	// The DataSet is ill-formed.	// Now add the time portion if present.		count = iptc.GetDataSet ( kIPTC_TimeCreated, &dsInfo );	if ( count != 0 ) {			for ( chPos = 0, digits = 0; digits < 2; ++digits, ++chPos ) {			if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;			xmpDate.hour = (xmpDate.hour * 10) + (dsInfo.dataPtr[chPos] - '0');		}		if ( xmpDate.hour < 0 ) xmpDate.hour = 0;		if ( xmpDate.hour > 23 ) xmpDate.hour = 23;				if ( dsInfo.dataPtr[chPos] == ':' ) ++chPos;		for ( digits = 0; digits < 2; ++digits, ++chPos ) {			if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;			xmpDate.minute = (xmpDate.minute * 10) + (dsInfo.dataPtr[chPos] - '0');		}		if ( xmpDate.minute < 0 ) xmpDate.minute = 0;		if ( xmpDate.minute > 59 ) xmpDate.minute = 59;				if ( dsInfo.dataPtr[chPos] == ':' ) ++chPos;		for ( digits = 0; digits < 2; ++digits, ++chPos ) {			if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;			xmpDate.second = (xmpDate.second * 10) + (dsInfo.dataPtr[chPos] - '0');		}		if ( xmpDate.second < 0 ) xmpDate.second = 0;		if ( xmpDate.second > 59 ) xmpDate.second = 59;				if ( dsInfo.dataPtr[chPos] == '+' ) {			xmpDate.tzSign = kXMP_TimeEastOfUTC;		} else if ( dsInfo.dataPtr[chPos] == '-' ) {			xmpDate.tzSign = kXMP_TimeWestOfUTC;		} else if ( chPos != dsInfo.dataLen ) {			return;	// The DataSet is ill-formed.		}				++chPos;	// Move past the time zone sign.		for ( chPos = 0, digits = 0; digits < 2; ++digits, ++chPos ) {			if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;			xmpDate.tzHour = (xmpDate.tzHour * 10) + (dsInfo.dataPtr[chPos] - '0');		}		if ( xmpDate.tzHour < 0 ) xmpDate.tzHour = 0;		if ( xmpDate.tzHour > 23 ) xmpDate.tzHour = 23;				if ( dsInfo.dataPtr[chPos] == ':' ) ++chPos;		for ( digits = 0; digits < 2; ++digits, ++chPos ) {			if ( (chPos >= dsInfo.dataLen) || (dsInfo.dataPtr[chPos] < '0') || (dsInfo.dataPtr[chPos] > '9') ) break;			xmpDate.tzMinute = (xmpDate.tzMinute * 10) + (dsInfo.dataPtr[chPos] - '0');		}		if ( xmpDate.tzMinute < 0 ) xmpDate.tzMinute = 0;		if ( xmpDate.tzMinute > 59 ) xmpDate.tzMinute = 59;			if ( chPos != dsInfo.dataLen ) return;	// The DataSet is ill-formed.		}		// Finally, set the XMP property.		xmp->SetProperty_Date ( xmpNS, xmpProp, xmpDate );		}	// ImportIPTC_DateCreated// =================================================================================================// ReconcileUtils::ImportIPTC// ==========================void ReconcileUtils::ImportIPTC ( const IPTC_Manager & iptc, SXMPMeta * xmp, int digestState ){	if ( digestState == kDigestMatches ) return;	for ( size_t i = 0; kKnownDataSets[i].id != 255; ++i ) {		const DataSetCharacteristics & thisDS = kKnownDataSets[i];		try {	// Don't let errors with one stop the others.						switch ( thisDS.mapForm ) {					case kIPTC_MapSimple :					ImportIPTC_Simple ( iptc, xmp, digestState, thisDS.id, thisDS.xmpNS, thisDS.xmpProp );					break;					case kIPTC_MapLangAlt :					ImportIPTC_LangAlt ( iptc, xmp, digestState, thisDS.id, thisDS.xmpNS, thisDS.xmpProp );					break;					case kIPTC_MapArray :					ImportIPTC_Array ( iptc, xmp, digestState, thisDS.id, thisDS.xmpNS, thisDS.xmpProp );					break;					case kIPTC_MapSpecial :					if ( thisDS.id == kIPTC_IntellectualGenre ) {						ImportIPTC_IntellectualGenre ( iptc, xmp, digestState, thisDS.xmpNS, thisDS.xmpProp );					} else if ( thisDS.id == kIPTC_SubjectCode ) {

⌨️ 快捷键说明

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