1 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2 /*          EXIFPROBE - TIFF/JPEG/EXIF image file probe               */
3 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
4 /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved.   */
5 /*                                                                    */
6 /* See the file LICENSE.EXIFPROBE for terms of use.                   */
7 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
8 
9 #ifndef lint
10 static char *ModuleId = "@(#) $Id: maker_olympus.c,v 1.25 2005/07/24 22:56:26 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Olympus camera maker-specific routines                             */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* Most of the information coded here is due to TsuruZoh Tachibanaya  */
17 /* at:                                                                */
18 /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html   */
19 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
20 /* April, 2005:                                                       */
21 /* Much of the new information for later models is taken from         */
22 /* information provided by a Phil Harvey (author of 'exiftool') at:   */
23 /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html   */
24 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include "defs.h"
30 #include "datadefs.h"
31 #include "maker_datadefs.h"
32 #include "summary.h"
33 #include "maker.h"
34 #include "misc.h"
35 #include "tags.h"
36 #include "extern.h"
37 #include "maker_extern.h"
38 
39 extern struct camera_id olympus_model_id[];
40 
41 /* Find the identifying number assigned to known Olympus camera       */
42 /* models. This number is used to dispatch print and interpret        */
43 /* routines approopriate to the current image.                        */
44 
45 int
olympus_model_number(char * model,char * software)46 olympus_model_number(char *model,char *software)
47 {
48     struct camera_id *model_id;
49     int number = NO_MODEL;
50 
51     for(model_id = &olympus_model_id[0]; model_id && model_id->name; ++model_id)
52     {
53         if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
54         {
55             number = model_id->id;
56             setnoteversion(model_id->noteversion);
57             setnotetagset(model_id->notetagset);    /* info only      */
58             break;
59         }
60     }
61     return(number);
62 }
63 
64 /* Dispatch a print routine based upon model                          */
65 
66 void
print_olympus_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)67 print_olympus_makervalue(struct ifd_entry *entry_ptr,int make, int model,
68                     char *prefix)
69 {
70     int noteversion = 0;
71 
72     noteversion = getnoteversion();
73 
74     if(entry_ptr && (PRINT_VALUE))
75     {
76         switch(noteversion)
77         {
78             case 1:
79                 print_olympus1_makervalue(entry_ptr,make,model,PREFIX);
80                 olympus1_interpret_value(entry_ptr);
81                 break;
82             default:
83                 print_value(entry_ptr,PREFIX);
84                 break;
85         }
86     }
87 }
88 
89 /* Model-specific print routine for Olympus cameras. This routine is  */
90 /* responsible for picking off any direct entry tags which are        */
91 /* peculiar and will not be handled properly by print_value()         */
92 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
93 /* there are no such entries, this function simply calls              */
94 /* print_value().                                                     */
95 
96 void
print_olympus1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)97 print_olympus1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
98                     char *prefix)
99 {
100     if(entry_ptr)
101     {
102         switch(entry_ptr->tag)
103         {
104             default:
105                 print_value(entry_ptr,PREFIX);
106                 break;
107         }
108     }
109 }
110 
111 /* Dispatch a routine to decode and print offset values for Olympus   */
112 /* cameras.                                                           */
113 void
print_olympus_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)114 print_olympus_offset_makervalue(FILE *inptr,unsigned short byteorder,
115     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
116     struct image_summary *summary_entry,char *parent_name,char*prefix,
117     int indent,int make,int model,int at_offset)
118 {
119     int noteversion = 0;
120 
121     noteversion = getnoteversion();
122 
123     if(entry_ptr)
124     {
125         switch(noteversion)
126         {
127             case 1:
128                 olympus1_offset_makervalue(inptr,byteorder,entry_ptr,
129                                             fileoffset_base,summary_entry,
130                                             parent_name,prefix,indent,
131                                             make,model,at_offset);
132                 olympus1_interpret_offset_makervalue(inptr,byteorder,entry_ptr,
133                                             fileoffset_base);
134                 break;
135             default:
136                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
137                                         fileoffset_base,parent_name,prefix,indent,
138                                         make,model,at_offset);
139                 break;
140         }
141     }
142 }
143 
144 /* Model-specific routine to print UNDEFINED values found at offsets  */
145 /* in OLYMPUS makernotes.                                             */
146 
147 void
olympus1_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)148 olympus1_offset_makervalue(FILE *inptr,unsigned short byteorder,
149     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
150     struct image_summary *summary_entry,char *parent_name,char*prefix,
151     int indent,int make,int model,int at_offset)
152 {
153     unsigned long value_offset,max_offset;
154     unsigned long dumplength;
155     unsigned long count;
156     unsigned short marker;
157     char *nameoftag;
158     char *fulldirname = CNULL;
159     int status = 0;
160     int chpr = 0;
161 
162     if(entry_ptr)
163     {
164         nameoftag = maker_tagname(entry_ptr->tag,make,model);
165         if((PRINT_LONGNAMES))
166         {
167             fulldirname = splice(parent_name,".",nameoftag);
168             nameoftag = fulldirname;
169         }
170         value_offset = fileoffset_base + entry_ptr->value;
171         count = entry_ptr->count;
172         switch(entry_ptr->tag)
173         {
174             case 0x0209:    /* CameraId                               */
175                 if(at_offset)
176                 {
177                     print_tag_address(ENTRY,value_offset,indent,prefix);
178                     print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model);
179                 }
180                 if((PRINT_VALUE))
181                     print_ascii(inptr,entry_ptr->count,value_offset);
182                 break;
183             case 0x0100: /* JPEG Thumbnail in TIFF MakerNote          */
184                 if(at_offset && (PRINT_SECTION))
185                 {
186                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
187                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
188                     chpr += printf(" length %lu",count);
189                 }
190                 else if(!at_offset && (PRINT_VALUE))
191                 {
192                     if(!(PRINT_OFFSET))
193                         chpr += printf("@%lu:%-9lu",value_offset,entry_ptr->count);
194                     else
195                         chpr += printf(":%-9lu", entry_ptr->count);
196                     if(!(PRINT_VALUE_AT_OFFSET))
197                         chpr += printf(" # UNDEFINED");
198                 }
199                 if((PRINT_SECTION) || (PRINT_SEGMENT))
200                     chpr = newline(chpr);
201                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
202                 setcharsprinted(chpr);
203                 chpr = 0;
204                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
205                                     count,summary_entry,fulldirname,
206                                     prefix,indent+SMALLINDENT);
207                 if(at_offset)
208                 {
209                     if((PRINT_SECTION))
210                     {
211                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
212                             chpr = newline(chpr);
213                         jpeg_status(status);
214                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
215                                                     indent,"-");
216                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
217                         if((PRINT_ENTRY) && !(PRINT_VALUE))
218                             chpr = newline(chpr);
219                     }
220                 }
221                 print_jpeg_status();
222                 if(marker && summary_entry)
223                 {
224                     /* The new one is on the end of the chain         */
225                     if((summary_entry = last_summary_entry(summary_entry)))
226                     {
227                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
228                         summary_entry->datatype = MAKER_IFD;
229                         summary_entry->subfiletype = THUMBNAIL_TYPE;
230                     }
231                 }
232                 /* make certain we're at the end                      */
233                 clearerr(inptr);
234                 fseek(inptr,value_offset + count,0);
235                 break;
236             case 0x0f00: /* Data                                      */
237                 if(at_offset && (PRINT_ENTRY))
238                 {
239                     print_tag_address(ENTRY,value_offset,indent,prefix);
240                     print_makertagid(entry_ptr,MAKERTAGWIDTH," : ",make,model);
241                     chpr += printf("length %-9lu # UNDEFINED", count);
242                 }
243                 else if(!at_offset && (PRINT_VALUE))
244                 {
245                     if(!(PRINT_OFFSET))
246                         chpr += printf("@%lu:%-9lu",value_offset,entry_ptr->count);
247                     else
248                         chpr += printf(":%-9lu", entry_ptr->count);
249                     if(!(PRINT_VALUE_AT_OFFSET))
250                         chpr += printf(" # UNDEFINED");
251                 }
252                 if(Max_undefined == 0)
253                 {
254                     if(chpr)
255                         printred(" (not dumped, use -U)");
256                 }
257                 else
258                 {
259                     if((Max_undefined == DUMPALL) || (Max_undefined > count))
260                         dumplength = count;
261                     else
262                         dumplength = Max_undefined;
263                     chpr = newline(chpr);
264                     hexdump(inptr,value_offset,count,dumplength,12,
265                                 indent,SUBINDENT);
266                     chpr = newline(1);
267                 }
268                 /* make certain we're at the end                      */
269                 fseek(inptr,value_offset + count,0);
270                 break;
271             case 0x2010:    /* Private IFD's all                      */
272             case 0x2020:
273             case 0x2030:
274             case 0x2040:
275             case 0x2050:
276                 if(!at_offset && (PRINT_VALUE))
277                 {
278                     if(!(PRINT_OFFSET))
279                         chpr += printf("@%lu",value_offset);
280                 }
281                 chpr = newline(chpr);
282                 max_offset = entry_ptr->value + fileoffset_base + entry_ptr->count;
283                 max_offset = process_private_ifd(inptr,byteorder,entry_ptr->value,
284                                         fileoffset_base,max_offset,entry_ptr->tag,
285                                         summary_entry,nameoftag,prefix,
286                                         make,model,indent);
287                 break;
288             default:
289                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
290                                         fileoffset_base,fulldirname,prefix,indent,
291                                         make,model,at_offset);
292                 break;
293         }
294         if(fulldirname)
295             free(fulldirname);
296     }
297     setcharsprinted(chpr);
298 }
299 
300 /* Olympus-specific tagnames for makernotes.                          */
301 
302 /* The tagname routine is the first place in the code path which      */
303 /* requires knowledge of the note version. If the version is not      */
304 /* given in the model table (e.g. the model is unknown), then switch  */
305 /* code in find_maker_scheme() should have set it. This routine       */
306 /* repeats the check for non-zero noteversion and is prepared to set  */
307 /* the noteversion first time through, but should never need to do    */
308 /* so. Noteversion should always be non-zero; it should be set to -1  */
309 /* if generic processing is required.                                 */
310 
311 char *
maker_olympus_tagname(unsigned short tag,int model)312 maker_olympus_tagname(unsigned short tag,int model)
313 {
314     char *tagname = CNULL;
315     int noteversion = 0;
316 
317     if((noteversion = getnoteversion()) == 0)
318     {
319         /* Need more model samples before it is safe to assume a      */
320         /* default                                                    */
321         noteversion = 1;
322         setnoteversion(1);
323     }
324 
325     /* Check specific models first                                    */
326     switch(noteversion)
327     {
328         case 1:
329             tagname = maker_olympus1_tagname(tag,model);
330             break;
331         default:
332             break;
333     }
334     return(tagname);
335 }
336 
337 char *
maker_olympus1_tagname(unsigned short tag,int model)338 maker_olympus1_tagname(unsigned short tag,int model)
339 {
340     char *tagname = CNULL;
341 
342     switch(tag)
343     {
344         case 0x0100: tagname = "JpegThumbnail"; break;
345         case 0x0200: tagname = "SpecialMode"; break;
346         case 0x0201: tagname = "CompressionMode"; break; /* "Quality"? */
347         case 0x0202: tagname = "Macro"; break;
348         case 0x0203: tagname = "BWMode"; break;
349         case 0x0204: tagname = "DigitalZoom"; break;
350         case 0x0205: tagname = "FocalplaneDiagonal"; break;
351         case 0x0207: tagname = "SoftwareRelease"; break;
352         case 0x0208: tagname = "PictureInfo"; break;
353         case 0x0209: tagname = "CameraID"; break;
354         case 0x020b: tagname = "ImageWidth"; break; /* ? */
355         case 0x020c: tagname = "ImageHeight"; break; /* ? */
356         case 0x0f00: tagname = "Data"; break;
357 
358 
359         case 0x0300: tagname = "PrecaptureFrames"; break;
360         case 0x0302: tagname = "OneTouchWB"; break;
361 
362 
363         case 0x1004: tagname = "FlashMode"; break;
364         case 0x1005: tagname = "FlashDevice"; break;
365         case 0x1006: tagname = "Bracket"; break;
366         case 0x100b: tagname = "FocusMode"; break;
367         case 0x100c: tagname = "FocusDistance"; break;
368         case 0x100d: tagname = "Zoom"; break;
369         case 0x100e: tagname = "MacroFocus"; break;
370         case 0x100f: tagname = "SharpnessFactor"; break;
371         case 0x1011: tagname = "ColorMatrix"; break;
372         case 0x1012: tagname = "BlackLevel"; break;
373         case 0x1015: tagname = "WhiteBalance"; break;
374         case 0x1017: tagname = "RedBalance"; break;
375         case 0x1018: tagname = "BlueBalance"; break;
376         case 0x101a: tagname = "SerialNumber"; break;
377         case 0x1023: tagname = "FlashBias"; break;
378         case 0x1029: tagname = "Contrast"; break;
379         case 0x102a: tagname = "SharpnessFactor"; break;
380         case 0x102b: tagname = "ColorControl"; break;
381         case 0x102c: tagname = "ValidBits"; break;
382         case 0x102d: tagname = "CoringFilter"; break;
383         case 0x102e: tagname = "ImageWidth"; break;
384         case 0x102f: tagname = "ImageHeight"; break;
385         case 0x1034: tagname = "CompressionRatio"; break;
386         case 0x1035: tagname = "PreviewImageValid"; break;
387         case 0x1036: tagname = "PreviewImageOffset"; break;
388         case 0x1037: tagname = "PreviewImageLength"; break;
389 
390         case 0x2010: tagname = "Equipment"; break; /* IFD */
391         case 0x2020: tagname = "CameraSettings"; break; /* IFD */
392         case 0x2030: tagname = "RawDevelopment"; break; /* IFD */
393         case 0x2040: tagname = "ImageProcessing"; break; /* IFD */
394         case 0x2050: tagname = "FocusInfo"; break; /* IFD */
395         default: break;
396     }
397     setnotetagset(1);
398     return(tagname);
399 }
400 
401 
402 void
olympus1_interpret_value(struct ifd_entry * entry_ptr)403 olympus1_interpret_value(struct ifd_entry *entry_ptr)
404 {
405     int chpr = 0;
406 
407     if(entry_ptr && (PRINT_VALUE))
408     {
409         switch(entry_ptr->tag)
410         {
411             case 0x0201:    /* Compression Mode */
412                 print_startvalue();
413                 /* This appears to report "compression" only, while the   */
414                 /* camera's "quality" setting combines compression and    */
415                 /* image size in incomprehensible ways.                   */
416                 switch(entry_ptr->value)
417                 {
418                     case 1: chpr += printf("SQ"); break;
419                     case 2: chpr += printf("HQ"); break;
420                     case 3: chpr += printf("SHQ"); break;
421                     case 4: chpr += printf("RAW1"); break;
422                     case 6: chpr += printf("RAW2"); break;
423                     case 33: chpr += printf("not compressed"); break; /* TIFF  */
424                     case 34: /* not sure about this one ###%%%         */
425                              chpr += printf("not compressed");
426                              break;
427                     default: printred("undefined"); break;
428                 }
429                 print_endvalue();
430                 break;
431             case 0x0202:    /* Macro */
432                 print_startvalue();
433                 switch(entry_ptr->value)
434                 {
435                     case 0: chpr += printf("Normal"); break;
436                     case 1: chpr += printf("Macro"); break;
437                     case 2: chpr += printf("View"); break;
438                     default: printred("undefined"); break;
439                 }
440                 print_endvalue();
441                 break;
442             default:
443                 break;
444         }
445     }
446     setcharsprinted(chpr);
447 }
448 
449 void
olympus1_interpret_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)450 olympus1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder,
451                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
452 {
453     unsigned long offset,value;
454     int chpr = 0;
455 
456     if((entry_ptr) && (PRINT_VALUE))
457     {
458         offset = entry_ptr->value + fileoffset_base;
459         switch(entry_ptr->tag)
460         {
461             case 0x0200:    /* SpecialMode                               */
462                 value = read_ulong(inptr,byteorder,offset);
463                 print_startvalue();
464                 switch(value)
465                 {
466                     case 0: chpr += printf("Normal"); break;
467                     case 1: chpr += printf("Unkown"); break;
468                     case 2: chpr += printf("Fast"); break;
469                     case 3: chpr += printf("Panorama,");
470                             value = read_ulong(inptr,byteorder,HERE);
471                             chpr += printf("#%lu,",value);
472                             value = read_ulong(inptr,byteorder,HERE);
473                             switch(value)
474                             {
475                                 case 1: chpr += printf(" Left to Right"); break;
476                                 case 2: chpr += printf(" Right to Left"); break;
477                                 case 3: chpr += printf(" Bottom to Top"); break;
478                                 case 4: chpr += printf(" Top to Bottom"); break;
479                                 default: printred(" undefined"); break;
480                             }
481                             break;
482                     default: printred("undefined"); break;
483                 }
484                 print_endvalue();
485                 break;
486             default:
487                 break;
488         }
489     }
490     setcharsprinted(chpr);
491 }
492 
493 /* ================== OLYMPUS SUBIFD ========================         */
494 
495 char *
olympus_private_tagname(unsigned short tag,unsigned short subifd_ident)496 olympus_private_tagname(unsigned short tag,unsigned short subifd_ident)
497 {
498     char *tagname = CNULL;
499 
500     switch(subifd_ident)
501     {
502         case 0x2010:
503             tagname = olympus_private_2010_tagname(tag);
504             break;
505         case 0x2020:
506             tagname = olympus_private_2020_tagname(tag);
507             break;
508         case 0x2030:
509             tagname = olympus_private_2030_tagname(tag);
510             break;
511         case 0x2040:
512             tagname = olympus_private_2040_tagname(tag);
513             break;
514         case 0x2050:
515             tagname = olympus_private_2050_tagname(tag);
516             break;
517         default:
518             break;
519     }
520     return(tagname);
521 }
522 
523 char *
olympus_private_2010_tagname(unsigned short tag)524 olympus_private_2010_tagname(unsigned short tag)
525 {
526     char *tagname = CNULL;
527 
528     switch(tag)
529     {
530         case 0x0000: tagname = "EquipmentInfoVersion"; break;
531         case 0x0100: tagname = "FirmwareVersion2"; break;
532         case 0x0101: tagname = "SerialNumber"; break;
533         case 0x0103: tagname = "FocalPlaneDiagonal"; break;
534         case 0x0104: tagname = "BodyFirmwareVersion"; break;
535         case 0x0201: tagname = "Lens"; break;
536         case 0x0202: tagname = "LensSerialNumber"; break;
537         case  0x0204: tagname = "LensFirmwareVersion"; break;
538         case 0x0206: tagname = "MaxApertureAtMaxFocal"; break;
539         case 0x0207: tagname = "MinFocalLength"; break;
540         case 0x0208: tagname = "MaxFocalLength"; break;
541         case 0x0301: tagname = "Extender"; break;
542         case 0x0302: tagname = "ExtenderSerialNumber"; break;
543         case 0x0304: tagname = "ExtenderFirmwareVersion"; break;
544         case 0x1000: tagname = "FlashType"; break;
545         case 0x1001: tagname = "FlashModel"; break;
546         case 0x1003: tagname = "FlashSerialNumber"; break;
547         case 0x1004: tagname = "FlashFirmwareVersion"; break;
548         default:
549             break;
550     }
551     return(tagname);
552 }
553 
554 char *
olympus_private_2020_tagname(unsigned short tag)555 olympus_private_2020_tagname(unsigned short tag)
556 {
557     char *tagname = CNULL;
558 
559     switch(tag)
560     {
561         case 0x0000: tagname = "CameraSettingsVersion"; break;
562         case 0x0100: tagname = "PreviewImageValid"; break;
563         case 0x0101: tagname = "PreviewImageOffset"; break;
564         case 0x0102: tagname = "PreviewImageLength"; break;
565         case 0x0200: tagname = "ExposureMode"; break;
566         case 0x0202: tagname = "MeteringMode"; break;
567         case 0x0300: tagname = "MacroMode"; break;
568         case 0x0301: tagname = "FocusMode"; break;
569         case 0x0302: tagname = "FocusProcess"; break;
570         case 0x0303: tagname = "AFSearch"; break;
571         case 0x0304: tagname = "AFAreas"; break;
572         case 0x0400: tagname = "FlashMode"; break;
573         case 0x0401: tagname = "FlashExposureCompensation"; break;
574         case 0x0501: tagname = "WhiteBalanceTemperature"; break;
575         case 0x0502: tagname = "WhiteBalanceBracket"; break;
576         case 0x0503: tagname = "CustomSaturation"; break;
577         case 0x0504: tagname = "ModifiedSaturation"; break;
578         case 0x0505: tagname = "ContrastSetting"; break;
579         case 0x0506: tagname = "SharpnessSetting"; break;
580         case 0x0507: tagname = "ColorSpace"; break;
581         case 0x0509: tagname = "SceneMode"; break;
582         case 0x050a: tagname = "NoiseReduction"; break;
583         case 0x050b: tagname = "DistortionCorrection"; break;
584         case 0x050c: tagname = "ShadingCompensation"; break;
585         case 0x050d: tagname = "CompressionFactor"; break;
586         case 0x050f: tagname = "Gradation"; break;
587         case 0x0600: tagname = "Sequence"; break;
588         case 0x0603: tagname = "ImageQuality2"; break;
589         default:
590             break;
591     }
592     return(tagname);
593 }
594 
595 char *
olympus_private_2030_tagname(unsigned short tag)596 olympus_private_2030_tagname(unsigned short tag)
597 {
598     char *tagname = CNULL;
599 
600     switch(tag)
601     {
602         case 0x0000: tagname = "RawDevVersion"; break;
603         case 0x0100: tagname = "RawDevExposureBiasValue"; break;
604         case 0x0101: tagname = "RawDevWhiteBalanceValue"; break;
605         case 0x0102: tagname = "RawDevWBFineAdjustment"; break;
606         case 0x0103: tagname = "RawDevGrayPoint"; break;
607         case 0x0104: tagname = "RawDevSaturationEmphasis"; break;
608         case 0x0105: tagname = "RawDevMemoryColorEmphasis"; break;
609         case 0x0106: tagname = "RawDevContrastValue"; break;
610         case 0x0107: tagname = "RawDevSharpnessValue"; break;
611         case 0x0108: tagname = "RawDevColorSpace"; break;
612         case 0x0109: tagname = "RawDevEngine"; break;
613         case 0x010a: tagname = "RawDevNoiseReduction"; break;
614         case 0x010b: tagname = "RawDevEditStatus"; break;
615         case 0x010c: tagname = "RawDevSettings"; break;
616         default:
617             break;
618     }
619 
620     return(tagname);
621 }
622 
623 char *
olympus_private_2040_tagname(unsigned short tag)624 olympus_private_2040_tagname(unsigned short tag)
625 {
626     char *tagname = CNULL;
627 
628     switch(tag)
629     {
630         case 0x0000: tagname = "ImageProcessingVersion"; break;
631         case 0x0100: tagname = "RedBlueBias"; break;
632         case 0x0200: tagname = "ColorMatrix"; break;
633         case 0x0300: tagname = "SmoothingParameter1"; break;
634         case 0x0310: tagname = "SmoothingParameter2"; break;
635         case 0x0600: tagname = "SmoothingThresholds"; break;
636         case 0x0610: tagname = "SmoothingThreshold2"; break;
637         case 0x0611: tagname = "ValidBits"; break;
638         case 0x0614: tagname = "ImageWidth2"; break;
639         case 0x0615: tagname = "ImageHeight2"; break;
640         case 0x1010: tagname = "NoiseFilter2"; break;
641         case 0x1012: tagname = "ShadingCompensation2"; break;
642         default:
643             break;
644     }
645 
646     return(tagname);
647 }
648 
649 char *
olympus_private_2050_tagname(unsigned short tag)650 olympus_private_2050_tagname(unsigned short tag)
651 {
652     char *tagname = CNULL;
653 
654     switch(tag)
655     {
656         case 0x0000: tagname = "FocusInfoVersion"; break;
657         case 0x0209: tagname = "AutoFocus?"; break;
658         case 0x0300: tagname = "ZoomPosition"; break;
659         case 0x0305: tagname = "FocusDistance"; break;
660         case 0x1201: tagname = "ExternalFlash"; break;
661         case 0x1208: tagname = "InternalFlash"; break;
662         default:
663             break;
664     }
665 
666     return(tagname);
667 }
668 
669 void
olympus_interpret_pe_value(struct ifd_entry * entry_ptr,unsigned short subifd_ident,char * prefix)670 olympus_interpret_pe_value(struct ifd_entry *entry_ptr,unsigned short subifd_ident,
671                                                                     char *prefix)
672 {
673     if(entry_ptr)
674     {
675         switch(subifd_ident)
676         {
677             case 0x2010:
678                 olympus2010_interpret_value(entry_ptr,prefix);
679                 break;
680             case 0x2020:
681                 olympus2020_interpret_value(entry_ptr,prefix);
682                 break;
683             case 0x2030:
684                 olympus2030_interpret_value(entry_ptr,prefix);
685                 break;
686             case 0x2040:
687                 olympus2040_interpret_value(entry_ptr,prefix);
688                 break;
689             case 0x2050:
690                 olympus2050_interpret_value(entry_ptr,prefix);
691                 break;
692             default:
693                 break;
694         }
695     }
696 }
697 
698 void
olympus2010_interpret_value(struct ifd_entry * entry_ptr,char * prefix)699 olympus2010_interpret_value(struct ifd_entry *entry_ptr,char *prefix)
700 {
701     int chpr = 0;
702 
703     if(entry_ptr && (PRINT_VALUE))
704     {
705         switch(entry_ptr->tag)
706         {
707             case 0x1000:
708                 print_startvalue();
709                 switch(entry_ptr->value)
710                 {
711                     case 0: chpr += printf("None"); break;
712                     case 2: chpr += printf("Simple E-System"); break;
713                     case 3: chpr += printf("E-System"); break;
714                     default: chpr += printf("unknown"); break;
715                 }
716                 print_endvalue();
717                 break;
718             case 0x1001:
719                 print_startvalue();
720                 switch(entry_ptr->value)
721                 {
722                     case 1: chpr += printf("FL-20"); break;
723                     case 2: chpr += printf("FL-50"); break;
724                     case 3: chpr += printf("RF-11"); break;
725                     case 4: chpr += printf("TF-22"); break;
726                     case 5: chpr += printf("FL-36"); break;
727                     default: chpr += printf("unknown"); break;
728                 }
729                 print_endvalue();
730                 break;
731             default:
732                 break;
733         }
734     }
735     setcharsprinted(chpr);
736 }
737 
738 
739 void
olympus2020_interpret_value(struct ifd_entry * entry_ptr,char * prefix)740 olympus2020_interpret_value(struct ifd_entry *entry_ptr,char *prefix)
741 {
742     int chpr = 0;
743 
744     if(entry_ptr && (PRINT_VALUE))
745     {
746         switch(entry_ptr->tag)
747         {
748             case 0x0100:
749                 print_startvalue();
750                 switch(entry_ptr->value)
751                 {
752                     case 0: chpr += printf("No"); break;
753                     case 1: chpr += printf("yes"); break;
754                     default: chpr += printf("unknown"); break;
755                 }
756                 print_endvalue();
757                 break;
758             case 0x0200:
759                 print_startvalue();
760                 switch(entry_ptr->value)
761                 {
762                     case 1: chpr += printf("Manual"); break;
763                     case 3: chpr += printf("Aperture-priority"); break;
764                     case 4: chpr += printf("Shutter-priority"); break;
765                     case 5: chpr += printf("Program AE"); break;
766                     default: chpr += printf("unknown"); break;
767                 }
768                 print_endvalue();
769                 break;
770             case 0x0202:
771                 print_startvalue();
772                 switch(entry_ptr->value)
773                 {
774                     case 2: chpr += printf("Center Weighted"); break;
775                     case 3: chpr += printf("Spot"); break;
776                     case 5: chpr += printf("ESP"); break;
777                     default: chpr += printf("unknown"); break;
778                 }
779                 print_endvalue();
780                 break;
781             case 0x0300:
782                 print_startvalue();
783                 switch(entry_ptr->value)
784                 {
785                     case 0: chpr += printf("Off"); break;
786                     case 1: chpr += printf("On"); break;
787                     default: chpr += printf("unknown"); break;
788                 }
789                 print_endvalue();
790                 break;
791             case 0x0301:
792                 print_startvalue();
793                 switch(entry_ptr->value)
794                 {
795                     case 0: chpr += printf("Single AF"); break;
796                     case 1: chpr += printf("Sequential Shooting AF"); break;
797                     case 2: chpr += printf("Continuous AF"); break;
798                     case 3: chpr += printf("Multi AF"); break;
799                     case 10: chpr += printf("Manual"); break;
800                     default: chpr += printf("unknown"); break;
801                 }
802                 print_endvalue();
803                 break;
804             case 0x0302:
805                 print_startvalue();
806                 switch(entry_ptr->value)
807                 {
808                     case 0: chpr += printf("AF Off"); break;
809                     case 1: chpr += printf("AF On"); break;
810                     default: chpr += printf("unknown"); break;
811                 }
812                 print_endvalue();
813                 break;
814             case 0x0303:
815                 print_startvalue();
816                 switch(entry_ptr->value)
817                 {
818                     case 0: chpr += printf("Not Ready"); break;
819                     case 1: chpr += printf("Ready"); break;
820                     default: chpr += printf("unknown"); break;
821                 }
822                 print_endvalue();
823                 break;
824             case 0x0504:
825                 print_startvalue();
826                 switch(entry_ptr->value)
827                 {
828                     case 0: chpr += printf("Off"); break;
829                     case 1: chpr += printf("CM1 (Red Enhance)"); break;
830                     case 2: chpr += printf("CM2 (Green Enhance)"); break;
831                     case 3: chpr += printf("CM3 (Blue Enhance)"); break;
832                     case 4: chpr += printf("CM4 (Skin Tones)"); break;
833                     default: chpr += printf("unknown"); break;
834                 }
835                 print_endvalue();
836                 break;
837             case 0x0507:
838                 print_startvalue();
839                 switch(entry_ptr->value)
840                 {
841                     case 0: chpr += printf("sRGB"); break;
842                     case 1: chpr += printf("Adobe RGB"); break;
843                     case 2: chpr += printf("Pro Photo RGB"); break;
844                     default: chpr += printf("unknown"); break;
845                 }
846                 print_endvalue();
847                 break;
848             case 0x0509:
849                 print_startvalue();
850                 switch(entry_ptr->value)
851                 {
852                     case 0: chpr += printf("Standard"); break;
853                     case 7: chpr += printf("Sport"); break;
854                     case 8: chpr += printf("Portrait"); break;
855                     case 9: chpr += printf("Landscape+Portrait"); break;
856                     case 10: chpr += printf("Landscape"); break;
857                     case 11: chpr += printf("Night schene"); break;
858                     case 17: chpr += printf("Night+Portrait"); break;
859                     case 19: chpr += printf("Fireworks"); break;
860                     case 20: chpr += printf("Sunset"); break;
861                     case 22: chpr += printf("Macro"); break;
862                     case 25: chpr += printf("Documents"); break;
863                     case 26: chpr += printf("Museum"); break;
864                     case 28: chpr += printf("Beach&Snow"); break;
865                     case 30: chpr += printf("Candle"); break;
866                     case 39: chpr += printf("High Key"); break;
867                     default: chpr += printf("unknown"); break;
868                 }
869                 print_endvalue();
870                 break;
871             case 0x050a:
872                 print_startvalue();
873                 switch(entry_ptr->value)
874                 {
875                     case 0: chpr += printf("Off"); break;
876                     case 1: chpr += printf("Noise Reduction On"); break;
877                     case 2: chpr += printf("Noise Filter On"); break;
878                     case 3: chpr += printf("Noise Reduction + Noise Filter On"); break;
879                     default: chpr += printf("unknown"); break;
880                 }
881                 print_endvalue();
882                 break;
883             case 0x050b:
884                 print_startvalue();
885                 switch(entry_ptr->value)
886                 {
887                     case 0: chpr += printf("Off"); break;
888                     case 1: chpr += printf("On"); break;
889                     default: chpr += printf("unknown"); break;
890                 }
891                 print_endvalue();
892                 break;
893             case 0x050c:
894                 print_startvalue();
895                 switch(entry_ptr->value)
896                 {
897                     case 0: chpr += printf("Off"); break;
898                     case 1: chpr += printf("On"); break;
899                     default: chpr += printf("unknown"); break;
900                 }
901                 print_endvalue();
902                 break;
903             case 0x050f:
904                 print_startvalue();
905                 switch(entry_ptr->value)
906                 {
907                     case -1: chpr += printf("Low Key"); break;
908                     case 0: chpr += printf("Normal"); break;
909                     case 1: chpr += printf("High Key"); break;
910                     default: chpr += printf("unknown"); break;
911                 }
912                 print_endvalue();
913                 break;
914             case 0x0600:
915                 chpr += printf("%#x,%#x",(unsigned short)entry_ptr->value & 0xffff,(unsigned short)((entry_ptr->value & 0xffff0000) >> 16));
916                 break;
917             case 0x0603:
918                 print_startvalue();
919                 switch(entry_ptr->value)
920                 {
921                     case 1: chpr += printf("SQ"); break;
922                     case 2: chpr += printf("HQ"); break;
923                     case 3: chpr += printf("SHQ"); break;
924                     case 4: chpr += printf("RAW1"); break;
925                     case 6: chpr += printf("RAW2"); break;
926                     case 33: chpr += printf("not compressed"); break;
927                     case 34: /* not sure about this one ###%%%         */
928                              chpr += printf("not compressed");
929                              break;
930                     default: chpr += printf("unknown"); break;
931                 }
932                 print_endvalue();
933                 break;
934             default:
935                 break;
936         }
937     }
938     setcharsprinted(chpr);
939 }
940 
941 
942 void
olympus2030_interpret_value(struct ifd_entry * entry_ptr,char * prefix)943 olympus2030_interpret_value(struct ifd_entry *entry_ptr,char *prefix)
944 {
945     if(entry_ptr && (PRINT_VALUE))
946     {
947         switch(entry_ptr->tag)
948         {
949             default:
950                 break;
951         }
952     }
953 }
954 
955 
956 void
olympus2040_interpret_value(struct ifd_entry * entry_ptr,char * prefix)957 olympus2040_interpret_value(struct ifd_entry *entry_ptr,char *prefix)
958 {
959     if(entry_ptr && (PRINT_VALUE))
960     {
961         switch(entry_ptr->tag)
962         {
963             default:
964                 break;
965         }
966     }
967 }
968 
969 void
olympus2050_interpret_value(struct ifd_entry * entry_ptr,char * prefix)970 olympus2050_interpret_value(struct ifd_entry *entry_ptr,char *prefix)
971 {
972     if(entry_ptr && (PRINT_VALUE))
973     {
974         switch(entry_ptr->tag)
975         {
976             default:
977                 break;
978         }
979     }
980 }
981 
982 /* Pick the appropriate offset value processor for Olympus private    */
983 /* IFDs based upon noteversion.                                       */
984 
985 void
olympus_offset_pe_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)986 olympus_offset_pe_value(FILE *inptr,unsigned short byteorder,
987                 struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
988                 unsigned short subifd_ident,struct image_summary *summary_entry,
989                 char *parent_name,char*prefix,
990                 int indent,int make,int model,int at_offset)
991 {
992     int noteversion = 0;
993 
994     noteversion = getnoteversion();
995 
996     if(entry_ptr)
997     {
998         switch(noteversion)
999         {
1000             case 1:
1001                 olympus1_offset_pe_value(inptr,byteorder,entry_ptr,
1002                                             fileoffset_base,subifd_ident,
1003                                             summary_entry,parent_name,prefix,
1004                                             indent,make,model,at_offset);
1005                 olympus1_interpret_offset_pe_value(inptr,byteorder,entry_ptr,
1006                                             fileoffset_base,subifd_ident);
1007                 break;
1008             default:
1009                 print_private_offset_value(inptr,byteorder,entry_ptr,
1010                                         fileoffset_base,subifd_ident,
1011                                         parent_name,prefix,indent,
1012                                         make,model,at_offset);
1013                 break;
1014         }
1015     }
1016 }
1017 
1018 /* Pick the appropriate offset value processor for Olympus            */
1019 /* noteversion 1 private IFDs, based upon the tag number of the IFD.  */
1020 
1021 void
olympus1_offset_pe_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1022 olympus1_offset_pe_value(FILE *inptr,unsigned short byteorder,
1023     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1024     unsigned short subifd_ident,struct image_summary *summary_entry,
1025     char *parent_name,char*prefix,
1026     int indent,int make,int model,int at_offset)
1027 {
1028     if(entry_ptr)
1029     {
1030         switch(subifd_ident)
1031         {
1032             case 0x2010:
1033                 olympus2010_offset_value(inptr,byteorder,entry_ptr,
1034                                             fileoffset_base,summary_entry,
1035                                             parent_name,prefix,indent,
1036                                             make,model,at_offset);
1037                 break;
1038             case 0x2020:
1039                 olympus2020_offset_value(inptr,byteorder,entry_ptr,
1040                                             fileoffset_base,summary_entry,
1041                                             parent_name,prefix,indent,
1042                                             make,model,at_offset);
1043                 break;
1044             case 0x2030:
1045                 olympus2030_offset_value(inptr,byteorder,entry_ptr,
1046                                             fileoffset_base,summary_entry,
1047                                             parent_name,prefix,indent,
1048                                             make,model,at_offset);
1049                 break;
1050             case 0x2040:
1051                 olympus2040_offset_value(inptr,byteorder,entry_ptr,
1052                                             fileoffset_base,summary_entry,
1053                                             parent_name,prefix,indent,
1054                                             make,model,at_offset);
1055                 break;
1056             case 0x2050:
1057                 olympus2050_offset_value(inptr,byteorder,entry_ptr,
1058                                             fileoffset_base,summary_entry,
1059                                             parent_name,prefix,indent,
1060                                             make,model,at_offset);
1061                 break;
1062             default:
1063                 print_private_offset_value(inptr,byteorder,entry_ptr,
1064                                         fileoffset_base,subifd_ident,
1065                                         parent_name,prefix,indent,
1066                                         make,model,at_offset);
1067                 break;
1068         }
1069     }
1070 }
1071 
1072 /* Olympus 'Equipment' IFD from Makernote (0x2010)                    */
1073 
1074 void
olympus2010_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1075 olympus2010_offset_value(FILE *inptr,unsigned short byteorder,
1076     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1077     struct image_summary *summary_entry,char *parent_name,char*prefix,
1078     int indent,int make,int model,int at_offset)
1079 {
1080     unsigned long value_offset;
1081     unsigned long count;
1082     char *nameoftag;
1083     char *fulldirname = CNULL;
1084     int chpr = 0;
1085 
1086     if(entry_ptr)
1087     {
1088         nameoftag = maker_tagname(entry_ptr->tag,make,model);
1089         if((PRINT_LONGNAMES))
1090         {
1091             fulldirname = splice(parent_name,".",nameoftag);
1092             nameoftag = fulldirname;
1093         }
1094         value_offset = fileoffset_base + entry_ptr->value;
1095         count = entry_ptr->count;
1096         switch(entry_ptr->tag)
1097         {
1098             case 0x0100:
1099             case 0x0101:
1100             case 0x0102:
1101             case 0x0202:
1102             case 0x0301:
1103             case 0x0302:
1104             case 0x1003:
1105             default:
1106                 print_private_offset_value(inptr,byteorder,entry_ptr,
1107                                         fileoffset_base,0x2010,
1108                                         fulldirname,prefix,indent,
1109                                         make,model,at_offset);
1110                 break;
1111         }
1112         if(fulldirname)
1113             free(fulldirname);
1114     }
1115     setcharsprinted(chpr);
1116 }
1117 
1118 /* Olympus 'CameraSettings' IFD from Makernote (0x2020)                    */
1119 
1120 void
olympus2020_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1121 olympus2020_offset_value(FILE *inptr,unsigned short byteorder,
1122     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1123     struct image_summary *summary_entry,char *parent_name,char*prefix,
1124     int indent,int make,int model,int at_offset)
1125 {
1126     static unsigned long jpegthumbnailoffset = 0UL;
1127     static unsigned long jpegthumbnailvalid = 1UL;
1128     unsigned long value_offset,max_offset;
1129     unsigned long count;
1130     unsigned short marker;
1131     char *nameoftag;
1132     char *fulldirname = CNULL;
1133     int status = 0;
1134     int chpr = 0;
1135 
1136     if(entry_ptr)
1137     {
1138         nameoftag = maker_tagname(entry_ptr->tag,make,model);
1139         if((PRINT_LONGNAMES))
1140         {
1141             fulldirname = splice(parent_name,".",nameoftag);
1142             nameoftag = fulldirname;
1143         }
1144         value_offset = fileoffset_base + entry_ptr->value;
1145         count = entry_ptr->count;
1146         switch(entry_ptr->tag)
1147         {
1148             case 0x0100: /* JPEG Thumbnail valid                      */
1149                 /* The default is 1 (valid), so this can turn off     */
1150                 /* processing if present and 0. Better to attempt     */
1151                 /* processing when invalid than miss a valid image.   */
1152                 jpegthumbnailvalid = value_offset;
1153                 break;
1154             case 0x0101: /* JPEG Thumbnail offset                     */
1155                 jpegthumbnailoffset = value_offset;
1156                 if(!(PRINT_VALUE_AT_OFFSET))
1157                 {
1158                     if(!(PRINT_OFFSET))
1159                         chpr += printf("@%lu",jpegthumbnailoffset);
1160                 }
1161                 break;
1162             case 0x0102: /* JPEG Thumbnail length                     */
1163                 if(jpegthumbnailvalid == 0)
1164                 {
1165                     jpegthumbnailvalid = 0;
1166                     break;
1167                 }
1168                 if(jpegthumbnailoffset)
1169                 {
1170                     count = entry_ptr->value;
1171                     value_offset = jpegthumbnailoffset;
1172                     jpegthumbnailoffset = 0UL;
1173                 }
1174                 else
1175                 {
1176                     printred("# Warning: no thumbnail offset");
1177                     break;
1178                 }
1179                 indent += SMALLINDENT;
1180                 if(at_offset && (PRINT_SECTION))
1181                 {
1182                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
1183                     chpr += printf("# Start of JPEG Thumbnail from MakerNote SubIFD");
1184                     chpr += printf(" length %ld",count);
1185                 }
1186                 if((PRINT_SECTION) || (PRINT_SEGMENT))
1187                     chpr = newline(chpr);
1188                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
1189                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
1190                                             count,summary_entry,fulldirname,
1191                                                 prefix,indent+MEDIUMINDENT);
1192                 if(at_offset)
1193                 {
1194                     if((PRINT_SECTION))
1195                     {
1196                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
1197                             chpr = newline(chpr);
1198                         jpeg_status(status);
1199                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
1200                                                                         indent,"-");
1201                         chpr += printf("# End of JPEG Thumbnail from MakerNote SubIFD");
1202                         if((PRINT_ENTRY) && !(PRINT_VALUE))
1203                             chpr = newline(chpr);
1204                     }
1205                 }
1206                 print_jpeg_status();
1207                 if(marker && summary_entry)
1208                 {
1209                     /* The new one is on the end of the chain         */
1210                     if((summary_entry = last_summary_entry(summary_entry)))
1211                     {
1212                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
1213                         summary_entry->datatype = MAKER_SUBIFD;
1214                         summary_entry->subfiletype = REDUCED_RES_TYPE;
1215                     }
1216                 }
1217                 /* make certain we're at the end                      */
1218                 clearerr(inptr);
1219                 fseek(inptr,value_offset + count,0);
1220                 break;
1221             case 0x0304:
1222             case 0x0503:
1223             case 0x0505:
1224             case 0x0506:
1225             case 0x050f:
1226             default:
1227                 print_private_offset_value(inptr,byteorder,entry_ptr,
1228                                         fileoffset_base,0x2020,
1229                                         fulldirname,prefix,indent,
1230                                         make,model,at_offset);
1231                 break;
1232         }
1233         if(fulldirname)
1234             free(fulldirname);
1235     }
1236     setcharsprinted(chpr);
1237 }
1238 
1239 /* Olympus 'RawDevelopment' IFD from Makernote (0x2030)                    */
1240 
1241 void
olympus2030_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1242 olympus2030_offset_value(FILE *inptr,unsigned short byteorder,
1243     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1244     struct image_summary *summary_entry,char *parent_name,char*prefix,
1245     int indent,int make,int model,int at_offset)
1246 {
1247     unsigned long value_offset;
1248     unsigned long count;
1249     char *nameoftag;
1250     char *fulldirname = CNULL;
1251     int chpr = 0;
1252 
1253     if(entry_ptr)
1254     {
1255         nameoftag = maker_tagname(entry_ptr->tag,make,model);
1256         if((PRINT_LONGNAMES))
1257         {
1258             fulldirname = splice(parent_name,".",nameoftag);
1259             nameoftag = fulldirname;
1260         }
1261         value_offset = fileoffset_base + entry_ptr->value;
1262         count = entry_ptr->count;
1263         switch(entry_ptr->tag)
1264         {
1265             default:
1266                 print_private_offset_value(inptr,byteorder,entry_ptr,
1267                                         fileoffset_base,0x2030,
1268                                         fulldirname,prefix,indent,
1269                                         make,model,at_offset);
1270                 break;
1271         }
1272         if(fulldirname)
1273             free(fulldirname);
1274     }
1275     setcharsprinted(chpr);
1276 }
1277 
1278 /* Olympus 'ImageProcessing' IFD from Makernote (0x2040)                    */
1279 
1280 void
olympus2040_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1281 olympus2040_offset_value(FILE *inptr,unsigned short byteorder,
1282     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1283     struct image_summary *summary_entry,char *parent_name,char*prefix,
1284     int indent,int make,int model,int at_offset)
1285 {
1286     unsigned long value_offset;
1287     unsigned long count;
1288     char *nameoftag;
1289     char *fulldirname = CNULL;
1290     int chpr = 0;
1291 
1292     if(entry_ptr)
1293     {
1294         nameoftag = maker_tagname(entry_ptr->tag,make,model);
1295         if((PRINT_LONGNAMES))
1296         {
1297             fulldirname = splice(parent_name,".",nameoftag);
1298             nameoftag = fulldirname;
1299         }
1300         value_offset = fileoffset_base + entry_ptr->value;
1301         count = entry_ptr->count;
1302         switch(entry_ptr->tag)
1303         {
1304             default:
1305                 print_private_offset_value(inptr,byteorder,entry_ptr,
1306                                         fileoffset_base,0x2040,
1307                                         fulldirname,prefix,indent,
1308                                         make,model,at_offset);
1309                 break;
1310         }
1311         if(fulldirname)
1312             free(fulldirname);
1313     }
1314     setcharsprinted(chpr);
1315 }
1316 
1317 /* Olympus 'FocusInfo' IFD from Makernote (0x2050)                    */
1318 
1319 void
olympus2050_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,struct image_summary * summary_entry,char * parent_name,char * prefix,int indent,int make,int model,int at_offset)1320 olympus2050_offset_value(FILE *inptr,unsigned short byteorder,
1321     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1322     struct image_summary *summary_entry,char *parent_name,char*prefix,
1323     int indent,int make,int model,int at_offset)
1324 {
1325     unsigned long value_offset;
1326     unsigned long count;
1327     char *nameoftag;
1328     char *fulldirname = CNULL;
1329     int chpr = 0;
1330 
1331     if(entry_ptr)
1332     {
1333         nameoftag = maker_tagname(entry_ptr->tag,make,model);
1334         if((PRINT_LONGNAMES))
1335         {
1336             fulldirname = splice(parent_name,".",nameoftag);
1337             nameoftag = fulldirname;
1338         }
1339         value_offset = fileoffset_base + entry_ptr->value;
1340         count = entry_ptr->count;
1341         switch(entry_ptr->tag)
1342         {
1343             default:
1344                 print_private_offset_value(inptr,byteorder,entry_ptr,
1345                                         fileoffset_base,0x2050,
1346                                         fulldirname,prefix,indent,
1347                                         make,model,at_offset);
1348                 break;
1349         }
1350         if(fulldirname)
1351             free(fulldirname);
1352     }
1353     setcharsprinted(chpr);
1354 }
1355 
1356 void
olympus1_interpret_offset_pe_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,unsigned short subifd_ident)1357 olympus1_interpret_offset_pe_value(FILE *inptr,unsigned short byteorder,
1358                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
1359                     unsigned short subifd_ident)
1360 {
1361     if(entry_ptr)
1362     {
1363         switch(subifd_ident)
1364         {
1365             case 0x2010:
1366                 olympus2010_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base);
1367                 break;
1368             case 0x2020:
1369                 olympus2020_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base);
1370                 break;
1371             case 0x2030:
1372                 olympus2030_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base);
1373                 break;
1374             case 0x2040:
1375                 olympus2040_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base);
1376                 break;
1377             case 0x2050:
1378                 olympus2050_interpret_offset_value(inptr,byteorder,entry_ptr,fileoffset_base);
1379                 break;
1380             default:
1381                 break;
1382         }
1383     }
1384 }
1385 
1386 void
olympus2010_interpret_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)1387 olympus2010_interpret_offset_value(FILE *inptr,unsigned short byteorder,
1388         struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
1389 {
1390     unsigned long offset;
1391 
1392     if(entry_ptr)
1393     {
1394         offset = entry_ptr->value + fileoffset_base;
1395         switch(entry_ptr->tag)
1396         {
1397             default:
1398                 break;
1399         }
1400     }
1401 }
1402 
1403 void
olympus2020_interpret_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)1404 olympus2020_interpret_offset_value(FILE *inptr,unsigned short byteorder,
1405         struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
1406 {
1407     unsigned long offset;
1408 
1409     if(entry_ptr)
1410     {
1411         offset = entry_ptr->value + fileoffset_base;
1412         switch(entry_ptr->tag)
1413         {
1414             default:
1415                 break;
1416         }
1417     }
1418 }
1419 
1420 void
olympus2030_interpret_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)1421 olympus2030_interpret_offset_value(FILE *inptr,unsigned short byteorder,
1422         struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
1423 {
1424     unsigned long offset;
1425 
1426     if(entry_ptr)
1427     {
1428         offset = entry_ptr->value + fileoffset_base;
1429         switch(entry_ptr->tag)
1430         {
1431             default:
1432                 break;
1433         }
1434     }
1435 }
1436 
1437 void
olympus2040_interpret_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)1438 olympus2040_interpret_offset_value(FILE *inptr,unsigned short byteorder,
1439         struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
1440 {
1441     unsigned long offset;
1442 
1443     if(entry_ptr)
1444     {
1445         offset = entry_ptr->value + fileoffset_base;
1446         switch(entry_ptr->tag)
1447         {
1448             default:
1449                 break;
1450         }
1451     }
1452 }
1453 
1454 void
olympus2050_interpret_offset_value(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)1455 olympus2050_interpret_offset_value(FILE *inptr,unsigned short byteorder,
1456         struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
1457 {
1458     unsigned long offset;
1459 
1460     if(entry_ptr)
1461     {
1462         offset = entry_ptr->value + fileoffset_base;
1463         switch(entry_ptr->tag)
1464         {
1465             default:
1466                 break;
1467         }
1468     }
1469 }
1470 
1471 int
olympus_private_value_is_offset(unsigned short subifd_ident,unsigned short tag)1472 olympus_private_value_is_offset(unsigned short subifd_ident,unsigned short tag)
1473 {
1474     int is_offset = 0;
1475 
1476     switch(subifd_ident)
1477     {
1478         case 0x2010: break;
1479         case 0x2020: is_offset = olympus2020_value_is_offset(tag); break;
1480         case 0x2030: break;
1481         case 0x2040: break;
1482         case 0x2050: break;
1483         default: break;
1484     }
1485     return(is_offset);
1486 }
1487 
1488 int
olympus2020_value_is_offset(unsigned short tag)1489 olympus2020_value_is_offset(unsigned short tag)
1490 {
1491     int is_offset = 0;
1492 
1493     switch(tag)
1494     {
1495         case 0x0100: is_offset = -1; break;
1496         case 0x0101: is_offset = 1; break;
1497         case 0x0102: is_offset = -1; break;
1498         default: break;
1499     }
1500     return(is_offset);
1501 }
1502 
1503