blob: 1248b80d4440ac8035b58df95410f9a7959d7da1 [file] [log] [blame]
The Android Open Source Project34a25642009-03-03 19:30:03 -08001//--------------------------------------------------------------------------
2// Parse some maker specific onformation.
3// (Very limited right now - add maker specific stuff to this module)
4//--------------------------------------------------------------------------
5#include "jhead.h"
6
7//--------------------------------------------------------------------------
8// Process exif format directory, as used by Cannon maker note
9//--------------------------------------------------------------------------
10void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
11 unsigned ExifLength)
12{
13 int de;
14 int a;
15 int NumDirEntries;
16
17 NumDirEntries = Get16u(DirStart);
18 #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
19
20 {
21 unsigned char * DirEnd;
22 DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
23 if (DirEnd > (OffsetBase+ExifLength)){
24 ErrNonfatal("Illegally sized directory",0,0);
25 return;
26 }
27
28 if (DumpExifMap){
Mark Salyzyn1ac78682014-04-17 13:28:32 -070029 printf("Map: %05td-%05td: Directory (makernote)\n",DirStart-OffsetBase, DirEnd-OffsetBase);
The Android Open Source Project34a25642009-03-03 19:30:03 -080030 }
31 }
32
33 if (ShowTags){
34 printf("(dir has %d entries)\n",NumDirEntries);
35 }
36
37 for (de=0;de<NumDirEntries;de++){
38 int Tag, Format, Components;
39 unsigned char * ValuePtr;
40 int ByteCount;
41 unsigned char * DirEntry;
42 DirEntry = DIR_ENTRY_ADDR(DirStart, de);
43
44 Tag = Get16u(DirEntry);
45 Format = Get16u(DirEntry+2);
46 Components = Get32u(DirEntry+4);
47
48 if ((Format-1) >= NUM_FORMATS) {
49 // (-1) catches illegal zero case as unsigned underflows to positive large.
50 ErrNonfatal("Illegal number format %d for tag %04x", Format, Tag);
51 continue;
52 }
53
54 if ((unsigned)Components > 0x10000){
55 ErrNonfatal("Illegal number of components %d for tag %04x", Components, Tag);
56 continue;
57 }
58
59 ByteCount = Components * BytesPerFormat[Format];
60
61 if (ByteCount > 4){
62 unsigned OffsetVal;
63 OffsetVal = Get32u(DirEntry+8);
64 // If its bigger than 4 bytes, the dir entry contains an offset.
Teow Wan Yee92f207c2016-08-24 09:50:36 +080065 if (OffsetVal > UINT32_MAX - ByteCount || OffsetVal+ByteCount > ExifLength){
The Android Open Source Project34a25642009-03-03 19:30:03 -080066 // Bogus pointer offset and / or bytecount value
67 ErrNonfatal("Illegal value pointer for tag %04x", Tag,0);
68 continue;
69 }
70 ValuePtr = OffsetBase+OffsetVal;
71
72 if (DumpExifMap){
73 printf("Map: %05d-%05d: Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
74 }
75 }else{
76 // 4 bytes or less and value is in the dir entry itself
77 ValuePtr = DirEntry+8;
78 }
79
80 if (ShowTags){
81 // Show tag name
82 printf(" Canon maker tag %04x Value = ", Tag);
83 }
84
85 // Show tag value.
86 switch(Format){
87
88 case FMT_UNDEFINED:
89 // Undefined is typically an ascii string.
90
91 case FMT_STRING:
92 // String arrays printed without function call (different from int arrays)
93 if (ShowTags){
94 printf("\"");
95 for (a=0;a<ByteCount;a++){
96 int ZeroSkipped = 0;
97 if (ValuePtr[a] >= 32){
98 if (ZeroSkipped){
99 printf("?");
100 ZeroSkipped = 0;
101 }
102 putchar(ValuePtr[a]);
103 }else{
104 if (ValuePtr[a] == 0){
105 ZeroSkipped = 1;
106 }
107 }
108 }
109 printf("\"\n");
110 }
111 break;
112
113 default:
114 if (ShowTags){
115 PrintFormatNumber(ValuePtr, Format, ByteCount);
116 printf("\n");
117 }
118 }
119 if (Tag == 1 && Components > 16){
120 int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
121 if (IsoCode >= 16 && IsoCode <= 24){
122 ImageInfo.ISOequivalent = 50 << (IsoCode-16);
123 }
124 }
125
126 if (Tag == 4 && Format == FMT_USHORT){
127 if (Components > 7){
128 int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
129 switch(WhiteBalance){
130 // 0=Auto, 6=Custom
131 case 1: ImageInfo.LightSource = 1; break; // Sunny
132 case 2: ImageInfo.LightSource = 1; break; // Cloudy
133 case 3: ImageInfo.LightSource = 3; break; // Thungsten
134 case 4: ImageInfo.LightSource = 2; break; // Fourescent
135 case 5: ImageInfo.LightSource = 4; break; // Flash
136 }
137 }
138 if (Components > 19 && ImageInfo.Distance <= 0) {
139 // Inidcates the distance the autofocus camera is focused to.
140 // Tends to be less accurate as distance increases.
141 int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
142printf("temp dist=%d\n",temp_dist);
143 if (temp_dist != 65535){
144 ImageInfo.Distance = (float)temp_dist/100;
145 }else{
146 ImageInfo.Distance = -1 /* infinity */;
147 }
148 }
149 }
150 }
151}
152
153//--------------------------------------------------------------------------
154// Show generic maker note - just hex bytes.
155//--------------------------------------------------------------------------
156void ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
157{
158 int a;
159 for (a=0;a<ByteCount;a++){
160 if (a > 10){
161 printf("...");
162 break;
163 }
164 printf(" %02x",ValuePtr[a]);
165 }
166 printf(" (%d bytes)", ByteCount);
167 printf("\n");
168
169}
170
171//--------------------------------------------------------------------------
172// Process maker note - to the limited extent that its supported.
173//--------------------------------------------------------------------------
174void ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
175 unsigned char * OffsetBase, unsigned ExifLength)
176{
177 if (strstr(ImageInfo.CameraMake, "Canon")){
178 ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
179 }else{
180 if (ShowTags){
181 ShowMakerNoteGeneric(ValuePtr, ByteCount);
182 }
183 }
184}
185