//-------------------------------------------------------------------------- // 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: %05d-%05d: 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+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); } } }