|
|
int Get32s(void * Long); | int Get32s(void * Long); |
unsigned Get32u(void * Long); | unsigned Get32u(void * Long); |
double ConvertAnyFormat(void * ValuePtr, int Format); | double ConvertAnyFormat(void * ValuePtr, int Format); |
void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength); |
void ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, |
|
unsigned NestingLevel); |
void process_COM (const uchar * Data, int length); | void process_COM (const uchar * Data, int length); |
void process_SOFn (const uchar * Data, int marker); | void process_SOFn (const uchar * Data, int marker); |
int Get16m(const void * Short); | int Get16m(const void * Short); |
|
|
//-------------------------------------------------------------------------- | //-------------------------------------------------------------------------- |
// Process one of the nested EXIF directories. | // Process one of the nested EXIF directories. |
//-------------------------------------------------------------------------- | //-------------------------------------------------------------------------- |
void ExifData::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength) |
void ExifData::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength, unsigned NestingLevel) |
{ | { |
int de; | int de; |
int a; | int a; |
|
|
unsigned ThumbnailOffset = 0; | unsigned ThumbnailOffset = 0; |
unsigned ThumbnailSize = 0; | unsigned ThumbnailSize = 0; |
| |
|
if ( NestingLevel > 4) |
|
throw FatalError("Maximum directory nesting exceeded (corrupt exif header)"); |
|
|
NumDirEntries = Get16u(DirStart); | NumDirEntries = Get16u(DirStart); |
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) | #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry)) |
| |
|
|
for (de=0;de<NumDirEntries;de++){ | for (de=0;de<NumDirEntries;de++){ |
int Tag, Format, Components; | int Tag, Format, Components; |
unsigned char * ValuePtr; | unsigned char * ValuePtr; |
int ByteCount; |
unsigned ByteCount; |
char * DirEntry; | char * DirEntry; |
DirEntry = (char *)DIR_ENTRY_ADDR(DirStart, de); | DirEntry = (char *)DIR_ENTRY_ADDR(DirStart, de); |
| |
|
|
throw FatalError("Illegal format code in EXIF dir"); | throw FatalError("Illegal format code in EXIF dir"); |
} | } |
| |
|
if ((unsigned)Components > 0x10000) { |
|
throw FatalError("Illegal number of components for tag"); |
|
continue; |
|
} |
|
|
ByteCount = Components * BytesPerFormat[Format]; | ByteCount = Components * BytesPerFormat[Format]; |
| |
if (ByteCount > 4){ | if (ByteCount > 4){ |
|
|
switch(Tag){ | switch(Tag){ |
| |
case TAG_MAKE: | case TAG_MAKE: |
ExifData::CameraMake = QString((char*)ValuePtr); |
ExifData::CameraMake = QString::fromLatin1((const char*)ValuePtr, 31); |
break; | break; |
| |
case TAG_MODEL: | case TAG_MODEL: |
ExifData::CameraModel = QString((char*)ValuePtr); |
ExifData::CameraModel = QString::fromLatin1((const char*)ValuePtr, 39); |
break; | break; |
| |
case TAG_ORIENTATION: | case TAG_ORIENTATION: |
|
|
break; | break; |
| |
case TAG_DATETIME_ORIGINAL: | case TAG_DATETIME_ORIGINAL: |
DateTime = QString((char*)ValuePtr); |
DateTime = QString::fromLatin1((const char*)ValuePtr, 19); |
break; | break; |
| |
case TAG_USERCOMMENT: | case TAG_USERCOMMENT: |
|
|
int c; | int c; |
c = (ValuePtr)[a]; | c = (ValuePtr)[a]; |
if (c != '\0' && c != ' '){ | if (c != '\0' && c != ' '){ |
//strncpy(ImageInfo.Comments, (const char*)(a+ValuePtr), 199); |
UserComment = QString::fromLatin1((const char*)(a+ValuePtr), 199); |
UserComment.sprintf("%s", (const char*)(a+ValuePtr)); |
|
break; | break; |
} | } |
} | } |
}else{ | }else{ |
//strncpy(ImageInfo.Comments, (const char*)ValuePtr, 199); |
UserComment = QString::fromLatin1((const char*)ValuePtr, 199); |
UserComment.sprintf("%s", (const char*)ValuePtr); |
|
} | } |
break; | break; |
| |
|
|
if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){ | if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){ |
unsigned char * SubdirStart; | unsigned char * SubdirStart; |
SubdirStart = OffsetBase + Get32u(ValuePtr); | SubdirStart = OffsetBase + Get32u(ValuePtr); |
if (SubdirStart < OffsetBase || SubdirStart > OffsetBase+ExifLength){ |
if (SubdirStart <= OffsetBase || SubdirStart >= OffsetBase+ExifLength){ |
throw FatalError("Illegal subdirectory link"); | throw FatalError("Illegal subdirectory link"); |
} | } |
ProcessExifDir(SubdirStart, OffsetBase, ExifLength); |
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel+1); |
continue; | continue; |
} | } |
} | } |
|
|
} | } |
}else{ | }else{ |
if (SubdirStart <= OffsetBase+ExifLength){ | if (SubdirStart <= OffsetBase+ExifLength){ |
ProcessExifDir(SubdirStart, OffsetBase, ExifLength); |
ProcessExifDir(SubdirStart, OffsetBase, ExifLength, NestingLevel+1); |
} | } |
} | } |
} | } |
|
|
} | } |
| |
if (ThumbnailSize && ThumbnailOffset){ | if (ThumbnailSize && ThumbnailOffset){ |
if (ThumbnailSize + ThumbnailOffset <= ExifLength){ |
if (ThumbnailSize + ThumbnailOffset < ExifLength){ |
// The thumbnail pointer appears to be valid. Store it. | // The thumbnail pointer appears to be valid. Store it. |
Thumbnail.loadFromData(OffsetBase + ThumbnailOffset, ThumbnailSize, "JPEG"); | Thumbnail.loadFromData(OffsetBase + ThumbnailOffset, ThumbnailSize, "JPEG"); |
} | } |
|
|
LastExifRefd = CharBuf; | LastExifRefd = CharBuf; |
| |
// First directory starts 16 bytes in. Offsets start at 8 bytes in. | // First directory starts 16 bytes in. Offsets start at 8 bytes in. |
ProcessExifDir(CharBuf+16, CharBuf+8, length-6); |
ProcessExifDir(CharBuf+16, CharBuf+8, length-6, 0); |
| |
// This is how far the interesting (non thumbnail) part of the exif went. | // This is how far the interesting (non thumbnail) part of the exif went. |
ExifSettingsLength = LastExifRefd - CharBuf; | ExifSettingsLength = LastExifRefd - CharBuf; |