📄 tiff_memoryreader.cpp
字号:
// =================================================================================================// TIFF_MemoryReader::GetTag_SShort// ================================bool TIFF_MemoryReader::GetTag_SShort ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int16* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_SShortType) || (thisTag->bytes != 2) ) return false; if ( data != 0 ) { *data = (XMP_Int16) this->GetUns16 ( &(thisTag->dataOrPtr) ); } return true;} // TIFF_MemoryReader::GetTag_SShort// =================================================================================================// TIFF_MemoryReader::GetTag_Long// ==============================bool TIFF_MemoryReader::GetTag_Long ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_LongType) || (thisTag->bytes != 4) ) return false; if ( data != 0 ) { *data = this->GetUns32 ( &(thisTag->dataOrPtr) ); } return true;} // TIFF_MemoryReader::GetTag_Long// =================================================================================================// TIFF_MemoryReader::GetTag_SLong// ===============================bool TIFF_MemoryReader::GetTag_SLong ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int32* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_SLongType) || (thisTag->bytes != 4) ) return false; if ( data != 0 ) { *data = (XMP_Int32) this->GetUns32 ( &(thisTag->dataOrPtr) ); } return true;} // TIFF_MemoryReader::GetTag_SLong// =================================================================================================// TIFF_MemoryReader::GetTag_Rational// ==================================bool TIFF_MemoryReader::GetTag_Rational ( XMP_Uns8 ifd, XMP_Uns16 id, Rational* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_RationalType) || (thisTag->bytes != 8) ) return false; if ( data != 0 ) { XMP_Uns32* dataPtr = (XMP_Uns32*)thisTag->dataOrPtr; data->num = this->GetUns32 ( dataPtr ); data->denom = this->GetUns32 ( dataPtr+1 ); } return true;} // TIFF_MemoryReader::GetTag_Rational// =================================================================================================// TIFF_MemoryReader::GetTag_SRational// ===================================bool TIFF_MemoryReader::GetTag_SRational ( XMP_Uns8 ifd, XMP_Uns16 id, SRational* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_SRationalType) || (thisTag->bytes != 8) ) return false; if ( data != 0 ) { XMP_Uns32* dataPtr = (XMP_Uns32*)thisTag->dataOrPtr; data->num = (XMP_Int32) this->GetUns32 ( dataPtr ); data->denom = (XMP_Int32) this->GetUns32 ( dataPtr+1 ); } return true;} // TIFF_MemoryReader::GetTag_SRational// =================================================================================================// TIFF_MemoryReader::GetTag_Float// ===============================bool TIFF_MemoryReader::GetTag_Float ( XMP_Uns8 ifd, XMP_Uns16 id, float* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_FloatType) || (thisTag->bytes != 4) ) return false; if ( data != 0 ) { *data = this->GetFloat ( &(thisTag->dataOrPtr) ); } return true;} // TIFF_MemoryReader::GetTag_Float// =================================================================================================// TIFF_MemoryReader::GetTag_Double// ================================bool TIFF_MemoryReader::GetTag_Double ( XMP_Uns8 ifd, XMP_Uns16 id, double* data ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( (thisTag->type != kTIFF_DoubleType) || (thisTag->bytes != 8) ) return false; if ( data != 0 ) { double* dataPtr = (double*)thisTag->dataOrPtr; *data = this->GetDouble ( dataPtr ); } return true;} // TIFF_MemoryReader::GetTag_Double// =================================================================================================// TIFF_MemoryReader::GetTag_ASCII// ===============================bool TIFF_MemoryReader::GetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr* dataPtr, XMP_StringLen* dataLen ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( thisTag->type != kTIFF_ASCIIType ) return false; if ( dataPtr != 0 ) { *dataPtr = (XMP_StringPtr)thisTag->dataOrPtr; if ( thisTag->bytes <= 4 ) *dataPtr = (XMP_StringPtr)(&thisTag->dataOrPtr); } if ( dataLen != 0 ) *dataLen = thisTag->bytes; return true;} // TIFF_MemoryReader::GetTag_ASCII// =================================================================================================// TIFF_MemoryReader::GetTag_EncodedString// =======================================bool TIFF_MemoryReader::GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::string* utf8Str ) const{ const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id ); if ( thisTag == 0 ) return false; if ( thisTag->type != kTIFF_UndefinedType ) return false; if ( utf8Str == 0 ) return true; // Return true if the converted string is not wanted. bool ok = this->DecodeString ( (void*)thisTag->dataOrPtr, thisTag->bytes, utf8Str ); return ok;} // TIFF_MemoryReader::GetTag_EncodedString// =================================================================================================// TIFF_MemoryReader::ParseMemoryStream// ====================================// *** Need to tell TIFF/Exif from TIFF/EP, DNG files are the latter.void TIFF_MemoryReader::ParseMemoryStream ( const void* data, XMP_Uns32 length, bool copyData /* = true */ ){ // Get rid of any current TIFF. if ( this->ownedStream ) free ( this->tiffStream ); this->ownedStream = false; this->tiffStream = 0; this->tiffLength = 0; for ( size_t i = 0; i < kTIFF_KnownIFDCount; ++i ) { this->containedIFDs[i].count = 0; this->containedIFDs[i].entries = 0; } if ( length == 0 ) return; // Allocate space for the full in-memory stream and copy it. if ( ! copyData ) { XMP_Assert ( ! this->ownedStream ); this->tiffStream = (XMP_Uns8*) data; } else { if ( length > 100*1024*1024 ) XMP_Throw ( "Outrageous length for memory-based TIFF", kXMPErr_BadTIFF ); this->tiffStream = (XMP_Uns8*) malloc(length); if ( this->tiffStream == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory ); memcpy ( this->tiffStream, data, length ); // AUDIT: Safe, malloc'ed length bytes above. this->ownedStream = true; } this->tiffLength = length; // Find and process the primary, Exif, GPS, and Interoperability IFDs. XMP_Uns32 primaryIFDOffset = this->CheckTIFFHeader ( this->tiffStream, length ); XMP_Uns32 tnailIFDOffset = 0; if ( primaryIFDOffset != 0 ) tnailIFDOffset = this->ProcessOneIFD ( primaryIFDOffset, kTIFF_PrimaryIFD ); const TweakedIFDEntry* exifIFDTag = this->FindTagInIFD ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer ); if ( (exifIFDTag != 0) && (exifIFDTag->type == kTIFF_LongType) && (exifIFDTag->bytes == 4) ) { XMP_Uns32 exifOffset = this->GetUns32 ( &exifIFDTag->dataOrPtr ); (void) this->ProcessOneIFD ( exifOffset, kTIFF_ExifIFD ); } const TweakedIFDEntry* gpsIFDTag = this->FindTagInIFD ( kTIFF_PrimaryIFD, kTIFF_GPSInfoIFDPointer ); if ( (gpsIFDTag != 0) && (gpsIFDTag->type == kTIFF_LongType) && (gpsIFDTag->bytes == 4) ) { XMP_Uns32 gpsOffset = this->GetUns32 ( &gpsIFDTag->dataOrPtr ); (void) this->ProcessOneIFD ( gpsOffset, kTIFF_GPSInfoIFD ); } const TweakedIFDEntry* interopIFDTag = this->FindTagInIFD ( kTIFF_ExifIFD, kTIFF_InteroperabilityIFDPointer ); if ( (interopIFDTag != 0) && (interopIFDTag->type == kTIFF_LongType) && (interopIFDTag->bytes == 4) ) { XMP_Uns32 interopOffset = this->GetUns32 ( &interopIFDTag->dataOrPtr ); (void) this->ProcessOneIFD ( interopOffset, kTIFF_InteropIFD ); } // Process the thumbnail IFD. We only do this for Exif-compliant TIFF streams. Extract the // JPEG thumbnail image pointer (tag 513) for later use by GetTNailInfo. if ( (tnailIFDOffset != 0) && (this->containedIFDs[kTIFF_ExifIFD].count > 0) ) { (void) this->ProcessOneIFD ( tnailIFDOffset, kTIFF_TNailIFD ); const TweakedIFDEntry* jpegInfo = FindTagInIFD ( kTIFF_TNailIFD, kTIFF_JPEGInterchangeFormat ); if ( jpegInfo != 0 ) { XMP_Uns32 tnailImageOffset = this->GetUns32 ( &jpegInfo->dataOrPtr ); this->jpegTNailPtr = (XMP_Uns8*)this->tiffStream + tnailImageOffset; } }} // TIFF_MemoryReader::ParseMemoryStream// =================================================================================================// TIFF_MemoryReader::ProcessOneIFD// ================================XMP_Uns32 TIFF_MemoryReader::ProcessOneIFD ( XMP_Uns32 ifdOffset, XMP_Uns8 ifd ){ TweakedIFDInfo& ifdInfo = this->containedIFDs[ifd]; if ( (ifdOffset < 8) || (ifdOffset > (this->tiffLength - kEmptyIFDLength)) ) { XMP_Throw ( "Bad IFD offset", kXMPErr_BadTIFF ); } XMP_Uns8* ifdPtr = this->tiffStream + ifdOffset; XMP_Uns16 ifdCount = this->GetUns16 ( ifdPtr ); TweakedIFDEntry* ifdEntries = (TweakedIFDEntry*)(ifdPtr+2); if ( ifdCount >= 0x8000 ) XMP_Throw ( "Outrageous IFD count", kXMPErr_BadTIFF ); if ( (ifdOffset + 2 + ifdCount*12 + 4) > this->tiffLength ) XMP_Throw ( "Out of bounds IFD", kXMPErr_BadTIFF ); ifdInfo.count = ifdCount; ifdInfo.entries = ifdEntries; XMP_Int32 prevTag = -1; // ! The GPS IFD has a tag 0, so we need a signed initial value. bool needsSorting = false; for ( size_t i = 0; i < ifdCount; ++i ) { TweakedIFDEntry* thisEntry = &ifdEntries[i]; // Tweak the IFD entry to be more useful. if ( ! this->nativeEndian ) { Flip2 ( &thisEntry->id ); Flip2 ( &thisEntry->type ); Flip4 ( &thisEntry->bytes ); } if ( thisEntry->id <= prevTag ) needsSorting = true; prevTag = thisEntry->id; if ( (thisEntry->type < kTIFF_ByteType) || (thisEntry->type > kTIFF_LastType) ) continue; // Bad type, skip this tag. thisEntry->bytes *= kTIFF_TypeSizes[thisEntry->type]; if ( thisEntry->bytes > this->tiffLength ) XMP_Throw ( "Bad TIFF data size", kXMPErr_BadTIFF ); if ( thisEntry->bytes > 4 ) { if ( ! this->nativeEndian ) Flip4 ( &thisEntry->dataOrPtr ); thisEntry->dataOrPtr += (XMP_Uns32)this->tiffStream; } } ifdPtr += (2 + ifdCount*12); XMP_Uns32 nextIFDOffset = this->GetUns32 ( ifdPtr ); if ( needsSorting ) SortIFD ( &ifdInfo ); // ! Don't perturb the ifdCount used to find the next IFD offset. return nextIFDOffset;} // TIFF_MemoryReader::ProcessOneIFD// =================================================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -