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

📄 iptc_support.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ============================void IPTC_Writer::SetDataSet_UTF8 ( XMP_Uns8 id, const void* utf8Ptr, XMP_Uns32 utf8Len, long which /* = -1 */ ){	const DataSetCharacteristics* knownDS = FindKnownDataSet ( id );	if ( knownDS == 0 ) XMP_Throw ( "Can only set known IPTC DataSets", kXMPErr_InternalFailure );		// Decide which character encoding to use and get a temporary pointer to the value.		XMP_Uns8 * tempPtr;	XMP_Uns32  dataLen;	std::string localStr, rtStr;		if ( this->utf8Encoding ) {			// We're already using UTF-8.		tempPtr = (XMP_Uns8*) utf8Ptr;		dataLen = utf8Len;		} else {// *** Disable the round trip loss checking for now. We only use UTF-8 if the input had it.			ReconcileUtils::UTF8ToLocal ( utf8Ptr, utf8Len, &localStr );//		ReconcileUtils::LocalToUTF8 ( localStr.data(), localStr.size(), &rtStr );		//		if ( (rtStr.size() == utf8Len) && (memcmp ( rtStr.data(), utf8Ptr, utf8Len ) == 0) ) {			// It round-tripped without loss, keep local encoding.			tempPtr = (XMP_Uns8*) localStr.data();			dataLen = localStr.size();//		} else {//			// Had round-trip loss, change to UTF-8 for all text DataSets.//			this->ConvertToUTF8();//			XMP_Assert ( this->utf8Encoding );//			tempPtr = (XMP_Uns8*) utf8Ptr;//			dataLen = utf8Len;//		}			}		// Set the value for this DataSet, making a non-transient copy of the value. Respect UTF-8 character	// boundaries when truncating. This is easy to check. If the first truncated byte has 10 in the	// high order 2 bits then we are in the middle of a UTF-8 multi-byte character.	// Back up to just before a byte with 11 in the high order 2 bits.	if ( dataLen > knownDS->maxLen ) {		dataLen = knownDS->maxLen;		if ( this->utf8Encoding && ((tempPtr[dataLen] >> 6) == 2) ) {			for ( ; (dataLen > 0) && ((tempPtr[dataLen] >> 6) != 3); --dataLen ) {}		}	}		DataSetMap::iterator dsPos = this->dataSets.find ( id );	long currCount = (long) this->dataSets.count ( id );		bool repeatable = false;			if ( knownDS->mapForm == kIPTC_MapArray ) {		repeatable = true;	} else if ( id == kIPTC_SubjectCode ) {		repeatable = true;	}		if ( ! repeatable ) {		if ( which > 0 ) XMP_Throw ( "Non-repeatable IPTC DataSet", kXMPErr_BadParam );	} else {			if ( which < 0 ) which = currCount;	// The default is to append.		if ( which > currCount ) {			XMP_Throw ( "Invalid index for IPTC DataSet", kXMPErr_BadParam );		} else if ( which == currCount ) {			dsPos = this->dataSets.end();	// To make later checks do the right thing.		} else {			dsPos = this->dataSets.lower_bound ( id );			for ( ; which > 0; --which ) ++dsPos;		}		}	if ( dsPos != this->dataSets.end() ) {		if ( (dsPos->second.dataLen == dataLen) && (memcmp ( dsPos->second.dataPtr, tempPtr, dataLen ) == 0) ) {			return;	// ! New value matches the old, don't update.		}	}		XMP_Uns8 * dataPtr = (XMP_Uns8*) malloc ( dataLen );	if ( dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );	memcpy ( dataPtr, tempPtr, dataLen );	// AUDIT: Safe, malloc'ed dataLen bytes above.		DataSetInfo dsInfo ( id, dataLen, dataPtr );	if ( dsPos != this->dataSets.end() ) {		this->DisposeLooseValue ( dsPos->second );		dsPos->second = dsInfo;	} else {		DataSetMap::value_type mapValue ( id, dsInfo );		(void) this->dataSets.insert ( this->dataSets.upper_bound ( id ), mapValue );	}		this->changed = true;}	// IPTC_Writer::SetDataSet_UTF8// =================================================================================================// IPTC_Writer::DeleteDataSet// ==========================void IPTC_Writer::DeleteDataSet ( XMP_Uns8 id, long which /* = -1 */ ){	DataSetMap::iterator dsBegin = this->dataSets.lower_bound ( id );	// Set for which == -1.	DataSetMap::iterator dsEnd   = this->dataSets.upper_bound ( id );		if ( dsBegin == dsEnd ) return;	// Nothing to delete.	if ( which >= 0 ) {		long currCount = (long) this->dataSets.count ( id );		if ( which >= currCount ) return;	// Nothing to delete.		for ( ; which > 0; --which ) ++dsBegin;		dsEnd = dsBegin; ++dsEnd;	// ! Can't do "dsEnd = dsBegin+1"!	}	for ( DataSetMap::iterator dsPos = dsBegin; dsPos != dsEnd; ++dsPos ) {		this->DisposeLooseValue ( dsPos->second );	}	this->dataSets.erase ( dsBegin, dsEnd );	this->changed = true;}	// IPTC_Writer::DeleteDataSet// =================================================================================================// IPTC_Writer::UpdateMemoryDataSets// =================================//// Reconstruct the entire IIM block. Start with DataSet 1:0 and 1:90 if UTF-8 encoding is used,// then 2:0, then 2:xx DataSets that have values. This does not include any alignment padding, that// is an artifact of some specific wrappers such as Photoshop image resources.XMP_Uns32 IPTC_Writer::UpdateMemoryDataSets ( void** dataPtr ){	if ( ! this->changed ) {		if ( dataPtr != 0 ) *dataPtr = this->iptcContent;		return this->iptcLength;	}	DataSetMap::iterator dsPos;	DataSetMap::iterator dsEnd = this->dataSets.end();	//	if ( this->utf8Encoding ) {		*** Disable round trip loss checking for now. ***//		if ( ! this->CheckRoundTripLoss() ) this->ConvertToLocal();//	}		// Compute the length of the new IIM block, including space for records other than 2. All other	// records are preserved as-is, including 1:90. If we ever start changing the encoding, we will	// have to remove any existing 1:90 and insert a new one.	XMP_Uns32 newLength = (5+2);	// For 2:0.	newLength += (this->iptcLength - rec2Length);	// For records other than 2.		for ( dsPos = this->dataSets.begin(); dsPos != dsEnd; ++dsPos ) {		XMP_Uns32 dsLen = dsPos->second.dataLen;		newLength += (5 + dsLen);		if ( dsLen > 0x7FFF ) newLength += 4;	// We always use a 4 byte extended length.	}		// Allocate the new IIM block.		XMP_Uns8* newContent = (XMP_Uns8*) malloc ( newLength );	if ( newContent == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );		XMP_Uns8* dsPtr = newContent;		XMP_Uns32 prefixLength = this->rec2Offset;	XMP_Uns32 suffixOffset = this->rec2Offset + this->rec2Length;	XMP_Uns32 suffixLength = this->iptcLength - suffixOffset;		if ( prefixLength > 0 ) {	// Write the records before 2.		memcpy ( dsPtr, this->iptcContent, prefixLength );	// AUDIT: Within range of allocation.		dsPtr += prefixLength;	}		if ( ! this->utf8Encoding ) {		// Start with 2:00 for version 2.		// *** We should probably write version 4 all the time. This is a late CS3 change, don't want		// *** to risk breaking other apps that might be strict about version checking.		memcpy ( dsPtr, "\x1C\x02\x00\x00\x02\x00\x02", (5+2) );	// AUDIT: Within range of allocation.		dsPtr += (5+2);	} else {		// Start with 2:00 for version 4.		memcpy ( dsPtr, "\x1C\x02\x00\x00\x02\x00\x04", (5+2) );	// AUDIT: Within range of allocation.		dsPtr += (5+2);	}		// Fill in the record 2 DataSets that have values.		for ( dsPos = this->dataSets.begin(); dsPos != dsEnd; ++dsPos ) {			DataSetInfo & dsInfo = dsPos->second;			dsPtr[0] = 0x1C;		dsPtr[1] = 2;		dsPtr[2] = dsInfo.id;		dsPtr += 3;				XMP_Uns32 dsLen = dsInfo.dataLen;		if ( dsLen <= 0x7FFF ) {			PutUns16BE ( (XMP_Uns16)dsLen, dsPtr );			dsPtr += 2;		} else {			PutUns16BE ( 0x8004, dsPtr );			PutUns32BE ( dsLen, dsPtr+2 );			dsPtr += 6;		}				if ( dsLen > (newLength - (dsPtr - newContent)) ) {			XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure );		}		memcpy ( dsPtr, dsInfo.dataPtr, dsLen );	// AUDIT: Protected by above check.		dsPtr += dsLen;	}		if ( suffixLength > 0 ) {	// Write the records after 2.		memcpy ( dsPtr, (this->iptcContent + suffixOffset), suffixLength );	// AUDIT: Within range of allocation.		dsPtr += suffixLength;	}		XMP_Assert ( dsPtr == (newContent + newLength) );		// Parse the new block, it is the best way to reset internal info and rebuild the map. 		this->ParseMemoryDataSets ( newContent, newLength, false );	// Don't make another copy of the content.	XMP_Assert ( this->iptcLength == newLength );	this->ownedContent = true;	// We really do own the new content.		// Done.	if ( dataPtr != 0 ) *dataPtr = this->iptcContent;	return this->iptcLength;	}	// IPTC_Writer::UpdateMemoryDataSets#if 0	// *** Disable the round trip loss checking for now.// =================================================================================================// IPTC_Writer::ConvertToUTF8// ==========================//// Convert the values of existing text DataSets to UTF-8. For now we only accept text DataSets.void IPTC_Writer::ConvertToUTF8(){	XMP_Assert ( ! this->utf8Encoding );	std::string utf8Str;	DataSetMap::iterator dsPos = this->dataSets.begin();	DataSetMap::iterator dsEnd = this->dataSets.end();		for ( ; dsPos != dsEnd; ++dsPos ) {		DataSetInfo & dsInfo = dsPos->second;		ReconcileUtils::LocalToUTF8 ( dsInfo.dataPtr, dsInfo.dataLen, &utf8Str );		this->DisposeLooseValue ( dsInfo );		dsInfo.dataLen = utf8Str.size();		dsInfo.dataPtr = (XMP_Uns8*) malloc ( dsInfo.dataLen );		if ( dsInfo.dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );		memcpy ( dsInfo.dataPtr, utf8Str.data(), dsInfo.dataLen );	// AUDIT: Safe, malloc'ed dataLen bytes above.	}		this->utf8Encoding = true;}	// IPTC_Writer::ConvertToUTF8// =================================================================================================// IPTC_Writer::ConvertToLocal// ===========================//// Convert the values of existing text DataSets to local. For now we only accept text DataSets.void IPTC_Writer::ConvertToLocal(){	XMP_Assert ( this->utf8Encoding );	std::string localStr;	DataSetMap::iterator dsPos = this->dataSets.begin();	DataSetMap::iterator dsEnd = this->dataSets.end();		for ( ; dsPos != dsEnd; ++dsPos ) {		DataSetInfo & dsInfo = dsPos->second;		ReconcileUtils::UTF8ToLocal ( dsInfo.dataPtr, dsInfo.dataLen, &localStr );		this->DisposeLooseValue ( dsInfo );		dsInfo.dataLen = localStr.size();		dsInfo.dataPtr = (XMP_Uns8*) malloc ( dsInfo.dataLen );		if ( dsInfo.dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );		memcpy ( dsInfo.dataPtr, localStr.data(), dsInfo.dataLen );	// AUDIT: Safe, malloc'ed dataLen bytes above.	}		this->utf8Encoding = false;}	// IPTC_Writer::ConvertToLocal// =================================================================================================// IPTC_Writer::CheckRoundTripLoss// ===============================//// See if we still need UTF-8 because of round-trip loss. Returns true if there is loss.bool IPTC_Writer::CheckRoundTripLoss(){	XMP_Assert ( this->utf8Encoding );	std::string localStr, rtStr;	DataSetMap::iterator dsPos = this->dataSets.begin();	DataSetMap::iterator dsEnd = this->dataSets.end();		for ( ; dsPos != dsEnd; ++dsPos ) {		DataSetInfo & dsInfo = dsPos->second;		XMP_StringPtr utf8Ptr = (XMP_StringPtr) dsInfo.dataPtr;		XMP_StringLen utf8Len = dsInfo.dataLen;		ReconcileUtils::UTF8ToLocal ( utf8Ptr, utf8Len, &localStr );		ReconcileUtils::LocalToUTF8 ( localStr.data(), localStr.size(), &rtStr );		if ( (rtStr.size() != utf8Len) || (memcmp ( rtStr.data(), utf8Ptr, utf8Len ) != 0) ) {			return true; // Had round-trip loss, keep UTF-8.		}	}		return false;	// No loss.}	// IPTC_Writer::CheckRoundTripLoss#endif

⌨️ 快捷键说明

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