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

📄 tiff_filewriter.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 5 页
字号:
static XMP_Uns8* CaptureJPEGTNail ( LFA_FileRef fileRef, IOBuffer* ioBuf, const TIFF_Manager& tiff ){	bool ok;	XMP_Uns8* jpegPtr = 0;	XMP_Uns32 jpegOffset, jpegLen;		ok = tiff.GetTag_Integer ( kTIFF_TNailIFD, kTIFF_JPEGInterchangeFormat, &jpegOffset );	if ( ok ) ok = tiff.GetTag_Integer ( kTIFF_TNailIFD, kTIFF_JPEGInterchangeFormatLength, &jpegLen );	if ( ! ok ) return 0;	if ( jpegLen > 1024*1024 ) return 0;	// ? XMP_Throw ( "Outrageous JPEG TNail length", kXMPErr_BadTIFF );	jpegPtr = (XMP_Uns8*) malloc ( jpegLen );	if ( jpegPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );		try {			if ( jpegLen > kIOBufferSize ) {			// This value is bigger than the I/O buffer, read it directly and restore the file position.			LFA_Seek ( fileRef, jpegOffset, SEEK_SET );			LFA_Read ( fileRef, jpegPtr, jpegLen, kLFA_RequireAll );			LFA_Seek ( fileRef, (ioBuf->filePos + ioBuf->len), SEEK_SET );		} else {			// This value can fit in the I/O buffer, so use that.			MoveToOffset ( fileRef, jpegOffset, ioBuf );			ok = CheckFileSpace ( fileRef, ioBuf, jpegLen );			if ( ! ok ) XMP_Throw ( "EOF in data block", kXMPErr_BadTIFF );			memcpy ( jpegPtr, ioBuf->ptr, jpegLen );	// AUDIT: Safe, malloc'ed jpegLen bytes above.		}		} catch ( ... ) {			free ( jpegPtr );		throw;		}		return jpegPtr;}	// CaptureJPEGTNail// =================================================================================================// TIFF_FileWriter::ParseFileStream// ================================//// The buffered I/O model is worth the logic complexity - as opposed to a simple seek/read for each// part of the TIFF stream. The vast majority of real-world TIFFs have the primary IFD, Exif IFD,// and all of their interesting tag values within the first 64K of the file. Well, at least before// we get around to our edit-by-append approach.void TIFF_FileWriter::ParseFileStream ( LFA_FileRef fileRef ) {	bool ok;	IOBuffer  ioBuf;	this->DeleteExistingInfo();	this->fileParsed = true;	this->tiffLength = (XMP_Uns32) LFA_Measure ( fileRef );	if ( this->tiffLength == 0 ) return;		// Find and process the primary, Exif, GPS, and Interoperability IFDs.		ioBuf.filePos = LFA_Seek ( fileRef, 0, SEEK_SET );	ok = CheckFileSpace ( fileRef, &ioBuf, 8 );	if ( ! ok ) XMP_Throw ( "TIFF too small", kXMPErr_BadTIFF );			XMP_Uns32 primaryIFDOffset = this->CheckTIFFHeader ( ioBuf.ptr, this->tiffLength );	XMP_Uns32 tnailIFDOffset   = 0;		if ( primaryIFDOffset != 0 ) tnailIFDOffset = this->ProcessFileIFD ( kTIFF_PrimaryIFD, primaryIFDOffset, fileRef, &ioBuf );	const InternalTagInfo* exifIFDTag = this->FindTagInIFD ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer );	if ( (exifIFDTag != 0) && (exifIFDTag->type == kTIFF_LongType) && (exifIFDTag->count == 1) ) {		XMP_Uns32 exifOffset = this->GetUns32 ( &exifIFDTag->dataOrOffset );		(void) this->ProcessFileIFD ( kTIFF_ExifIFD, exifOffset, fileRef, &ioBuf );	}	const InternalTagInfo* gpsIFDTag = this->FindTagInIFD ( kTIFF_PrimaryIFD, kTIFF_GPSInfoIFDPointer );	if ( (gpsIFDTag != 0) && (gpsIFDTag->type == kTIFF_LongType) && (gpsIFDTag->count == 1) ) {		XMP_Uns32 gpsOffset = this->GetUns32 ( &gpsIFDTag->dataOrOffset );		(void) this->ProcessFileIFD ( kTIFF_GPSInfoIFD, gpsOffset, fileRef, &ioBuf );	}	const InternalTagInfo* interopIFDTag = this->FindTagInIFD ( kTIFF_ExifIFD, kTIFF_InteroperabilityIFDPointer );	if ( (interopIFDTag != 0) && (interopIFDTag->type == kTIFF_LongType) && (interopIFDTag->dataLen == 4) ) {		XMP_Uns32 interopOffset = this->GetUns32 ( &interopIFDTag->dataOrOffset );		(void) this->ProcessFileIFD ( kTIFF_InteropIFD, interopOffset, fileRef, &ioBuf );	}		// Process the thumbnail IFD. We only do this for Exif-compliant TIFF streams. Do this after	// the others since they are often within the first 64K of the file and the thumbnail is not.	if ( (tnailIFDOffset != 0) && (! this->containedIFDs[kTIFF_ExifIFD].tagMap.empty()) ) {		(void) this->ProcessFileIFD ( kTIFF_TNailIFD, tnailIFDOffset, fileRef, &ioBuf );		this->jpegTNailPtr = CaptureJPEGTNail ( fileRef, &ioBuf, *this );	}		#if 0	{		printf ( "\nExiting TIFF_FileWriter::ParseFileStream\n" );		for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {			InternalIFDInfo & thisIFD = this->containedIFDs[ifd];			printf ( "\n   IFD %d, count %d, mapped %d, offset %d (0x%X), next IFD %d (0x%X)\n",					 ifd, thisIFD.origCount, thisIFD.tagMap.size(),					 thisIFD.origOffset, thisIFD.origOffset, thisIFD.origNextIFD, thisIFD.origNextIFD );			InternalTagMap::iterator tagPos;			InternalTagMap::iterator tagEnd = thisIFD.tagMap.end();			for ( tagPos = thisIFD.tagMap.begin(); tagPos != tagEnd; ++tagPos ) {				InternalTagInfo & thisTag = tagPos->second;				printf ( "      Tag %d, dataOrOffset 0x%X, origLen %d, origOffset %d (0x%X)\n",						 thisTag.id, thisTag.dataOrOffset, thisTag.origLen, thisTag.origOffset, thisTag.origOffset );			}		}		printf ( "\n" );	}	#endif}	// TIFF_FileWriter::ParseFileStream// =================================================================================================// TIFF_FileWriter::ProcessFileIFD// ===============================XMP_Uns32 TIFF_FileWriter::ProcessFileIFD ( XMP_Uns8 ifd, XMP_Uns32 ifdOffset, LFA_FileRef fileRef, IOBuffer* ioBuf ) {	InternalIFDInfo& ifdInfo ( this->containedIFDs[ifd] );		MoveToOffset ( fileRef, ifdOffset, ioBuf );	// Move to the start of the IFD.		bool ok = CheckFileSpace ( fileRef, ioBuf, 2 );	if ( ! ok ) XMP_Throw ( "IFD count missing", kXMPErr_BadTIFF );	XMP_Uns16 tagCount = this->GetUns16 ( ioBuf->ptr );	if ( tagCount >= 0x8000 ) XMP_Throw ( "Outrageous IFD count", kXMPErr_BadTIFF );	if ( (ifdOffset + 2 + tagCount*12 + 4) > this->tiffLength ) XMP_Throw ( "Out of bounds IFD", kXMPErr_BadTIFF );		ifdInfo.origOffset = ifdOffset;	ifdInfo.origCount  = tagCount;		// ---------------------------------------------------------------------------------------------	// First create all of the IFD map entries, capturing short values, and get the next IFD offset.	// We're using a std::map for storage, it automatically eliminates duplicates and provides	// sorted output. Plus the "map[key] = value" assignment conveniently keeps the last encountered	// value, following Photoshop's behavior.	ioBuf->ptr += 2;	// Move to the first IFD entry.		for ( XMP_Uns16 i = 0; i < tagCount; ++i, ioBuf->ptr += 12 ) {			if ( ! CheckFileSpace ( fileRef, ioBuf, 12 ) ) XMP_Throw ( "EOF within IFD", kXMPErr_BadTIFF );				RawIFDEntry*    rawTag = (RawIFDEntry*)ioBuf->ptr;		InternalTagInfo mapTag ( this->GetUns16(&rawTag->id), this->GetUns16(&rawTag->type), this->GetUns32(&rawTag->count) );		if ( (mapTag.type < kTIFF_ByteType) || (mapTag.type > kTIFF_LastType) ) continue;	// Bad type, skip this tag.		mapTag.dataLen = mapTag.origLen = mapTag.count * kTIFF_TypeSizes[mapTag.type];		mapTag.dataOrOffset = rawTag->dataOrOffset;	// Keep the value or offset in stream byte ordering.		if ( mapTag.dataLen <= 4 ) {			mapTag.dataPtr = (XMP_Uns8*) &mapTag.dataOrOffset;			mapTag.origOffset = ifdOffset + 2 + (12 * i);	// Compute the data offset.		} else {			mapTag.origOffset = this->GetUns32 ( &rawTag->dataOrOffset );	// Extract the data offset.		}		ifdInfo.tagMap[mapTag.id] = mapTag;		}		if ( ! CheckFileSpace ( fileRef, ioBuf, 4 ) ) XMP_Throw ( "EOF at next IFD offset", kXMPErr_BadTIFF );	ifdInfo.origNextIFD = this->GetUns32 ( ioBuf->ptr );		// ---------------------------------------------------------------------------------------------	// Go back over the tag map and extract the data for large recognized tags. This is done in 2	// passes, in order to lessen the typical amount of I/O. On the first pass make sure we have at	// least 32K of data following the IFD in the buffer, and extract all of the values in that	// portion. This should cover an original file, or the appended values with an appended IFD.		if ( (ioBuf->limit - ioBuf->ptr) < 32*1024 ) RefillBuffer ( fileRef, ioBuf );		InternalTagMap::iterator tagPos = ifdInfo.tagMap.begin();	InternalTagMap::iterator tagEnd = ifdInfo.tagMap.end();		const XMP_Uns16* knownTagPtr = sKnownTags[ifd];	// Points into the ordered recognized tag list.		XMP_Uns32 bufBegin = (XMP_Uns32)ioBuf->filePos;	// TIFF stream bounds for the current buffer.	XMP_Uns32 bufEnd   = bufBegin + ioBuf->len;		for ( ; tagPos != tagEnd; ++tagPos ) {			InternalTagInfo* currTag = &tagPos->second;		if ( currTag->dataLen <= 4 ) continue;	// Short values are already in the dataOrOffset field.		while ( *knownTagPtr < currTag->id ) ++knownTagPtr;		if ( *knownTagPtr != currTag->id ) continue;	// Skip unrecognized tags.		if ( currTag->dataLen > 1024*1024 ) XMP_Throw ( "Outrageous data length", kXMPErr_BadTIFF );				if ( (bufBegin <= currTag->origOffset) && ((currTag->origOffset + currTag->dataLen) <= bufEnd) ) {			// This value is already fully within the current I/O buffer, copy it.			MoveToOffset ( fileRef, currTag->origOffset, ioBuf );			currTag->dataPtr = (XMP_Uns8*) malloc ( currTag->dataLen );			if ( currTag->dataPtr == 0 ) XMP_Throw ( "No data block", kXMPErr_NoMemory );			memcpy ( currTag->dataPtr, ioBuf->ptr, currTag->dataLen );	// AUDIT: Safe, malloc'ed currTag->dataLen bytes above.		}		}		// ---------------------------------------------------------------------------------------------	// Now the second large value pass. This will reposition the I/O buffer as necessary. Hopefully	// just once, to pick up the span of data not covered in the first pass.		tagPos = ifdInfo.tagMap.begin();	// Reset both map/array positions.	knownTagPtr = sKnownTags[ifd];		for ( ; tagPos != tagEnd; ++tagPos ) {			InternalTagInfo* currTag = &tagPos->second;		if ( (currTag->dataLen <= 4) || (currTag->dataPtr != 0) ) continue;	// Done this tag?		while ( *knownTagPtr < currTag->id ) ++knownTagPtr;		if ( *knownTagPtr != currTag->id ) continue;	// Skip unrecognized tags.		if ( currTag->dataLen > 1024*1024 ) XMP_Throw ( "Outrageous data length", kXMPErr_BadTIFF );		currTag->dataPtr = (XMP_Uns8*) malloc ( currTag->dataLen );		if ( currTag->dataPtr == 0 ) XMP_Throw ( "No data block", kXMPErr_NoMemory );				if ( currTag->dataLen > kIOBufferSize ) {			// This value is bigger than the I/O buffer, read it directly and restore the file position.			LFA_Seek ( fileRef, currTag->origOffset, SEEK_SET );			LFA_Read ( fileRef, currTag->dataPtr, currTag->dataLen, kLFA_RequireAll );			LFA_Seek ( fileRef, (ioBuf->filePos + ioBuf->len), SEEK_SET );		} else {			// This value can fit in the I/O buffer, so use that.			MoveToOffset ( fileRef, currTag->origOffset, ioBuf );			ok = CheckFileSpace ( fileRef, ioBuf, currTag->dataLen );			if ( ! ok ) XMP_Throw ( "EOF in data block", kXMPErr_BadTIFF );			memcpy ( currTag->dataPtr, ioBuf->ptr, currTag->dataLen );	// AUDIT: Safe, malloc'ed currTag->dataLen bytes above.		}			}		// Done, return the next IFD offset.		return ifdInfo.origNextIFD;}	// TIFF_FileWriter::ProcessFileIFD// =================================================================================================// TIFF_FileWriter::IntegrateFromPShop6// ====================================//// See comments for ProcessPShop6IFD.void TIFF_FileWriter::IntegrateFromPShop6 ( const void * buriedPtr, size_t buriedLen ) {	TIFF_MemoryReader buriedExif;	buriedExif.ParseMemoryStream ( buriedPtr, buriedLen );		this->ProcessPShop6IFD ( buriedExif, kTIFF_PrimaryIFD );	this->ProcessPShop6IFD ( buriedExif, kTIFF_TNailIFD );	this->ProcessPShop6IFD ( buriedExif, kTIFF_ExifIFD );	this->ProcessPShop6IFD ( buriedExif, kTIFF_GPSInfoIFD );}	// TIFF_FileWriter::IntegrateFromPShop6// =================================================================================================// TIFF_FileWriter::CopyTagToMasterIFD// ===================================//// Create a new master IFD entry from a buried Photoshop 6 IFD entry. Don't try to get clever with// large values, just create a new copy. This preserves a clean separation between the memory-based// and file-based TIFF processing.void* TIFF_FileWriter::CopyTagToMasterIFD ( const TagInfo & ps6Tag, InternalIFDInfo * masterIFD ){	InternalTagInfo newTag ( ps6Tag.id, ps6Tag.type, ps6Tag.count );	newTag.dataLen = ps6Tag.dataLen;		if ( newTag.dataLen <= 4 ) {		newTag.dataPtr = (XMP_Uns8*) &newTag.dataOrOffset;		newTag.dataOrOffset = *((XMP_Uns32*)ps6Tag.dataPtr);	} else {		XMP_Assert ( newTag.dataOrOffset == 0 );		newTag.dataPtr = (XMP_Uns8*) malloc ( newTag.dataLen );		if ( newTag.dataPtr == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory );		memcpy ( newTag.dataPtr, ps6Tag.dataPtr, newTag.dataLen );	// AUDIT: Safe, malloc'ed dataLen bytes above.	}	newTag.changed = true;	// ! See comments with ProcessPShop6IFD.	XMP_Assert ( (newTag.origLen == 0) && (newTag.origOffset == 0) );		masterIFD->tagMap[newTag.id] = newTag;	masterIFD->changed = true;		return masterIFD->tagMap[newTag.id].dataPtr;	// ! Return the address within the map entry for small values.}	// TIFF_FileWriter::CopyTagToMasterIFD// =================================================================================================// FlipCFATable// ============//// The CFA pattern table is trivial, a pair of short counts followed by n*m bytes.static bool FlipCFATable ( void* voidPtr, XMP_Uns32 tagLen, GetUns16_Proc GetUns16 ){	if ( tagLen < 4 ) return false;		XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr;	Flip2 ( &u16Ptr[0] );	// Flip the counts to match the master TIFF.	Flip2 ( &u16Ptr[1] );		XMP_Uns16 columns = GetUns16 ( &u16Ptr[0] );	// Fetch using the master TIFF's routine.	XMP_Uns16 rows    = GetUns16 ( &u16Ptr[1] );		if ( tagLen != (XMP_Uns32)(4 + columns*rows) ) return false;		return true;}	// FlipCFATable// =================================================================================================// FlipDSDTable// ============//// The device settings description table is trivial, a pair of short counts followed by UTF-16// strings. So the whole value should be flipped as a sequence of 16 bit items.// ! The Exif 2.2 description is a bit garbled. It might be wrong. It would be nice to have a real example.static bool FlipDSDTable ( void* voidPtr, XMP_Uns32 tagLen, GetUns16_Proc GetUns16 ){	if ( tagLen < 4 ) return false;		XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr;	for ( size_t i = tagLen/2; i > 0; --i, ++u16Ptr ) Flip2 ( u16Ptr );

⌨️ 快捷键说明

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