//--------------------------------------------------------------------------
// Parse some maker specific onformation.
// (Very limited right now - add maker specific stuff to this module)
//--------------------------------------------------------------------------
#include "jhead.h"
//--------------------------------------------------------------------------
// Process exif format directory, as used by Cannon maker note
//--------------------------------------------------------------------------
void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
unsigned ExifLength)
{
int de;
int a;
int NumDirEntries;
NumDirEntries = Get16u(DirStart);
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
{
unsigned char * DirEnd;
DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
if (DirEnd > (OffsetBase+ExifLength)){
ErrNonfatal("Illegally sized directory",0,0);
return;
}
if (DumpExifMap){
printf("Map: %05td-%05td: Directory (makernote)\n",DirStart-OffsetBase, DirEnd-OffsetBase);
}
}
if (ShowTags){
printf("(dir has %d entries)\n",NumDirEntries);
}
for (de=0;de<NumDirEntries;de++){
int Tag, Format, Components;
unsigned char * ValuePtr;
int ByteCount;
unsigned char * DirEntry;
DirEntry = DIR_ENTRY_ADDR(DirStart, de);
Tag = Get16u(DirEntry);
Format = Get16u(DirEntry+2);
Components = Get32u(DirEntry+4);
if ((Format-1) >= NUM_FORMATS) {
// (-1) catches illegal zero case as unsigned underflows to positive large.
ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag);
continue;
}
if ((unsigned)Components > 0x10000){
ErrNonfatal("Illegal number of components %d for tag %04x", Components, Tag);
continue;
}
ByteCount = Components * BytesPerFormat[Format];
if (ByteCount > 4){
unsigned OffsetVal;
OffsetVal = Get32u(DirEntry+8);
// If its bigger than 4 bytes, the dir entry contains an offset.
if (OffsetVal > UINT32_MAX - ByteCount || OffsetVal+ByteCount > ExifLength){
// Bogus pointer offset and / or bytecount value
ErrNonfatal("Illegal value pointer for tag %04x", Tag,0);
continue;
}
ValuePtr = OffsetBase+OffsetVal;
if (DumpExifMap){
printf("Map: %05d-%05d: Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
}
}else{
// 4 bytes or less and value is in the dir entry itself
ValuePtr = DirEntry+8;
}
if (ShowTags){
// Show tag name
printf(" Canon maker tag %04x Value = ", Tag);
}
// Show tag value.
switch(Format){
case FMT_UNDEFINED:
// Undefined is typically an ascii string.
case FMT_STRING:
// String arrays printed without function call (different from int arrays)
if (ShowTags){
printf("\"");
for (a=0;a<ByteCount;a++){
int ZeroSkipped = 0;
if (ValuePtr[a] >= 32){
if (ZeroSkipped){
printf("?");
ZeroSkipped = 0;
}
putchar(ValuePtr[a]);
}else{
if (ValuePtr[a] == 0){
ZeroSkipped = 1;
}
}
}
printf("\"\n");
}
break;
default:
if (ShowTags){
PrintFormatNumber(ValuePtr, Format, ByteCount);
printf("\n");
}
}
if (Tag == 1 && Components > 16){
int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
if (IsoCode >= 16 && IsoCode <= 24){
ImageInfo.ISOequivalent = 50 << (IsoCode-16);
}
}
if (Tag == 4 && Format == FMT_USHORT){
if (Components > 7){
int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
switch(WhiteBalance){
// 0=Auto, 6=Custom
case 1: ImageInfo.LightSource = 1; break; // Sunny
case 2: ImageInfo.LightSource = 1; break; // Cloudy
case 3: ImageInfo.LightSource = 3; break; // Thungsten
case 4: ImageInfo.LightSource = 2; break; // Fourescent
case 5: ImageInfo.LightSource = 4; break; // Flash
}
}
if (Components > 19 && ImageInfo.Distance <= 0) {
// Inidcates the distance the autofocus camera is focused to.
// Tends to be less accurate as distance increases.
int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
printf("temp dist=%d\n",temp_dist);
if (temp_dist != 65535){
ImageInfo.Distance = (float)temp_dist/100;
}else{
ImageInfo.Distance = -1 /* infinity */;
}
}
}
}
}
//--------------------------------------------------------------------------
// Show generic maker note - just hex bytes.
//--------------------------------------------------------------------------
void ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
{
int a;
for (a=0;a<ByteCount;a++){
if (a > 10){
printf("...");
break;
}
printf(" %02x",ValuePtr[a]);
}
printf(" (%d bytes)", ByteCount);
printf("\n");
}
//--------------------------------------------------------------------------
// Process maker note - to the limited extent that its supported.
//--------------------------------------------------------------------------
void ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
unsigned char * OffsetBase, unsigned ExifLength)
{
if (strstr(ImageInfo.CameraMake, "Canon")){
ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
}else{
if (ShowTags){
ShowMakerNoteGeneric(ValuePtr, ByteCount);
}
}
}