summaryrefslogtreecommitdiff
path: root/makernote.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit426377d9ce95606bac741d99b5b0a3e2038924fe (patch)
treee369cfdda7dfd42203aee8100cad25e2033f1cc8 /makernote.c
downloadjhead-426377d9ce95606bac741d99b5b0a3e2038924fe.tar.gz
Diffstat (limited to 'makernote.c')
-rw-r--r--makernote.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/makernote.c b/makernote.c
new file mode 100644
index 0000000..0be4df5
--- /dev/null
+++ b/makernote.c
@@ -0,0 +1,185 @@
+//--------------------------------------------------------------------------
+// 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);
+ }
+ }
+}
+