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

📄 tiff_filewriter.cpp

📁 flash xmp sdk,flash官方SDK
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		return true;	}	// FlipDSDTable// =================================================================================================// FlipOECFSFRTable// ================//// The OECF and SFR tables have the same layout://    2 short counts, columns and rows//    c ASCII strings, null terminated, column names//    c*r rationalsstatic bool FlipOECFSFRTable ( void* voidPtr, XMP_Uns32 tagLen, GetUns16_Proc GetUns16 ){	XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr;	Flip2 ( &u16Ptr[0] );	// Flip the data 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] );		XMP_Uns32 minLen = 4 + columns + (8 * columns * rows);	// Minimum legit tag size.	if ( tagLen < minLen ) return false;		// Compute the start of the rationals from the end of value. No need to walk through the names.	XMP_Uns32* u32Ptr = (XMP_Uns32*) ((XMP_Uns8*)voidPtr + tagLen - (8 * columns * rows));	for ( size_t i = 2*columns*rows; i > 0; --i, ++u32Ptr ) Flip4 ( u32Ptr );		return true;	}	// FlipOECFSFRTable// =================================================================================================// TIFF_FileWriter::ProcessPShop6IFD// =================================//// Photoshop 6 wrote wacky TIFF files that have much of the Exif metadata buried inside of image// resource 1058, which is itself within tag 34377 in the 0th IFD. This routine moves the buried// tags up to the parent file. Existing tags are not replaced.//// While it is tempting to try to directly use the TIFF_MemoryReader's tweaked IFD info, making that// visible would compromise implementation separation. Better to pay the modest runtime cost of // using the official GetIFD method, letting it build the map.//// The tags that get moved are marked as being changed, as is the IFD they are moved into, but the// overall TIFF_FileWriter object is not. We don't want this integration on its own to force a file// update, but a file update should include these changes.// ! Be careful to not move tags that are the nasty Exif explicit offsets, e.g. the Exif or GPS IFD// ! "pointers". These are tags with a LONG type and count of 1, whose value is an offset into the// ! buried TIFF stream. We can't reliably plant that offset into the outer IFD structure.// ! To make things even more fun, the buried Exif might not have the same endianness as the outer!void TIFF_FileWriter::ProcessPShop6IFD ( const TIFF_MemoryReader& buriedExif, XMP_Uns8 ifd ){	bool ok, found;	TagInfoMap ps6IFD;		found = buriedExif.GetIFD ( ifd, &ps6IFD );	if ( ! found ) return;		bool needsFlipping = (this->bigEndian != buriedExif.IsBigEndian());		InternalIFDInfo* masterIFD = &this->containedIFDs[ifd];		TagInfoMap::const_iterator ps6Pos = ps6IFD.begin();	TagInfoMap::const_iterator ps6End = ps6IFD.end();			for ( ; ps6Pos != ps6End; ++ps6Pos ) {			// Copy buried tags to the master IFD if they don't already exist there.				const TagInfo& ps6Tag = ps6Pos->second;			if ( this->FindTagInIFD ( ifd, ps6Tag.id ) != 0 ) continue;	// Keep existing master tags.		if ( needsFlipping && (ps6Tag.id == 37500) ) continue;	// Don't copy an unflipped MakerNote.		if ( (ps6Tag.id == kTIFF_ExifIFDPointer) ||	// Skip the tags that are explicit offsets.			 (ps6Tag.id == kTIFF_GPSInfoIFDPointer) ||			 (ps6Tag.id == kTIFF_JPEGInterchangeFormat) ||			 (ps6Tag.id == kTIFF_InteroperabilityIFDPointer) ) continue;				void* voidPtr = CopyTagToMasterIFD ( ps6Tag, masterIFD );				if ( needsFlipping ) {			switch ( ps6Tag.type ) {					case kTIFF_ByteType:				case kTIFF_SByteType:				case kTIFF_ASCIIType:					// Nothing more to do.					break;					case kTIFF_ShortType:				case kTIFF_SShortType:					{						XMP_Uns16* u16Ptr = (XMP_Uns16*)voidPtr;						for ( size_t i = ps6Tag.count; i > 0; --i, ++u16Ptr ) Flip2 ( u16Ptr );					}					break;					case kTIFF_LongType:				case kTIFF_SLongType:				case kTIFF_FloatType:					{						XMP_Uns32* u32Ptr = (XMP_Uns32*)voidPtr;						for ( size_t i = ps6Tag.count; i > 0; --i, ++u32Ptr ) Flip4 ( u32Ptr );					}					break;					case kTIFF_RationalType:				case kTIFF_SRationalType:					{						XMP_Uns32* ratPtr = (XMP_Uns32*)voidPtr;						for ( size_t i = (2 * ps6Tag.count); i > 0; --i, ++ratPtr ) Flip4 ( ratPtr );					}					break;					case kTIFF_DoubleType:					{						XMP_Uns64* u64Ptr = (XMP_Uns64*)voidPtr;						for ( size_t i = ps6Tag.count; i > 0; --i, ++u64Ptr ) Flip8 ( u64Ptr );					}					break;					case kTIFF_UndefinedType:					// Fix up the few kinds of special tables that Exif 2.2 defines.					ok = true;	// Keep everything that isn't a special table.					if ( ps6Tag.id == kTIFF_CFAPattern ) {						ok = FlipCFATable ( voidPtr, ps6Tag.dataLen, this->GetUns16 );					} else if ( ps6Tag.id == kTIFF_DeviceSettingDescription ) {						ok = FlipDSDTable ( voidPtr, ps6Tag.dataLen, this->GetUns16 );					} else if ( (ps6Tag.id == kTIFF_OECF) || (ps6Tag.id == kTIFF_SpatialFrequencyResponse) ) {						ok = FlipOECFSFRTable ( voidPtr, ps6Tag.dataLen, this->GetUns16 );					}					if ( ! ok ) this->DeleteTag ( ifd, ps6Tag.id );					break;								default:					// ? XMP_Throw ( "Unexpected tag type", kXMPErr_InternalFailure );					this->DeleteTag ( ifd, ps6Tag.id );					break;				}		}			}	}	// TIFF_FileWriter::ProcessPShop6IFD// =================================================================================================// TIFF_FileWriter::DetermineAppendInfo// ====================================#ifndef Trace_DetermineAppendInfo	#define Trace_DetermineAppendInfo 0#endifXMP_Uns32 TIFF_FileWriter::DetermineAppendInfo ( XMP_Uns32 appendedOrigin,												 bool      appendedIFDs[kTIFF_KnownIFDCount],												 XMP_Uns32 newIFDOffsets[kTIFF_KnownIFDCount],												 bool      appendAll /* = false */ ){	XMP_Uns32 appendedLength = 0;	XMP_Assert ( (appendedOrigin & 1) == 0 );	// Make sure it is even.		#if Trace_DetermineAppendInfo	{		printf ( "\nEntering TIFF_FileWriter::DetermineAppendInfo%s\n", (appendAll ? ", append all" : "") );		for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {			InternalIFDInfo & thisIFD = this->containedIFDs[ifd];			printf ( "\n   IFD %d, origCount %d, map.size %d, origOffset %d (0x%X), origNextIFD %d (0x%X)",					 ifd, thisIFD.origCount, thisIFD.tagMap.size(),					 thisIFD.origOffset, thisIFD.origOffset, thisIFD.origNextIFD, thisIFD.origNextIFD );			if ( thisIFD.changed ) printf ( ", changed" );			if ( thisIFD.origCount < thisIFD.tagMap.size() ) printf ( ", should get appended" );			printf ( "\n" );			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)",						 thisTag.id, thisTag.dataOrOffset, thisTag.origLen, thisTag.origOffset, thisTag.origOffset );				if ( thisTag.changed ) printf ( ", changed" );				if ( (thisTag.dataLen > thisTag.origLen) && (thisTag.dataLen > 4) ) printf ( ", should get appended" );				printf ( "\n" );			}		}		printf ( "\n" );	}	#endif		// Determine which of the IFDs will be appended. If the Exif, GPS, or Interoperability IFDs are	// appended, set dummy values for their offsets in the "owning" IFD. This must be done first	// since this might cause the owning IFD to grow.		if ( ! appendAll ) {		for ( int i = 0; i < kTIFF_KnownIFDCount ;++i ) appendedIFDs[i] = false;	} else {		for ( int i = 0; i < kTIFF_KnownIFDCount ;++i ) appendedIFDs[i] = (this->containedIFDs[i].tagMap.size() > 0);	}		appendedIFDs[kTIFF_InteropIFD] |= (this->containedIFDs[kTIFF_InteropIFD].origCount <									   this->containedIFDs[kTIFF_InteropIFD].tagMap.size());	if ( appendedIFDs[kTIFF_InteropIFD] ) {		this->SetTag_Long ( kTIFF_ExifIFD, kTIFF_InteroperabilityIFDPointer, 0xABADABAD );	}		appendedIFDs[kTIFF_GPSInfoIFD] |= (this->containedIFDs[kTIFF_GPSInfoIFD].origCount <									   this->containedIFDs[kTIFF_GPSInfoIFD].tagMap.size());	if ( appendedIFDs[kTIFF_GPSInfoIFD] ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_GPSInfoIFDPointer, 0xABADABAD );	}		appendedIFDs[kTIFF_ExifIFD] |= (this->containedIFDs[kTIFF_ExifIFD].origCount <								    this->containedIFDs[kTIFF_ExifIFD].tagMap.size());	if ( appendedIFDs[kTIFF_ExifIFD] ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer, 0xABADABAD );	}		appendedIFDs[kTIFF_TNailIFD] |= (this->containedIFDs[kTIFF_TNailIFD].origCount <									 this->containedIFDs[kTIFF_TNailIFD].tagMap.size());		appendedIFDs[kTIFF_PrimaryIFD] |= (this->containedIFDs[kTIFF_PrimaryIFD].origCount <									   this->containedIFDs[kTIFF_PrimaryIFD].tagMap.size());	// The appended data (if any) will be a sequence of an IFD followed by its large values.	// Determine the new offsets for the appended IFDs and tag values, and the total amount of	// appended stuff. 			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;				newIFDOffsets[ifd] = ifdInfo.origOffset;		if ( appendedIFDs[ifd] ) {			newIFDOffsets[ifd] = appendedOrigin + appendedLength;			appendedLength += 6 + (12 * tagCount);		}				InternalTagMap::iterator tagPos = ifdInfo.tagMap.begin();		InternalTagMap::iterator tagEnd = ifdInfo.tagMap.end();		for ( ; tagPos != tagEnd; ++tagPos ) {			InternalTagInfo & currTag ( tagPos->second );			if ( (! (appendAll | currTag.changed)) || (currTag.dataLen <= 4) ) continue;			if ( (currTag.dataLen <= currTag.origLen) && (! appendAll) ) {				this->PutUns32 ( currTag.origOffset, &currTag.dataOrOffset );	// Reuse the old space.			} else {				this->PutUns32 ( (appendedOrigin + appendedLength), &currTag.dataOrOffset );	// Set the appended offset.				appendedLength += ((currTag.dataLen + 1) & 0xFFFFFFFEUL);	// Round to an even size.			}		}		}		// If the Exif, GPS, or Interoperability IFDs get appended, update the tag values for their new offsets.		if ( appendedIFDs[kTIFF_ExifIFD] ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer, newIFDOffsets[kTIFF_ExifIFD] );	}	if ( appendedIFDs[kTIFF_GPSInfoIFD] ) {		this->SetTag_Long ( kTIFF_PrimaryIFD, kTIFF_GPSInfoIFDPointer, newIFDOffsets[kTIFF_GPSInfoIFD] );	}	if ( appendedIFDs[kTIFF_InteropIFD] ) {		this->SetTag_Long ( kTIFF_ExifIFD, kTIFF_InteroperabilityIFDPointer, newIFDOffsets[kTIFF_InteropIFD] );	}		#if Trace_DetermineAppendInfo	{		printf ( "Exiting TIFF_FileWriter::DetermineAppendInfo\n" );		for ( int ifd = 0; ifd < kTIFF_KnownIFDCount; ++ifd ) {			InternalIFDInfo & thisIFD = this->containedIFDs[ifd];			printf ( "\n   IFD %d, origCount %d, map.size %d, origOffset %d (0x%X), origNextIFD %d (0x%X)",					 ifd, thisIFD.origCount, thisIFD.tagMap.size(),					 thisIFD.origOffset, thisIFD.origOffset, thisIFD.origNextIFD, thisIFD.origNextIFD );			if ( thisIFD.changed ) printf ( ", changed" );			if ( appendedIFDs[ifd] ) printf ( ", will be appended at %d (0x%X)", newIFDOffsets[ifd], newIFDOffsets[ifd] );			printf ( "\n" );			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)",						 thisTag.id, thisTag.dataOrOffset, thisTag.origLen, thisTag.origOffset, thisTag.origOffset );				if ( thisTag.changed ) printf ( ", changed" );				if ( (thisTag.dataLen > thisTag.origLen) && (thisTag.dataLen > 4) ) {					XMP_Uns32 newOffset = this->GetUns32 ( &thisTag.dataOrOffset );					printf ( ", will be appended at %d (0x%X)", newOffset, newOffset );				}				printf ( "\n" );			}		}		printf ( "\n" );	}	#endif		return appendedLength;	}	// TIFF_FileWriter::DetermineAppendInfo// =================================================================================================// TIFF_FileWriter::UpdateMemByAppend// ==================================//// 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.//// When doing the update-by-append we're only going to be modifying things that have changed. This// means IFDs with changed, added, or deleted tags, and large values for changed or added tags. The// IFDs and tag values are updated in-place if they fit, leaving holes in the stream if the new// value is smaller than the old.// ** Someday we might want to use the FreeOffsets and FreeByteCounts tags to track free space.// ** Probably not a huge win in practice though, and the TIFF spec says they are not recommended// ** for general interchange use.void TIFF_FileWriter::UpdateMemByAppend ( XMP_Uns8** newStream_out, XMP_Uns32* newLength_out,										  bool appendAll /* = false */, XMP_Uns32 extraSpace /* = 0 */ ){	bool appendedIFDs[kTIFF_KnownIFDCount];	XMP_Uns32 newIFDOffsets[kTIFF_KnownIFDCount];	XMP_Uns32 appendedOrigin = ((this->tiffLength + 1) & 0xFFFFFFFEUL);	// Start at an even offset.	XMP_Uns32 appendedLength = DetermineAppendInfo ( appendedOrigin, appendedIFDs, newIFDOffsets, appendAll );

⌨️ 快捷键说明

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