1 /*--------------------------------------------------------------------------
2   This file contains subroutines for use by Jpegtopnm to handle the
3   EXIF header.
4 
5   The code is adapted from the program Jhead by Matthaias Wandel
6   December 1999 - August 2000, and contributed to the public domain.
7   Bryan Henderson adapted it to Netpbm in September 2001.  Bryan
8   added more of Wandel's code, from Jhead 1.9 dated December 2002 in
9   January 2003.
10 
11   An EXIF header is a JFIF APP1 marker.  It is generated by some
12   digital cameras and contains information about the circumstances of
13   the creation of the image (camera settings, etc.).
14 
15   The EXIF header uses the TIFF format, only it contains only tag
16   values and no actual image.
17 
18   Note that the image format called EXIF is simply JFIF with an EXIF
19   header, i.e. a subformat of JFIF.
20 
21   See the EXIF specs at http://exif.org (2001.09.01).
22 
23 --------------------------------------------------------------------------*/
24 #include "pm_config.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <math.h>
28 #include <string.h>
29 #include <time.h>
30 #include <errno.h>
31 #include <limits.h>
32 #include <ctype.h>
33 
34 #if MSVCRT
35     #include <sys/utime.h>
36 #else
37     #include <utime.h>
38     #include <sys/types.h>
39     #include <unistd.h>
40     #include <errno.h>
41 #endif
42 
43 #include "pm_c_util.h"
44 #include "pm.h"
45 #include "nstring.h"
46 
47 #include "exif.h"
48 
49 static const unsigned char * DirWithThumbnailPtrs;
50 static double FocalplaneXRes;
51 bool HaveXRes;
52 static double FocalplaneUnits;
53 static int ExifImageWidth;
54 
55 typedef struct {
56     unsigned short Tag;
57     const char * Desc;
58 } TagTable;
59 
60 
61 
62 /* Describes format descriptor */
63 static int const bytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
64 #define NUM_FORMATS 12
65 
66 #define FMT_BYTE       1
67 #define FMT_STRING     2
68 #define FMT_USHORT     3
69 #define FMT_ULONG      4
70 #define FMT_URATIONAL  5
71 #define FMT_SBYTE      6
72 #define FMT_UNDEFINED  7
73 #define FMT_SSHORT     8
74 #define FMT_SLONG      9
75 #define FMT_SRATIONAL 10
76 #define FMT_SINGLE    11
77 #define FMT_DOUBLE    12
78 
79 /* Describes tag values */
80 
81 #define TAG_EXIF_OFFSET       0x8769
82 #define TAG_INTEROP_OFFSET    0xa005
83 
84 #define TAG_MAKE              0x010F
85 #define TAG_MODEL             0x0110
86 
87 #define TAG_ORIENTATION       0x0112
88 
89 #define TAG_XRESOLUTION       0x011A
90 #define TAG_YRESOLUTION       0x011B
91 
92 #define TAG_EXPOSURETIME      0x829A
93 #define TAG_FNUMBER           0x829D
94 
95 #define TAG_SHUTTERSPEED      0x9201
96 #define TAG_APERTURE          0x9202
97 #define TAG_MAXAPERTURE       0x9205
98 #define TAG_FOCALLENGTH       0x920A
99 
100 #define TAG_DATETIME_ORIGINAL 0x9003
101 #define TAG_USERCOMMENT       0x9286
102 
103 #define TAG_SUBJECT_DISTANCE  0x9206
104 #define TAG_FLASH             0x9209
105 
106 #define TAG_FOCALPLANEXRES    0xa20E
107 #define TAG_FOCALPLANEUNITS   0xa210
108 #define TAG_EXIF_IMAGEWIDTH   0xA002
109 #define TAG_EXIF_IMAGELENGTH  0xA003
110 
111 /* the following is added 05-jan-2001 vcs */
112 #define TAG_EXPOSURE_BIAS     0x9204
113 #define TAG_WHITEBALANCE      0x9208
114 #define TAG_METERING_MODE     0x9207
115 #define TAG_EXPOSURE_PROGRAM  0x8822
116 #define TAG_ISO_EQUIVALENT    0x8827
117 #define TAG_COMPRESSION_LEVEL 0x9102
118 
119 #define TAG_THUMBNAIL_OFFSET  0x0201
120 #define TAG_THUMBNAIL_LENGTH  0x0202
121 
122 static TagTable const tagTable[] = {
123   {   0x100,   "ImageWidth"},
124   {   0x101,   "ImageLength"},
125   {   0x102,   "BitsPerSample"},
126   {   0x103,   "Compression"},
127   {   0x106,   "PhotometricInterpretation"},
128   {   0x10A,   "FillOrder"},
129   {   0x10D,   "DocumentName"},
130   {   0x10E,   "ImageDescription"},
131   {   0x10F,   "Make"},
132   {   0x110,   "Model"},
133   {   0x111,   "StripOffsets"},
134   {   0x112,   "Orientation"},
135   {   0x115,   "SamplesPerPixel"},
136   {   0x116,   "RowsPerStrip"},
137   {   0x117,   "StripByteCounts"},
138   {   0x11A,   "XResolution"},
139   {   0x11B,   "YResolution"},
140   {   0x11C,   "PlanarConfiguration"},
141   {   0x128,   "ResolutionUnit"},
142   {   0x12D,   "TransferFunction"},
143   {   0x131,   "Software"},
144   {   0x132,   "DateTime"},
145   {   0x13B,   "Artist"},
146   {   0x13E,   "WhitePoint"},
147   {   0x13F,   "PrimaryChromaticities"},
148   {   0x156,   "TransferRange"},
149   {   0x200,   "JPEGProc"},
150   {   0x201,   "ThumbnailOffset"},
151   {   0x202,   "ThumbnailLength"},
152   {   0x211,   "YCbCrCoefficients"},
153   {   0x212,   "YCbCrSubSampling"},
154   {   0x213,   "YCbCrPositioning"},
155   {   0x214,   "ReferenceBlackWhite"},
156   {   0x828D,  "CFARepeatPatternDim"},
157   {   0x828E,  "CFAPattern"},
158   {   0x828F,  "BatteryLevel"},
159   {   0x8298,  "Copyright"},
160   {   0x829A,  "ExposureTime"},
161   {   0x829D,  "FNumber"},
162   {   0x83BB,  "IPTC/NAA"},
163   {   0x8769,  "ExifOffset"},
164   {   0x8773,  "InterColorProfile"},
165   {   0x8822,  "ExposureProgram"},
166   {   0x8824,  "SpectralSensitivity"},
167   {   0x8825,  "GPSInfo"},
168   {   0x8827,  "ISOSpeedRatings"},
169   {   0x8828,  "OECF"},
170   {   0x9000,  "ExifVersion"},
171   {   0x9003,  "DateTimeOriginal"},
172   {   0x9004,  "DateTimeDigitized"},
173   {   0x9101,  "ComponentsConfiguration"},
174   {   0x9102,  "CompressedBitsPerPixel"},
175   {   0x9201,  "ShutterSpeedValue"},
176   {   0x9202,  "ApertureValue"},
177   {   0x9203,  "BrightnessValue"},
178   {   0x9204,  "ExposureBiasValue"},
179   {   0x9205,  "MaxApertureValue"},
180   {   0x9206,  "SubjectDistance"},
181   {   0x9207,  "MeteringMode"},
182   {   0x9208,  "LightSource"},
183   {   0x9209,  "Flash"},
184   {   0x920A,  "FocalLength"},
185   {   0x927C,  "MakerNote"},
186   {   0x9286,  "UserComment"},
187   {   0x9290,  "SubSecTime"},
188   {   0x9291,  "SubSecTimeOriginal"},
189   {   0x9292,  "SubSecTimeDigitized"},
190   {   0xA000,  "FlashPixVersion"},
191   {   0xA001,  "ColorSpace"},
192   {   0xA002,  "ExifImageWidth"},
193   {   0xA003,  "ExifImageLength"},
194   {   0xA005,  "InteroperabilityOffset"},
195   {   0xA20B,  "FlashEnergy"},                 /* 0x920B in TIFF/EP */
196   {   0xA20C,  "SpatialFrequencyResponse"},  /* 0x920C    -  - */
197   {   0xA20E,  "FocalPlaneXResolution"},     /* 0x920E    -  - */
198   {   0xA20F,  "FocalPlaneYResolution"},      /* 0x920F    -  - */
199   {   0xA210,  "FocalPlaneResolutionUnit"},  /* 0x9210    -  - */
200   {   0xA214,  "SubjectLocation"},             /* 0x9214    -  - */
201   {   0xA215,  "ExposureIndex"},            /* 0x9215    -  - */
202   {   0xA217,  "SensingMethod"},            /* 0x9217    -  - */
203   {   0xA300,  "FileSource"},
204   {   0xA301,  "SceneType"},
205   {      0, NULL}
206 } ;
207 
208 
209 
210 typedef enum { NORMAL, MOTOROLA } ByteOrder;
211 
212 
213 
214 static uint16_t
get16u(const void * const data,ByteOrder const byteOrder)215 get16u(const void * const data,
216        ByteOrder    const byteOrder) {
217 /*--------------------------------------------------------------------------
218    Convert a 16 bit unsigned value from file's native byte order
219 --------------------------------------------------------------------------*/
220     if (byteOrder == MOTOROLA){
221         return (((const unsigned char *)data)[0] << 8) |
222             ((const unsigned char *)data)[1];
223     }else{
224         return (((const unsigned char *)data)[1] << 8) |
225             ((const unsigned char *)data)[0];
226     }
227 }
228 
229 
230 
231 static int32_t
get32s(const void * const data,ByteOrder const byteOrder)232 get32s(const void * const data,
233        ByteOrder    const byteOrder) {
234 /*--------------------------------------------------------------------------
235    Convert a 32 bit signed value from file's native byte order
236 --------------------------------------------------------------------------*/
237     if (byteOrder == MOTOROLA){
238         return
239             (((const char *)data)[0] << 24) |
240             (((const unsigned char *)data)[1] << 16) |
241             (((const unsigned char *)data)[2] << 8 ) |
242             (((const unsigned char *)data)[3] << 0 );
243     } else {
244         return
245             (((const char *)data)[3] << 24) |
246             (((const unsigned char *)data)[2] << 16) |
247             (((const unsigned char *)data)[1] << 8 ) |
248             (((const unsigned char *)data)[0] << 0 );
249     }
250 }
251 
252 
253 
254 static uint32_t
get32u(const void * const data,ByteOrder const byteOrder)255 get32u(const void * const data,
256        ByteOrder    const byteOrder) {
257 /*--------------------------------------------------------------------------
258    Convert a 32 bit unsigned value from file's native byte order
259 --------------------------------------------------------------------------*/
260     return (uint32_t)get32s(data, byteOrder) & 0xffffffff;
261 }
262 
263 
264 
265 static void
printFormatNumber(FILE * const fileP,const void * const ValuePtr,int const Format,int const ByteCount,ByteOrder const byteOrder)266 printFormatNumber(FILE *       const fileP,
267                   const void * const ValuePtr,
268                   int          const Format,
269                   int          const ByteCount,
270                   ByteOrder    const byteOrder) {
271 /*--------------------------------------------------------------------------
272    Display a number as one of its many formats
273 --------------------------------------------------------------------------*/
274     switch(Format){
275     case FMT_SBYTE:
276     case FMT_BYTE:
277         fprintf(fileP, "%02x\n", *(unsigned char *)ValuePtr);
278         break;
279     case FMT_USHORT:
280         fprintf(fileP, "%d\n",get16u(ValuePtr, byteOrder));
281         break;
282     case FMT_ULONG:
283     case FMT_SLONG:
284         fprintf(fileP, "%d\n",get32s(ValuePtr, byteOrder));
285         break;
286     case FMT_SSHORT:
287         fprintf(fileP, "%hd\n",(signed short)get16u(ValuePtr, byteOrder));
288         break;
289     case FMT_URATIONAL:
290     case FMT_SRATIONAL:
291         fprintf(fileP, "%d/%d\n",get32s(ValuePtr, byteOrder),
292                 get32s(4+(char *)ValuePtr, byteOrder));
293         break;
294     case FMT_SINGLE:
295         fprintf(fileP, "%f\n",(double)*(float *)ValuePtr);
296         break;
297     case FMT_DOUBLE:
298         fprintf(fileP, "%f\n",*(double *)ValuePtr);
299         break;
300     default:
301         fprintf(fileP, "Unknown format %d:", Format);
302         {
303             unsigned int a;
304             for (a = 0; a < ByteCount && a < 16; ++a)
305                 printf("%02x", ((unsigned char *)ValuePtr)[a]);
306         }
307         fprintf(fileP, "\n");
308     }
309 }
310 
311 
312 
313 static double
convertAnyFormat(const void * const ValuePtr,int const Format,ByteOrder const byteOrder)314 convertAnyFormat(const void * const ValuePtr,
315                  int          const Format,
316                  ByteOrder    const byteOrder) {
317 /*--------------------------------------------------------------------------
318    Evaluate number, be it int, rational, or float from directory.
319 --------------------------------------------------------------------------*/
320     double Value;
321     Value = 0;
322 
323     switch(Format){
324     case FMT_SBYTE:
325         Value = *(signed char *)ValuePtr;
326         break;
327     case FMT_BYTE:
328         Value = *(unsigned char *)ValuePtr;
329         break;
330     case FMT_USHORT:
331         Value = get16u(ValuePtr, byteOrder);
332         break;
333     case FMT_ULONG:
334         Value = get32u(ValuePtr, byteOrder);
335         break;
336     case FMT_URATIONAL:
337     case FMT_SRATIONAL: {
338         int num, den;
339         num = get32s(ValuePtr, byteOrder);
340         den = get32s(4+(char *)ValuePtr, byteOrder);
341         Value = den == 0 ? 0 : (double)(num/den);
342     } break;
343     case FMT_SSHORT:
344         Value = (signed short)get16u(ValuePtr, byteOrder);
345         break;
346     case FMT_SLONG:
347         Value = get32s(ValuePtr, byteOrder);
348         break;
349 
350     /* Not sure if this is correct (never seen float used in Exif format) */
351     case FMT_SINGLE:
352         Value = (double)*(float *)ValuePtr;
353         break;
354     case FMT_DOUBLE:
355         Value = *(double *)ValuePtr;
356         break;
357     }
358     return Value;
359 }
360 
361 
362 
363 static void
traceTag(int const tag,int const format,const unsigned char * const valuePtr,unsigned int const byteCount,ByteOrder const byteOrder)364 traceTag(int                   const tag,
365          int                   const format,
366          const unsigned char * const valuePtr,
367          unsigned int          const byteCount,
368          ByteOrder             const byteOrder) {
369 
370     /* Show tag name */
371     unsigned int a;
372     bool found;
373     for (a = 0, found = false; !found; ++a){
374         if (tagTable[a].Tag == 0){
375             fprintf(stderr, "  Unknown Tag %04x Value = ", tag);
376             found = true;
377         }
378         if (tagTable[a].Tag == tag){
379             fprintf(stderr, "    %s = ",tagTable[a].Desc);
380             found = true;
381         }
382     }
383 
384     /* Show tag value. */
385     switch(format){
386 
387     case FMT_UNDEFINED:
388         /* Undefined is typically an ascii string. */
389 
390     case FMT_STRING: {
391         /* String arrays printed without function call
392            (different from int arrays)
393         */
394         bool noPrint;
395         printf("\"");
396         for (a = 0, noPrint = false; a < byteCount; ++a){
397             if (ISPRINT((valuePtr)[a])){
398                 fprintf(stderr, "%c", valuePtr[a]);
399                 noPrint = false;
400             } else {
401                 /* Avoiding indicating too many unprintable characters of
402                    proprietary bits of binary information this program may not
403                    know how to parse.
404                 */
405                 if (!noPrint){
406                     fprintf(stderr, "?");
407                     noPrint = true;
408                 }
409             }
410         }
411         fprintf(stderr, "\"\n");
412     } break;
413 
414     default:
415         /* Handle arrays of numbers later (will there ever be?)*/
416         printFormatNumber(stderr, valuePtr, format, byteCount, byteOrder);
417     }
418 }
419 
420 
421 
422 /* Forward declaration for recursion */
423 
424 static void
425 processExifDir(const unsigned char *  const ExifData,
426                unsigned int           const ExifLength,
427                unsigned int           const DirOffset,
428                exif_ImageInfo *       const imageInfoP,
429                ByteOrder              const byteOrder,
430                bool                   const wantTagTrace,
431                const unsigned char ** const LastExifRefdP);
432 
433 
434 static void
processDirEntry(const unsigned char * const dirEntry,const unsigned char * const exifData,unsigned int const exifLength,ByteOrder const byteOrder,bool const wantTagTrace,exif_ImageInfo * const imageInfoP,unsigned int * const thumbnailOffsetP,unsigned int * const thumbnailSizeP,bool * const haveThumbnailP,const unsigned char ** const lastExifRefdP)435 processDirEntry(const unsigned char *  const dirEntry,
436                 const unsigned char *  const exifData,
437                 unsigned int           const exifLength,
438                 ByteOrder              const byteOrder,
439                 bool                   const wantTagTrace,
440                 exif_ImageInfo *       const imageInfoP,
441                 unsigned int *         const thumbnailOffsetP,
442                 unsigned int *         const thumbnailSizeP,
443                 bool *                 const haveThumbnailP,
444                 const unsigned char ** const lastExifRefdP) {
445 
446     int const tag        = get16u(&dirEntry[0], byteOrder);
447     int const format     = get16u(&dirEntry[2], byteOrder);
448     int const components = get32u(&dirEntry[4], byteOrder);
449 
450     const unsigned char * valuePtr;
451         /* This actually can point to a variety of things; it must be cast to
452            other types when used.  But we use it as a byte-by-byte cursor, so
453            we declare it as a pointer to a generic byte here.
454         */
455     unsigned int byteCount;
456 
457     if ((format-1) >= NUM_FORMATS) {
458         /* (-1) catches illegal zero case as unsigned underflows
459            to positive large.
460         */
461         pm_message("Illegal number format %d for tag %04x", format, tag);
462         return;
463     }
464 
465     byteCount = components * bytesPerFormat[format];
466 
467     if (byteCount > 4){
468         unsigned const offsetVal = get32u(&dirEntry[8], byteOrder);
469         /* If its bigger than 4 bytes, the dir entry contains an offset.*/
470         if (offsetVal + byteCount > exifLength){
471             /* Bogus pointer offset and / or bytecount value */
472             pm_message("Illegal pointer offset value in EXIF "
473                        "for tag %04x.  "
474                        "Offset %d bytes %d ExifLen %d\n",
475                        tag, offsetVal, byteCount, exifLength);
476             return;
477         }
478         valuePtr = &exifData[offsetVal];
479     } else {
480         /* 4 bytes or less and value is in the dir entry itself */
481         valuePtr = &dirEntry[8];
482     }
483 
484     if (*lastExifRefdP < valuePtr + byteCount){
485         /* Keep track of last byte in the exif header that was actually
486            referenced.  That way, we know where the discardable thumbnail data
487            begins.
488         */
489         *lastExifRefdP = valuePtr + byteCount;
490     }
491 
492     if (wantTagTrace)
493         traceTag(tag, format, valuePtr, byteCount, byteOrder);
494 
495     *haveThumbnailP = (tag == TAG_THUMBNAIL_OFFSET);
496 
497     /* Extract useful components of tag */
498     switch (tag){
499 
500     case TAG_MAKE:
501         STRSCPY(imageInfoP->CameraMake, (const char*)valuePtr);
502         break;
503 
504     case TAG_MODEL:
505         STRSCPY(imageInfoP->CameraModel, (const char*)valuePtr);
506         break;
507 
508     case TAG_XRESOLUTION:
509         imageInfoP->XResolution =
510             convertAnyFormat(valuePtr, format, byteOrder);
511         break;
512 
513     case TAG_YRESOLUTION:
514         imageInfoP->YResolution =
515             convertAnyFormat(valuePtr, format, byteOrder);
516         break;
517 
518     case TAG_DATETIME_ORIGINAL:
519         STRSCPY(imageInfoP->DateTime, (const char*)valuePtr);
520         imageInfoP->DatePointer = (const char*)valuePtr;
521         break;
522 
523     case TAG_USERCOMMENT: {
524         /* Olympus has this padded with trailing spaces.  We stop the copy
525            where those start.
526         */
527         const char * const value = (const char *)valuePtr;
528 
529         unsigned int cursor;
530         unsigned int outCursor;
531         unsigned int end;
532 
533         for (end = byteCount; end > 0 && value[end] == ' '; --end);
534 
535         /* Skip "ASCII" if it is there */
536         if (end >= 5 && MEMEQ(value, "ASCII", 5))
537             cursor = 5;
538         else
539             cursor = 0;
540 
541         /* Skip consecutive blanks and NULs */
542 
543         for (;
544              cursor < byteCount &&
545                  (value[cursor] == '\0' || value[cursor] == ' ');
546              ++cursor);
547 
548         /* Copy the rest as the comment */
549 
550         for (outCursor = 0;
551              cursor < end && outCursor < MAX_COMMENT-1;
552              ++cursor)
553             imageInfoP->Comments[outCursor++] = value[cursor];
554 
555         imageInfoP->Comments[outCursor++] = '\0';
556     } break;
557 
558     case TAG_FNUMBER:
559         /* Simplest way of expressing aperture, so I trust it the most.
560            (overwrite previously computd value if there is one)
561         */
562         imageInfoP->ApertureFNumber =
563             (float)convertAnyFormat(valuePtr, format, byteOrder);
564         break;
565 
566     case TAG_APERTURE:
567     case TAG_MAXAPERTURE:
568         /* More relevant info always comes earlier, so only use this field if
569            we don't have appropriate aperture information yet.
570         */
571         if (imageInfoP->ApertureFNumber == 0){
572             imageInfoP->ApertureFNumber = (float)
573                 exp(convertAnyFormat(valuePtr, format, byteOrder)
574                     * log(2) * 0.5);
575         }
576         break;
577 
578     case TAG_FOCALLENGTH:
579         /* Nice digital cameras actually save the focal length
580            as a function of how farthey are zoomed in.
581         */
582 
583         imageInfoP->FocalLength =
584             (float)convertAnyFormat(valuePtr, format, byteOrder);
585         break;
586 
587     case TAG_SUBJECT_DISTANCE:
588         /* Inidcates the distacne the autofocus camera is focused to.
589            Tends to be less accurate as distance increases.
590         */
591         imageInfoP->Distance =
592             (float)convertAnyFormat(valuePtr, format, byteOrder);
593         break;
594 
595     case TAG_EXPOSURETIME:
596         /* Simplest way of expressing exposure time, so I
597            trust it most.  (overwrite previously computd value
598            if there is one)
599         */
600         imageInfoP->ExposureTime =
601             (float)convertAnyFormat(valuePtr, format, byteOrder);
602         break;
603 
604     case TAG_SHUTTERSPEED:
605         /* More complicated way of expressing exposure time,
606            so only use this value if we don't already have it
607            from somewhere else.
608         */
609         if (imageInfoP->ExposureTime == 0){
610             imageInfoP->ExposureTime = (float)
611                 (1/exp(convertAnyFormat(valuePtr, format, byteOrder)
612                        * log(2)));
613         }
614         break;
615 
616     case TAG_FLASH:
617         if ((int)convertAnyFormat(valuePtr, format, byteOrder) & 0x7){
618             imageInfoP->FlashUsed = TRUE;
619         }else{
620             imageInfoP->FlashUsed = FALSE;
621         }
622         break;
623 
624     case TAG_ORIENTATION:
625         imageInfoP->Orientation =
626             (int)convertAnyFormat(valuePtr, format, byteOrder);
627         if (imageInfoP->Orientation < 1 ||
628             imageInfoP->Orientation > 8){
629             pm_message("Undefined rotation value %d",
630                        imageInfoP->Orientation);
631             imageInfoP->Orientation = 0;
632         }
633         break;
634 
635     case TAG_EXIF_IMAGELENGTH:
636     case TAG_EXIF_IMAGEWIDTH:
637         /* Use largest of height and width to deal with images
638            that have been rotated to portrait format.
639         */
640         ExifImageWidth =
641             MIN(ExifImageWidth,
642                 (int)convertAnyFormat(valuePtr, format, byteOrder));
643         break;
644 
645     case TAG_FOCALPLANEXRES:
646         HaveXRes = TRUE;
647         FocalplaneXRes = convertAnyFormat(valuePtr, format, byteOrder);
648         break;
649 
650     case TAG_FOCALPLANEUNITS:
651         switch((int)convertAnyFormat(valuePtr, format, byteOrder)){
652         case 1: FocalplaneUnits = 25.4; break; /* 1 inch */
653         case 2:
654             /* According to the information I was using, 2
655                means meters.  But looking at the Cannon
656                powershot's files, inches is the only
657                sensible value.
658             */
659             FocalplaneUnits = 25.4;
660             break;
661 
662         case 3: FocalplaneUnits = 10;   break;  /* 1 centimeter*/
663         case 4: FocalplaneUnits = 1;    break;  /* 1 millimeter*/
664         case 5: FocalplaneUnits = .001; break;  /* 1 micrometer*/
665         }
666         break;
667 
668         /* Remaining cases contributed by: Volker C. Schoech
669            (schoech@gmx.de)
670         */
671 
672     case TAG_EXPOSURE_BIAS:
673         imageInfoP->ExposureBias =
674             (float) convertAnyFormat(valuePtr, format, byteOrder);
675         break;
676 
677     case TAG_WHITEBALANCE:
678         imageInfoP->Whitebalance =
679             (int)convertAnyFormat(valuePtr, format, byteOrder);
680         break;
681 
682     case TAG_METERING_MODE:
683         imageInfoP->MeteringMode =
684             (int)convertAnyFormat(valuePtr, format, byteOrder);
685         break;
686 
687     case TAG_EXPOSURE_PROGRAM:
688         imageInfoP->ExposureProgram =
689             (int)convertAnyFormat(valuePtr, format, byteOrder);
690         break;
691 
692     case TAG_ISO_EQUIVALENT:
693         imageInfoP->ISOequivalent =
694             (int)convertAnyFormat(valuePtr, format, byteOrder);
695         if ( imageInfoP->ISOequivalent < 50 )
696             imageInfoP->ISOequivalent *= 200;
697         break;
698 
699     case TAG_COMPRESSION_LEVEL:
700         imageInfoP->CompressionLevel =
701             (int)convertAnyFormat(valuePtr, format, byteOrder);
702         break;
703 
704     case TAG_THUMBNAIL_OFFSET:
705         *thumbnailOffsetP = (unsigned int)
706             convertAnyFormat(valuePtr, format, byteOrder);
707         break;
708 
709     case TAG_THUMBNAIL_LENGTH:
710         *thumbnailSizeP = (unsigned int)
711             convertAnyFormat(valuePtr, format, byteOrder);
712         break;
713 
714     case TAG_EXIF_OFFSET:
715     case TAG_INTEROP_OFFSET: {
716         unsigned int const subdirOffset = get32u(valuePtr, byteOrder);
717         if (subdirOffset >= exifLength)
718             pm_message("Illegal exif or interop offset "
719                        "directory link.  Offset is %u, "
720                        "but Exif data is only %u bytes.",
721                        subdirOffset, exifLength);
722         else
723             processExifDir(exifData, exifLength, subdirOffset,
724                            imageInfoP, byteOrder, wantTagTrace,
725                            lastExifRefdP);
726     } break;
727     }
728 }
729 
730 
731 
732 static void
processExifDir(const unsigned char * const exifData,unsigned int const exifLength,unsigned int const dirOffset,exif_ImageInfo * const imageInfoP,ByteOrder const byteOrder,bool const wantTagTrace,const unsigned char ** const lastExifRefdP)733 processExifDir(const unsigned char *  const exifData,
734                unsigned int           const exifLength,
735                unsigned int           const dirOffset,
736                exif_ImageInfo *       const imageInfoP,
737                ByteOrder              const byteOrder,
738                bool                   const wantTagTrace,
739                const unsigned char ** const lastExifRefdP) {
740 /*--------------------------------------------------------------------------
741    Process one of the nested EXIF directories.
742 --------------------------------------------------------------------------*/
743     const unsigned char * const dirStart = exifData + dirOffset;
744     unsigned int const numDirEntries = get16u(&dirStart[0], byteOrder);
745     unsigned int de;
746     bool haveThumbnail;
747     unsigned int thumbnailOffset;
748     unsigned int thumbnailSize;
749 
750     #define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
751 
752     {
753         const unsigned char * const dirEnd =
754             DIR_ENTRY_ADDR(dirStart, numDirEntries);
755         if (dirEnd + 4 > (exifData + exifLength)){
756             if (dirEnd + 2 == exifData + exifLength ||
757                 dirEnd == exifData + exifLength){
758                 /* Version 1.3 of jhead would truncate a bit too much.
759                    This also caught later on as well.
760                 */
761             }else{
762                 /* Note: Files that had thumbnails trimmed with jhead
763                    1.3 or earlier might trigger this.
764                 */
765                 pm_message("Illegal directory entry size");
766                 return;
767             }
768         }
769         *lastExifRefdP = MAX(*lastExifRefdP, dirEnd);
770     }
771 
772     if (wantTagTrace)
773         pm_message("Directory with %d entries", numDirEntries);
774 
775     haveThumbnail   = false;  /* initial value */
776     thumbnailOffset = 0;      /* initial value */
777     thumbnailSize   = 0;      /* initial value */
778 
779     for (de = 0; de < numDirEntries; ++de)
780         processDirEntry(DIR_ENTRY_ADDR(dirStart, de), exifData, exifLength,
781                         byteOrder, wantTagTrace, imageInfoP,
782                         &thumbnailOffset, &thumbnailSize, &haveThumbnail,
783                         lastExifRefdP);
784 
785     if (haveThumbnail)
786         DirWithThumbnailPtrs = dirStart;
787 
788     {
789         /* In addition to linking to subdirectories via exif tags,
790            there's also a potential link to another directory at the end
791            of each directory.  This has got to be the result of a
792            committee!
793         */
794         if (DIR_ENTRY_ADDR(dirStart, numDirEntries) + 4 <=
795             exifData + exifLength){
796             unsigned int const subdirOffset =
797                 get32u(dirStart + 2 + 12*numDirEntries, byteOrder);
798             if (subdirOffset){
799                 const unsigned char * const subdirStart =
800                     exifData + subdirOffset;
801                 if (subdirStart > exifData + exifLength){
802                     if (subdirStart < exifData + exifLength + 20){
803                         /* Jhead 1.3 or earlier would crop the whole directory!
804                            As Jhead produces this form of format incorrectness,
805                            I'll just let it pass silently.
806                         */
807                         if (wantTagTrace)
808                             printf("Thumbnail removed with "
809                                    "Jhead 1.3 or earlier\n");
810                     }else{
811                         pm_message("Illegal subdirectory link");
812                     }
813                 }else{
814                     if (subdirOffset <= exifLength)
815                         processExifDir(exifData, exifLength, subdirOffset,
816                                        imageInfoP, byteOrder, wantTagTrace,
817                                        lastExifRefdP);
818                 }
819             }
820         }else{
821             /* The exif header ends before the last next directory pointer. */
822         }
823     }
824 
825     if (thumbnailSize && thumbnailOffset){
826         if (thumbnailSize + thumbnailOffset <= exifLength){
827             /* The thumbnail pointer appears to be valid.  Store it. */
828             imageInfoP->ThumbnailPointer = exifData + thumbnailOffset;
829             imageInfoP->ThumbnailSize = thumbnailSize;
830 
831             if (wantTagTrace){
832                 fprintf(stderr, "Thumbnail size: %u bytes\n", thumbnailSize);
833             }
834         }
835     }
836 }
837 
838 
839 
840 void
exif_parse(const unsigned char * const exifData,unsigned int const length,exif_ImageInfo * const imageInfoP,bool const wantTagTrace,const char ** const errorP)841 exif_parse(const unsigned char * const exifData,
842            unsigned int          const length,
843            exif_ImageInfo *      const imageInfoP,
844            bool                  const wantTagTrace,
845            const char **         const errorP) {
846 /*--------------------------------------------------------------------------
847   Interpret an EXIF APP1 marker
848 
849   'exifData' is the actual Exif data; it does not include the
850   "Exif" identifier and length field that often prefix Exif data.
851 
852   'length' is the length of the Exif section.
853 --------------------------------------------------------------------------*/
854     ByteOrder byteOrder;
855     int FirstOffset;
856     const unsigned char * lastExifRefd;
857 
858     *errorP = NULL;  /* initial assumption */
859 
860     if (wantTagTrace)
861         fprintf(stderr, "Exif header %d bytes long\n",length);
862 
863     if (MEMEQ(exifData + 0, "II" , 2)) {
864         if (wantTagTrace)
865             fprintf(stderr, "Exif header in Intel order\n");
866         byteOrder = NORMAL;
867     } else {
868         if (MEMEQ(exifData + 0, "MM", 2)) {
869             if (wantTagTrace)
870                 fprintf(stderr, "Exif header in Motorola order\n");
871             byteOrder = MOTOROLA;
872         } else {
873             pm_asprintf(errorP, "Invalid alignment marker in Exif "
874                         "data.  First two bytes are '%c%c' (0x%02x%02x) "
875                         "instead of 'II' or 'MM'.",
876                         exifData[0], exifData[1], exifData[0], exifData[1]);
877         }
878     }
879     if (!*errorP) {
880         unsigned short const start = get16u(exifData + 2, byteOrder);
881         /* Check the next value for correctness. */
882         if (start != 0x002a){
883             pm_asprintf(errorP, "Invalid Exif header start.  "
884                         "two bytes after the alignment marker "
885                         "should be 0x002a, but is 0x%04x",
886                         start);
887         }
888     }
889     if (!*errorP) {
890         FirstOffset = get32u(exifData + 4, byteOrder);
891         if (FirstOffset < 8 || FirstOffset > 16){
892             /* I used to ensure this was set to 8 (website I used
893                indicated its 8) but PENTAX Optio 230 has it set
894                differently, and uses it as offset. (Sept 11 2002)
895                 */
896             pm_message("Suspicious offset of first IFD value in Exif header");
897         }
898 
899         imageInfoP->Comments[0] = '\0';  /* Initial value - null string */
900 
901         HaveXRes = FALSE;  /* Initial assumption */
902         FocalplaneUnits = 0;
903         ExifImageWidth = 0;
904 
905         lastExifRefd = exifData;
906         DirWithThumbnailPtrs = NULL;
907 
908         processExifDir(exifData, length, FirstOffset,
909                        imageInfoP, byteOrder, wantTagTrace, &lastExifRefd);
910 
911         /* Compute the CCD width, in millimeters. */
912         if (HaveXRes){
913             imageInfoP->HaveCCDWidth = 1;
914             imageInfoP->CCDWidth =
915                     (float)(ExifImageWidth * FocalplaneUnits / FocalplaneXRes);
916         } else
917             imageInfoP->HaveCCDWidth = 0;
918 
919         if (wantTagTrace){
920             fprintf(stderr,
921                     "Non-settings part of Exif header: %lu bytes\n",
922                     (unsigned long)(exifData + length - lastExifRefd));
923         }
924     }
925 }
926 
927 
928 
929 void
exif_showImageInfo(const exif_ImageInfo * const imageInfoP,FILE * const fileP)930 exif_showImageInfo(const exif_ImageInfo * const imageInfoP,
931                    FILE *                 const fileP) {
932 /*--------------------------------------------------------------------------
933    Show the collected image info, displaying camera F-stop and shutter
934    speed in a consistent and legible fashion.
935 --------------------------------------------------------------------------*/
936     if (imageInfoP->CameraMake[0]) {
937         fprintf(fileP, "Camera make  : %s\n", imageInfoP->CameraMake);
938         fprintf(fileP, "Camera model : %s\n", imageInfoP->CameraModel);
939     }
940     if (imageInfoP->DateTime[0])
941         fprintf(fileP, "Date/Time    : %s\n", imageInfoP->DateTime);
942 
943     fprintf(fileP, "Resolution   : %f x %f\n",
944             imageInfoP->XResolution, imageInfoP->YResolution);
945 
946     if (imageInfoP->Orientation > 1) {
947 
948         /* Only print orientation if one was supplied, and if its not
949            1 (normal orientation)
950 
951            1 - The 0th row is at the visual top of the image
952                and the 0th column is the visual left-hand side.
953            2 - The 0th row is at the visual top of the image
954                and the 0th column is the visual right-hand side.
955            3 - The 0th row is at the visual bottom of the image
956                and the 0th column is the visual right-hand side.
957            4 - The 0th row is at the visual bottom of the image
958                and the 0th column is the visual left-hand side.
959            5 - The 0th row is the visual left-hand side of of the image
960                and the 0th column is the visual top.
961            6 - The 0th row is the visual right-hand side of of the image
962                and the 0th column is the visual top.
963            7 - The 0th row is the visual right-hand side of of the image
964                and the 0th column is the visual bottom.
965            8 - The 0th row is the visual left-hand side of of the image
966                and the 0th column is the visual bottom.
967 
968            Note: The descriptions here are the same as the name of the
969            command line option to pass to jpegtran to right the image
970         */
971         static const char * OrientTab[9] = {
972             "Undefined",
973             "Normal",           /* 1 */
974             "flip horizontal",  /* left right reversed mirror */
975             "rotate 180",       /* 3 */
976             "flip vertical",    /* upside down mirror */
977             "transpose",    /* Flipped about top-left <--> bottom-right axis.*/
978             "rotate 90",        /* rotate 90 cw to right it. */
979             "transverse",   /* flipped about top-right <--> bottom-left axis */
980             "rotate 270",       /* rotate 270 to right it. */
981         };
982 
983         fprintf(fileP, "Orientation  : %s\n",
984                 OrientTab[imageInfoP->Orientation]);
985     }
986 
987     if (imageInfoP->IsColor == 0)
988         fprintf(fileP, "Color/bw     : Black and white\n");
989 
990     if (imageInfoP->FlashUsed >= 0)
991         fprintf(fileP, "Flash used   : %s\n",
992                 imageInfoP->FlashUsed ? "Yes" :"No");
993 
994     if (imageInfoP->FocalLength) {
995         fprintf(fileP, "Focal length : %4.1fmm",
996                 (double)imageInfoP->FocalLength);
997         if (imageInfoP->HaveCCDWidth){
998             fprintf(fileP, "  (35mm equivalent: %dmm)",
999                     (int)
1000                     (imageInfoP->FocalLength/imageInfoP->CCDWidth*36 + 0.5));
1001         }
1002         fprintf(fileP, "\n");
1003     }
1004 
1005     if (imageInfoP->HaveCCDWidth)
1006         fprintf(fileP, "CCD width    : %2.4fmm\n",
1007                 (double)imageInfoP->CCDWidth);
1008 
1009     if (imageInfoP->ExposureTime) {
1010         if (imageInfoP->ExposureTime < 0.010){
1011             fprintf(fileP,
1012                     "Exposure time: %6.4f s ",
1013                     (double)imageInfoP->ExposureTime);
1014         }else{
1015             fprintf(fileP,
1016                     "Exposure time: %5.3f s ",
1017                     (double)imageInfoP->ExposureTime);
1018         }
1019         if (imageInfoP->ExposureTime <= 0.5){
1020             fprintf(fileP, " (1/%d)",(int)(0.5 + 1/imageInfoP->ExposureTime));
1021         }
1022         fprintf(fileP, "\n");
1023     }
1024     if (imageInfoP->ApertureFNumber){
1025         fprintf(fileP, "Aperture     : f/%3.1f\n",
1026                 (double)imageInfoP->ApertureFNumber);
1027     }
1028     if (imageInfoP->Distance){
1029         if (imageInfoP->Distance < 0){
1030             fprintf(fileP, "Focus dist.  : Infinite\n");
1031         }else{
1032             fprintf(fileP, "Focus dist.  :%5.2fm\n",
1033                     (double)imageInfoP->Distance);
1034         }
1035     }
1036 
1037     if (imageInfoP->ISOequivalent){ /* 05-jan-2001 vcs */
1038         fprintf(fileP, "ISO equiv.   : %2d\n",(int)imageInfoP->ISOequivalent);
1039     }
1040     if (imageInfoP->ExposureBias){ /* 05-jan-2001 vcs */
1041         fprintf(fileP, "Exposure bias:%4.2f\n",
1042                 (double)imageInfoP->ExposureBias);
1043     }
1044 
1045     if (imageInfoP->Whitebalance){ /* 05-jan-2001 vcs */
1046         switch(imageInfoP->Whitebalance) {
1047         case 1:
1048             fprintf(fileP, "Whitebalance : sunny\n");
1049             break;
1050         case 2:
1051             fprintf(fileP, "Whitebalance : fluorescent\n");
1052             break;
1053         case 3:
1054             fprintf(fileP, "Whitebalance : incandescent\n");
1055             break;
1056         default:
1057             fprintf(fileP, "Whitebalance : cloudy\n");
1058         }
1059     }
1060     if (imageInfoP->MeteringMode){ /* 05-jan-2001 vcs */
1061         switch(imageInfoP->MeteringMode) {
1062         case 2:
1063             fprintf(fileP, "Metering Mode: center weight\n");
1064             break;
1065         case 3:
1066             fprintf(fileP, "Metering Mode: spot\n");
1067             break;
1068         case 5:
1069             fprintf(fileP, "Metering Mode: matrix\n");
1070             break;
1071         }
1072     }
1073     if (imageInfoP->ExposureProgram){ /* 05-jan-2001 vcs */
1074         switch(imageInfoP->ExposureProgram) {
1075         case 2:
1076             fprintf(fileP, "Exposure     : program (auto)\n");
1077             break;
1078         case 3:
1079             fprintf(fileP, "Exposure     : aperture priority (semi-auto)\n");
1080             break;
1081         case 4:
1082             fprintf(fileP, "Exposure     : shutter priority (semi-auto)\n");
1083             break;
1084         }
1085     }
1086     if (imageInfoP->CompressionLevel){ /* 05-jan-2001 vcs */
1087         switch(imageInfoP->CompressionLevel) {
1088         case 1:
1089             fprintf(fileP, "Jpeg Quality  : basic\n");
1090             break;
1091         case 2:
1092             fprintf(fileP, "Jpeg Quality  : normal\n");
1093             break;
1094         case 4:
1095             fprintf(fileP, "Jpeg Quality  : fine\n");
1096             break;
1097        }
1098     }
1099 
1100     /* Print the comment. Print 'Comment:' for each new line of comment. */
1101     if (imageInfoP->Comments[0]) {
1102         unsigned int a;
1103 
1104         fprintf(fileP, "Comment      : ");
1105 
1106         for (a = 0; a < MAX_COMMENT && imageInfoP->Comments[a]; ++a) {
1107             char const c = imageInfoP->Comments[a];
1108             if (c == '\n'){
1109                 /* Do not start a new line if the string ends with a cr */
1110                 if (imageInfoP->Comments[a+1] != '\0')
1111                     fprintf(fileP, "\nComment      : ");
1112                 else
1113                     fprintf(fileP, "\n");
1114             } else
1115                 putc(c, fileP);
1116         }
1117         fprintf(fileP, "\n");
1118     }
1119 
1120     fprintf(fileP, "\n");
1121 }
1122 
1123 
1124