summaryrefslogtreecommitdiff
path: root/source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp')
-rw-r--r--source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp157
1 files changed, 75 insertions, 82 deletions
diff --git a/source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp b/source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp
index 4ca9cac..316cea0 100644
--- a/source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp
+++ b/source/XMPFiles/FormatSupport/TIFF_MemoryReader.cpp
@@ -1,6 +1,6 @@
// =================================================================================================
// ADOBE SYSTEMS INCORPORATED
-// Copyright 2006-2007 Adobe Systems Incorporated
+// Copyright 2006 Adobe Systems Incorporated
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -14,7 +14,7 @@
/// \brief Implementation of the memory-based read-only TIFF_Manager.
///
/// The read-only forms of TIFF_Manager are derived from TIFF_Reader. The GetTag methods are common
-/// implementations in TIFF_Reader. The parsing code is different in the TIFF_MemoryReader and
+/// implementations in TIFF_Reader. The parsing code is different in the TIFF_MemoryReader and
/// TIFF_FileReader constructors. There are also separate destructors to release captured info.
///
/// The read-only implementations use runtime data that is simple tweaks on the stored form. The
@@ -52,9 +52,9 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD )
XMP_Uns16 tagCount = thisIFD->count;
TweakedIFDEntry* ifdEntries = thisIFD->entries;
XMP_Uns16 prevTag = ifdEntries[0].id;
-
+
for ( size_t i = 1; i < tagCount; ++i ) {
-
+
XMP_Uns16 thisTag = ifdEntries[i].id;
if ( thisTag > prevTag ) {
@@ -76,7 +76,7 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD )
for ( j = (XMP_Int32)i-1; j >= 0; --j ) {
if ( ifdEntries[j].id <= thisTag ) break;
}
-
+
if ( (j >= 0) && (ifdEntries[j].id == thisTag) ) {
// Out of order duplicate, move it to position j, move the tail of the array up.
@@ -96,11 +96,11 @@ void TIFF_MemoryReader::SortIFD ( TweakedIFDInfo* thisIFD )
}
}
-
+
}
-
+
thisIFD->count = tagCount; // Save the final count.
-
+
} // TIFF_MemoryReader::SortIFD
// =================================================================================================
@@ -111,15 +111,16 @@ bool TIFF_MemoryReader::GetIFD ( XMP_Uns8 ifd, TagInfoMap* ifdMap ) const
{
if ( ifd > kTIFF_LastRealIFD ) XMP_Throw ( "Invalid IFD requested", kXMPErr_InternalFailure );
const TweakedIFDInfo* thisIFD = &containedIFDs[ifd];
-
+
if ( ifdMap != 0 ) ifdMap->clear();
if ( thisIFD->count == 0 ) return false;
-
+
if ( ifdMap != 0 ) {
-
+
for ( size_t i = 0; i < thisIFD->count; ++i ) {
TweakedIFDEntry* thisTag = &(thisIFD->entries[i]);
+ if ( (thisTag->type < kTIFF_ByteType) || (thisTag->type > kTIFF_LastType) ) continue; // Bad type, skip this tag.
TagInfo info ( thisTag->id, thisTag->type, 0, 0, thisTag->bytes );
info.count = info.dataLen / (XMP_Uns32)kTIFF_TypeSizes[info.type];
@@ -128,9 +129,9 @@ bool TIFF_MemoryReader::GetIFD ( XMP_Uns8 ifd, TagInfoMap* ifdMap ) const
(*ifdMap)[info.id] = info;
}
-
+
}
-
+
return true;
} // TIFF_MemoryReader::GetIFD
@@ -144,23 +145,23 @@ const TIFF_MemoryReader::TweakedIFDEntry* TIFF_MemoryReader::FindTagInIFD ( XMP_
if ( ifd == kTIFF_KnownIFD ) {
// ... lookup the tag in the known tag map
}
-
+
if ( ifd > kTIFF_LastRealIFD ) XMP_Throw ( "Invalid IFD requested", kXMPErr_InternalFailure );
const TweakedIFDInfo* thisIFD = &containedIFDs[ifd];
-
+
if ( thisIFD->count == 0 ) return 0;
-
+
XMP_Uns32 spanLength = thisIFD->count;
const TweakedIFDEntry* spanBegin = &(thisIFD->entries[0]);
-
+
while ( spanLength > 1 ) {
XMP_Uns32 halfLength = spanLength >> 1; // Since spanLength > 1, halfLength > 0.
const TweakedIFDEntry* spanMiddle = spanBegin + halfLength;
-
+
// There are halfLength entries below spanMiddle, then the spanMiddle entry, then
// spanLength-halfLength-1 entries above spanMiddle (which can be none).
-
+
if ( spanMiddle->id == id ) {
spanBegin = spanMiddle;
break;
@@ -170,9 +171,9 @@ const TIFF_MemoryReader::TweakedIFDEntry* TIFF_MemoryReader::FindTagInIFD ( XMP_
spanBegin = spanMiddle; // Keep a valid spanBegin for the return check, don't use spanMiddle+1.
spanLength -= halfLength;
}
-
+
}
-
+
if ( spanBegin->id != id ) spanBegin = 0;
return spanBegin;
@@ -186,11 +187,11 @@ XMP_Uns32 TIFF_MemoryReader::GetValueOffset ( XMP_Uns8 ifd, XMP_Uns16 id ) const
{
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return 0;
-
+
XMP_Uns8 * valuePtr = (XMP_Uns8*) this->GetDataPtr ( thisTag );
-
+
return (XMP_Uns32)(valuePtr - this->tiffStream); // ! TIFF streams can't exceed 4GB.
-
+
} // TIFF_MemoryReader::GetValueOffset
// =================================================================================================
@@ -201,20 +202,21 @@ bool TIFF_MemoryReader::GetTag ( XMP_Uns8 ifd, XMP_Uns16 id, TagInfo* info ) con
{
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return false;
-
+ if ( (thisTag->type < kTIFF_ByteType) || (thisTag->type > kTIFF_LastType) ) return false; // Bad type, skip this tag.
+
if ( info != 0 ) {
info->id = thisTag->id;
info->type = thisTag->type;
info->count = thisTag->bytes / (XMP_Uns32)kTIFF_TypeSizes[thisTag->type];
info->dataLen = thisTag->bytes;
-
+
info->dataPtr = this->GetDataPtr ( thisTag );
}
-
+
return true;
-
+
} // TIFF_MemoryReader::GetTag
// =================================================================================================
@@ -225,7 +227,7 @@ bool TIFF_MemoryReader::GetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32*
{
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return false;
-
+
if ( data != 0 ) {
if ( thisTag->type == kTIFF_ShortType ) {
if ( thisTag->bytes != 2 ) return false; // Wrong count.
@@ -237,7 +239,7 @@ bool TIFF_MemoryReader::GetTag_Integer ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32*
return false;
}
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Integer
@@ -251,11 +253,11 @@ bool TIFF_MemoryReader::GetTag_Byte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns8* data
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return false;
if ( (thisTag->type != kTIFF_ByteType) || (thisTag->bytes != 1) ) return false;
-
+
if ( data != 0 ) {
*data = * ( (XMP_Uns8*) this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Byte
@@ -269,11 +271,11 @@ bool TIFF_MemoryReader::GetTag_SByte ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int8* dat
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return false;
if ( (thisTag->type != kTIFF_SByteType) || (thisTag->bytes != 1) ) return false;
-
+
if ( data != 0 ) {
*data = * ( (XMP_Int8*) this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_SByte
@@ -287,11 +289,11 @@ bool TIFF_MemoryReader::GetTag_Short ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns16* da
const TweakedIFDEntry* thisTag = this->FindTagInIFD ( ifd, id );
if ( thisTag == 0 ) return false;
if ( (thisTag->type != kTIFF_ShortType) || (thisTag->bytes != 2) ) return false;
-
+
if ( data != 0 ) {
*data = this->GetUns16 ( this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Short
@@ -305,11 +307,11 @@ bool TIFF_MemoryReader::GetTag_SShort ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int16* d
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 ( this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_SShort
@@ -323,11 +325,11 @@ bool TIFF_MemoryReader::GetTag_Long ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Uns32* dat
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 ( this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Long
@@ -341,11 +343,11 @@ bool TIFF_MemoryReader::GetTag_SLong ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_Int32* da
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 ( this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_SLong
@@ -359,13 +361,13 @@ bool TIFF_MemoryReader::GetTag_Rational ( XMP_Uns8 ifd, XMP_Uns16 id, Rational*
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*) this->GetDataPtr ( thisTag );
data->num = this->GetUns32 ( dataPtr );
data->denom = this->GetUns32 ( dataPtr+1 );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Rational
@@ -379,13 +381,13 @@ bool TIFF_MemoryReader::GetTag_SRational ( XMP_Uns8 ifd, XMP_Uns16 id, SRational
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*) this->GetDataPtr ( thisTag );
data->num = (XMP_Int32) this->GetUns32 ( dataPtr );
data->denom = (XMP_Int32) this->GetUns32 ( dataPtr+1 );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_SRational
@@ -399,11 +401,11 @@ bool TIFF_MemoryReader::GetTag_Float ( XMP_Uns8 ifd, XMP_Uns16 id, float* data )
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 ( this->GetDataPtr ( thisTag ) );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Float
@@ -417,12 +419,12 @@ bool TIFF_MemoryReader::GetTag_Double ( XMP_Uns8 ifd, XMP_Uns16 id, double* data
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*) this->GetDataPtr ( thisTag );
*data = this->GetDouble ( dataPtr );
}
-
+
return true;
} // TIFF_MemoryReader::GetTag_Double
@@ -436,13 +438,13 @@ bool TIFF_MemoryReader::GetTag_ASCII ( XMP_Uns8 ifd, XMP_Uns16 id, XMP_StringPtr
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) this->GetDataPtr ( thisTag );
}
-
+
if ( dataLen != 0 ) *dataLen = thisTag->bytes;
-
+
return true;
} // TIFF_MemoryReader::GetTag_ASCII
@@ -456,9 +458,9 @@ bool TIFF_MemoryReader::GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::
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 ( this->GetDataPtr ( thisTag ), thisTag->bytes, utf8Str );
return ok;
@@ -473,21 +475,21 @@ bool TIFF_MemoryReader::GetTag_EncodedString ( XMP_Uns8 ifd, XMP_Uns16 id, std::
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;
@@ -500,13 +502,16 @@ void TIFF_MemoryReader::ParseMemoryStream ( const void* data, XMP_Uns32 length,
}
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 );
+
+ // ! Need the thumbnail IFD for checking full Exif APP1 in some JPEG files!
+ if ( tnailIFDOffset != 0 ) (void) this->ProcessOneIFD ( tnailIFDOffset, kTIFF_TNailIFD );
const TweakedIFDEntry* exifIFDTag = this->FindTagInIFD ( kTIFF_PrimaryIFD, kTIFF_ExifIFDPointer );
if ( (exifIFDTag != 0) && (exifIFDTag->type == kTIFF_LongType) && (exifIFDTag->bytes == 4) ) {
@@ -525,18 +530,6 @@ void TIFF_MemoryReader::ParseMemoryStream ( const void* data, XMP_Uns32 length,
XMP_Uns32 interopOffset = this->GetUns32 ( &interopIFDTag->dataOrPos );
(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->dataOrPos );
- this->jpegTNailPtr = (XMP_Uns8*)this->tiffStream + tnailImageOffset;
- }
- }
} // TIFF_MemoryReader::ParseMemoryStream
@@ -547,11 +540,11 @@ void TIFF_MemoryReader::ParseMemoryStream ( const void* data, XMP_Uns32 length,
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);
@@ -561,11 +554,11 @@ XMP_Uns32 TIFF_MemoryReader::ProcessOneIFD ( XMP_Uns32 ifdOffset, XMP_Uns8 ifd )
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 ) {
@@ -573,7 +566,7 @@ XMP_Uns32 TIFF_MemoryReader::ProcessOneIFD ( XMP_Uns32 ifdOffset, XMP_Uns8 ifd )
Flip2 ( &thisEntry->type );
Flip4 ( &thisEntry->bytes );
}
-
+
if ( thisEntry->id <= prevTag ) needsSorting = true;
prevTag = thisEntry->id;
@@ -586,12 +579,12 @@ XMP_Uns32 TIFF_MemoryReader::ProcessOneIFD ( XMP_Uns32 ifdOffset, XMP_Uns8 ifd )
}
}
-
+
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