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

📄 tiff_filewriter.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	// Allocate the new block of memory for the full stream. Copy the original stream. Write the	// modified IFDs and values. Finally rebuild the internal IFD info and tag map.		XMP_Uns32 newLength = appendedOrigin + appendedLength;	XMP_Uns8* newStream = (XMP_Uns8*) malloc ( newLength + extraSpace );	if ( newStream == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );	memcpy ( newStream, this->memStream, this->tiffLength );	// AUDIT: Safe, malloc'ed newLength bytes above.	if ( this->tiffLength < appendedOrigin ) {		XMP_Assert ( appendedOrigin == (this->tiffLength + 1) );		newStream[this->tiffLength] = 0;	// Clear the pad byte.	}		try {	// We might get exceptions from the next part and must delete newStream on the way out.			// Write the modified IFDs and values. Rewrite the full IFD from scratch to make sure the		// tags are now unique and sorted. Copy large changed values to their appropriate location.				XMP_Uns32 appendedOffset = appendedOrigin;				for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {					InternalIFDInfo& ifdInfo ( this->containedIFDs[ifd] );			size_t tagCount = ifdInfo.tagMap.size();			if ( ! (appendAll | ifdInfo.changed) ) continue;			if ( tagCount == 0 ) continue;			XMP_Uns8* ifdPtr = newStream + newIFDOffsets[ifd];						if ( appendedIFDs[ifd] ) {				XMP_Assert ( newIFDOffsets[ifd] == appendedOffset );				appendedOffset += 6 + (12 * tagCount);			}						this->PutUns16 ( (XMP_Uns16)tagCount, ifdPtr );			ifdPtr += 2;			InternalTagMap::iterator tagPos = ifdInfo.tagMap.begin();			InternalTagMap::iterator tagEnd = ifdInfo.tagMap.end();			for ( ; tagPos != tagEnd; ++tagPos ) {				InternalTagInfo & currTag ( tagPos->second );				this->PutUns16 ( currTag.id, ifdPtr );				ifdPtr += 2;				this->PutUns16 ( currTag.type, ifdPtr );				ifdPtr += 2;				this->PutUns32 ( currTag.count, ifdPtr );				ifdPtr += 4;				*((XMP_Uns32*)ifdPtr) = currTag.dataOrOffset;				if ( (appendAll | currTag.changed) && (currTag.dataLen > 4) ) {					XMP_Uns32 valueOffset = this->GetUns32 ( &currTag.dataOrOffset );					if ( (currTag.dataLen <= currTag.origLen) && (! appendAll) ) {						XMP_Assert ( valueOffset == currTag.origOffset );					} else {						XMP_Assert ( valueOffset == appendedOffset );						appendedOffset += ((currTag.dataLen + 1) & 0xFFFFFFFEUL);					}					if ( currTag.dataLen > (newLength - valueOffset) ) XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure );					memcpy ( (newStream + valueOffset), currTag.dataPtr, currTag.dataLen );	// AUDIT: Protected by the above check.					if ( (currTag.dataLen & 1) != 0 ) newStream[valueOffset+currTag.dataLen] = 0;				}				ifdPtr += 4;			}						this->PutUns32 ( ifdInfo.origNextIFD, ifdPtr );			ifdPtr += 4;				}				XMP_Assert ( appendedOffset == newLength );				// Back fill the offsets for the primary and thumnbail IFDs, if they are now appended.				if ( appendedIFDs[kTIFF_PrimaryIFD] ) {			this->PutUns32 ( newIFDOffsets[kTIFF_PrimaryIFD], (newStream + 4) );		}				if ( appendedIFDs[kTIFF_TNailIFD] ) {			size_t primaryIFDCount = this->containedIFDs[kTIFF_PrimaryIFD].tagMap.size();			XMP_Uns32 tnailRefOffset = newIFDOffsets[kTIFF_PrimaryIFD] + 2 + (12 * primaryIFDCount);			this->PutUns32 ( newIFDOffsets[kTIFF_TNailIFD], (newStream + tnailRefOffset) );		}		} catch ( ... ) {			free ( newStream );		throw;		}		*newStream_out = newStream;	*newLength_out = newLength;	}	// TIFF_FileWriter::UpdateMemByAppend// =================================================================================================// TIFF_FileWriter::DetermineVisibleLength// =======================================XMP_Uns32 TIFF_FileWriter::DetermineVisibleLength(){	XMP_Uns32 visibleLength = 8;	// Start with the TIFF header size.	for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {			InternalIFDInfo& ifdInfo ( this->containedIFDs[ifd] );		size_t tagCount = ifdInfo.tagMap.size();		if ( tagCount == 0 ) continue;		visibleLength += 6 + (12 * tagCount);		InternalTagMap::iterator tagPos = ifdInfo.tagMap.begin();		InternalTagMap::iterator tagEnd = ifdInfo.tagMap.end();		for ( ; tagPos != tagEnd; ++tagPos ) {			InternalTagInfo & currTag ( tagPos->second );			if ( currTag.dataLen > 4 ) visibleLength += ((currTag.dataLen + 1) & 0xFFFFFFFE);	// ! Round to even lengths.		}		}		return visibleLength;	}	// TIFF_FileWriter::DetermineVisibleLength// =================================================================================================// TIFF_FileWriter::UpdateMemByRewrite// ===================================//// Normally we update TIFF in a conservative "by-append" manner. Changes are written in-place where// they fit, anything requiring growth is appended to the end and the old space is abandoned. The// end for memory-based TIFF is the end of the data block, the end for file-based TIFF is the end of// the file. This update-by-append model has the advantage of not perturbing any hidden offsets, a// common feature of proprietary MakerNotes.//// The condenseStream parameter can be used to rewrite the full stream instead of appending. This// will discard any MakerNote tag and risks breaking offsets that are hidden. This can be necessary// though to try to make the TIFF fit in a JPEG file.//// We don't do most of the actual rewrite here. We set things up so that UpdateMemByAppend can be// called to append onto a bare TIFF header. Additional hidden offsets are then handled here.//// These tags are recognized as being hidden offsets when composing a condensed stream://    273 - StripOffsets, lengths in tag 279//    288 - FreeOffsets, lengths in tag 289//    324 - TileOffsets, lengths in tag 325//    330 - SubIFDs, lengths within the IFDs (Plus subIFD values and possible chaining!)//    513 - JPEGInterchangeFormat, length in tag 514//    519 - JPEGQTables, each table is 64 bytes//    520 - JPEGDCTables, lengths ???//    521 - JPEGACTables, lengths ???// Some of these will handled and kept, some will be thrown out, some will cause the rewrite to fail.//// The hidden offsets for the Exif, GPS, and Interoperability IFDs (tags 34665, 34853, and 40965)// are handled by the code in DetermineAppendInfo, which is called from UpdateMemByAppend, which is// called from here.// ! So far, a memory-based TIFF rewrite would only be done for the Exif portion of a JPEG file.// ! In which case we're probably OK to handle JPEGInterchangeFormat (used for compressed thumbnails)// ! and complain about any of the other hidden offset tags.// tag	count	type// 273		n	short or long// 279		n	short or long// 288		n	long// 289		n	long// 324		n	long// 325		n	short or long// 330		n	long// 513		1	long// 514		1	long// 519		n	long// 520		n	long// 521		n	longstatic XMP_Uns16 kNoGoTags[] =	{		kTIFF_StripOffsets,		// 273	*** Should be handled?		kTIFF_StripByteCounts,	// 279	*** Should be handled?		kTIFF_FreeOffsets,		// 288	*** Should be handled?		kTIFF_FreeByteCounts,	// 289	*** Should be handled?		kTIFF_TileOffsets,		// 324	*** Should be handled?		kTIFF_TileByteCounts,	// 325	*** Should be handled?		kTIFF_SubIFDs,			// 330	*** Should be handled?		kTIFF_JPEGQTables,		// 519		kTIFF_JPEGDCTables,		// 520		kTIFF_JPEGACTables,		// 521		0xFFFF	// Must be last as a sentinel.	};static XMP_Uns16 kBanishedTags[] =	{		kTIFF_MakerNote,	// *** Should someday support MakerNoteSafety.		0xFFFF	// Must be last as a sentinel.	};struct SimpleHiddenContentInfo {	XMP_Uns8  ifd;	XMP_Uns16 offsetTag, lengthTag;};struct SimpleHiddenContentLocations {	XMP_Uns32 length, oldOffset, newOffset;	SimpleHiddenContentLocations() : length(0), oldOffset(0), newOffset(0) {};};enum { kSimpleHiddenContentCount = 1 };static const SimpleHiddenContentInfo kSimpleHiddenContentInfo [kSimpleHiddenContentCount] =	{		{ kTIFF_TNailIFD, kTIFF_JPEGInterchangeFormat, kTIFF_JPEGInterchangeFormatLength }	};// -------------------------------------------------------------------------------------------------void TIFF_FileWriter::UpdateMemByRewrite ( XMP_Uns8** newStream_out, XMP_Uns32* newLength_out ) {	const InternalTagInfo* tagInfo;		// Check for tags that we don't tolerate because they have data we can't (or refuse to) find.		for ( XMP_Uns8 ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {		for ( int i = 0; kNoGoTags[i] != 0xFFFF; ++i ) {			tagInfo = this->FindTagInIFD ( ifd, kNoGoTags[i] );			if ( tagInfo != 0 ) XMP_Throw ( "Tag not tolerated for TIFF rewrite", kXMPErr_Unimplemented );		}	}		// Delete unwanted tags. 		for ( XMP_Uns8 ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {		for ( int i = 0; kBanishedTags[i] != 0xFFFF; ++i ) {			this->DeleteTag ( ifd, kBanishedTags[i] );		}	}		// Make sure the "pointer" tags for the Exif, GPS, and Interop IFDs exist. The order is	// important, adding the Interop pointer can cause the Exif IFD to exist.		if ( ! this->containedIFDs[kTIFF_InteropIFD].tagMap.empty() ) {		this->SetTag_Long ( kTIFF_ExifIFD, kTIFF_InteroperabilityIFDPointer, 0xABADABAD );	}		if ( ! this->containedIFDs[kTIFF_GPSInfoIFD].tagMap.empty() ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_GPSInfoIFDPointer, 0xABADABAD );	}		if ( ! this->containedIFDs[kTIFF_ExifIFD].tagMap.empty() ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer, 0xABADABAD );	}	// Determine the offsets and additional size for the hidden offset content. Set the offset tags	// to the new offset.		XMP_Uns32 hiddenContentLength = 0;	XMP_Uns32 hiddenContentOrigin = this->DetermineVisibleLength();		SimpleHiddenContentLocations hiddenLocations [kSimpleHiddenContentCount];		for ( int i = 0; i < kSimpleHiddenContentCount; ++i ) {		const SimpleHiddenContentInfo & hiddenInfo ( kSimpleHiddenContentInfo[i] );				bool haveLength = this->GetTag_Integer ( hiddenInfo.ifd, hiddenInfo.lengthTag, &hiddenLocations[i].length );		bool haveOffset = this->GetTag_Integer ( hiddenInfo.ifd, hiddenInfo.offsetTag, &hiddenLocations[i].oldOffset );		if ( haveLength != haveOffset ) XMP_Throw ( "Unpaired simple hidden content tag", kXMPErr_BadTIFF );		if ( (! haveLength) || (hiddenLocations[i].length == 0) ) continue;		hiddenLocations[i].newOffset = hiddenContentOrigin + hiddenContentLength;		this->SetTag_Long ( hiddenInfo.ifd, hiddenInfo.offsetTag, hiddenLocations[i].newOffset );		hiddenContentLength += ((hiddenLocations[i].length + 1) & 0xFFFFFFFE);	// ! Round up for even offsets.	}		// Save any old memory stream for the content behind hidden offsets. Setup a bare TIFF header.	XMP_Uns8* oldStream = this->memStream;	XMP_Uns8 bareTIFF [8];	if ( this->bigEndian ) {		bareTIFF[0] = 0x4D; bareTIFF[1] = 0x4D; bareTIFF[2] = 0x00; bareTIFF[3] = 0x2A;	} else {		bareTIFF[0] = 0x49; bareTIFF[1] = 0x49; bareTIFF[2] = 0x2A; bareTIFF[3] = 0x00;	}	*((XMP_Uns32*)&bareTIFF[4]) = 0;		this->memStream = &bareTIFF[0];	this->tiffLength = sizeof ( bareTIFF );	this->ownedStream = false;	// Call UpdateMemByAppend to write the new stream, telling it to append everything.		this->UpdateMemByAppend ( newStream_out, newLength_out, true, hiddenContentLength );	// Copy the hidden content and update the output stream length;	XMP_Assert ( *newLength_out == hiddenContentOrigin );	*newLength_out += hiddenContentLength;		for ( int i = 0; i < kSimpleHiddenContentCount; ++i ) {		if ( hiddenLocations[i].length == 0 ) continue;		XMP_Uns8* srcPtr  = oldStream + hiddenLocations[i].oldOffset;		XMP_Uns8* destPtr = *newStream_out + hiddenLocations[i].newOffset;		memcpy ( destPtr, srcPtr, hiddenLocations[i].length );	// AUDIT: Safe copy, not user data, computed length.	}		}	// TIFF_FileWriter::UpdateMemByRewrite// =================================================================================================// TIFF_FileWriter::UpdateMemoryStream// ===================================//// Normally we update TIFF in a conservative "by-append" manner. Changes are written in-place where// they fit, anything requiring growth is appended to the end and the old space is abandoned. The// end for memory-based TIFF is the end of the data block, the end for file-based TIFF is

⌨️ 快捷键说明

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