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_asahi.c,v 1.10 2005/07/24 22:56:26 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Asahi/Pentax camera maker-specific routines                        */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* This information is from an image by Johannes Tschebisch at:       */
17 /* http://www.jojotsch.de/downloads/jojothumb/beispiele/              */
18 /*                             html_exif/bilder/bilder.html           */
19 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
20 
21 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
22 /* New info (Jan 05) from Evan Hunter:                                */
23 /* http://www.ozhiker.com/electronics/pjmt/jpeg_info/pentax_mn.html   */
24 
25 /* April 05: tagset 3 largely due to Phil Harvey's pages at:          */
26 /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html   */
27 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include "defs.h"
33 #include "datadefs.h"
34 #include "maker_datadefs.h"
35 #include "summary.h"
36 #include "maker.h"
37 #include "misc.h"
38 #include "tags.h"
39 #include "maker_extern.h"
40 #include "extern.h"
41 
42 extern struct camera_id pentax_model_id[];
43 
44 /* Find the identifying number assigned to known Asahi/Pentax camera  */
45 /* models. This number is used to dispatch print and interpret        */
46 /* routines approopriate to the current image.                        */
47 
48 int
asahi_model_number(char * model,char * software)49 asahi_model_number(char *model,char *software)
50 {
51     struct camera_id *model_id;
52     int number = NO_MODEL;
53 
54     for(model_id = &pentax_model_id[0]; model_id && model_id->name; ++model_id)
55     {
56         if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
57         {
58             number = model_id->id;
59             setnoteversion(model_id->noteversion);
60             setnotetagset(model_id->notetagset);    /* info only      */
61             break;
62         }
63     }
64     return(number);
65 }
66 
67 /* If an unknown model is seen, use the makernote scheme to select a  */
68 /* noteversion to use                                                 */
69 
70 /* There are some assumptions involved in doing this, but there seems */
71 /* sufficient difference (and distinctive difference) between         */
72 /* Asahi/Pentax schemes to make this reasonable.                      */
73 
74 /* v3 has first tag 0x01 (1 SHORT) ID scheme,  "PENTAX Corporation"   */
75 /* v2 has first tag 0x02 (2 SHORT) ID scheme,  "Asahi Optical"        */
76     /* second tag 0x02 (2 SHORT)                                      */
77 /* v1 has first tag 0x01 (1 SHORT) ER scheme (no ID), "Asahi Optical" */
78     /* second tag 0x02 (1 SHORT)                                      */
79 
80 int
set_asahi_noteversion()81 set_asahi_noteversion()
82 {
83     struct maker_scheme *scheme;
84     int noteversion = 0;
85     int tagset = 0;
86 
87     scheme = retrieve_makerscheme();
88     if(scheme->note_version <= 0)
89     {
90         switch(scheme->scheme_type)
91         {
92             case HAS_ID_SCHEME:
93                 if(scheme->first_entry.tag == 0x1)
94                 {
95                     tagset = 3;
96                     noteversion = 3;
97                 }
98                 else
99                 {
100                     tagset = 2;
101                     noteversion = 2;
102                 }
103                 break;
104             case PLAIN_IFD_SCHEME:
105                 tagset = 1;
106                 noteversion = 1;
107                 break;
108         }
109         setnotetagset(tagset);
110         setnoteversion(noteversion);
111     }
112     else
113         noteversion = scheme->note_version;
114     return(noteversion);
115 }
116 
117 /* Dispatch print routines for direct values in Asahi/Pentax cameras, */
118 /* based upon previously set noteversion                              */
119 
120 void
print_asahi_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)121 print_asahi_makervalue(struct ifd_entry *entry_ptr,int make,int model,
122                                                         char *prefix)
123 {
124     int noteversion = 0;
125 
126     noteversion = getnoteversion();
127 
128     if(entry_ptr)
129     {
130         switch(noteversion)
131         {
132             case 3:
133                 print_asahi1_makervalue(entry_ptr,make,model,prefix);
134                 asahi3_interpret_value(entry_ptr);
135                 break;
136             case 2:
137                 print_asahi1_makervalue(entry_ptr,make,model,prefix);
138                 asahi2_interpret_value(entry_ptr);
139                 break;
140             case 1:
141                 print_asahi1_makervalue(entry_ptr,make,model,prefix);
142                 asahi1_interpret_value(entry_ptr);
143                 break;
144             default:
145                 print_value(entry_ptr,PREFIX);
146                 break;
147         }
148     }
149 }
150 
151 /* Model-specific print routine for Asahi/Pentax cameras. This        */
152 /* routine is responsible for picking off any direct entry tags which */
153 /* are peculiar and will not be handled properly by print_value()     */
154 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
155 /* there are no such entries, this function simply calls              */
156 /* print_value().                                                     */
157 
158 void
print_asahi1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)159 print_asahi1_makervalue(struct ifd_entry *entry_ptr,int make,int model,
160                     char *prefix)
161 {
162     if(entry_ptr)
163     {
164         switch(entry_ptr->tag)
165         {
166             default:
167                 print_value(entry_ptr,PREFIX);
168                 break;
169         }
170     }
171 }
172 
173 
174 /* Dispatch a routine to decode and print offset values for Asahi/Pentax     */
175 /* cameras.                                                           */
176 
177 void
print_asahi_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)178 print_asahi_offset_makervalue(FILE *inptr,unsigned short byteorder,
179     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
180     struct image_summary *summary_entry,char *parent_name,
181     char *prefix,int indent,int make,int model,int at_offset)
182 {
183     int noteversion = 0;
184 
185     noteversion = getnoteversion();
186 
187     if(entry_ptr)
188     {
189         switch(noteversion)
190         {
191             case 3:
192                 asahi2_offset_makervalue(inptr,byteorder,entry_ptr,
193                                             fileoffset_base,summary_entry,
194                                             parent_name,prefix,indent,
195                                             make,model,at_offset);
196                 break;
197             case 2:
198                 asahi1_offset_makervalue(inptr,byteorder,entry_ptr,
199                                             fileoffset_base,summary_entry,
200                                             parent_name,prefix,indent,
201                                             make,model,at_offset);
202                 break;
203             case 1:
204                 asahi1_offset_makervalue(inptr,byteorder,entry_ptr,
205                                             fileoffset_base,summary_entry,
206                                             parent_name,prefix,indent,
207                                             make,model,at_offset);
208                 break;
209             default:
210                 print_value(entry_ptr,PREFIX);
211                 break;
212         }
213     }
214 }
215 
216 
217 /* Model-specific routine to print UNDEFINED values found at offsets  */
218 /* in Asahi/Pentax makernotes.                                        */
219 
220 void
asahi1_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)221 asahi1_offset_makervalue(FILE *inptr,unsigned short byteorder,
222     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
223     struct image_summary *summary_entry,char *parent_name,char *prefix,
224     int indent,int make,int model,int at_offset)
225 {
226     unsigned long value_offset,max_offset;
227     unsigned short marker;
228     unsigned long count;
229     char *nameoftag;
230     char *fulldirname = CNULL;
231     int status = 0;
232     int chpr = 0;
233 
234     if(inptr && entry_ptr)
235     {
236         nameoftag = maker_tagname(entry_ptr->tag,make,model);
237         fulldirname = splice(parent_name,".",nameoftag);
238         value_offset = fileoffset_base + entry_ptr->value;
239         count = entry_ptr->count;
240 
241         switch(entry_ptr->tag)
242         {
243             case 0x0004:    /* JpegThumbnailOffset                    */
244                 /* These models provide the 0x2000 tag as well as the */
245                 /* 0x0003/0x0004 tags. Both entries point to the same */
246                 /* thumbnail, so just print values for length and     */
247                 /* offset tags, and display the thumbnail on the      */
248                 /* (self-contained) 0x2000 tag                        */
249                 if(!at_offset && (PRINT_VALUE))
250                 {
251                     if(!(PRINT_OFFSET))
252                         chpr += printf("@%lu",value_offset);
253                 }
254                 break;
255             case 0x2000: /* Jpeg Thumbnail as UNDEFINED section       */
256                 if(at_offset && (PRINT_SECTION))
257                 {
258                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
259                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
260                     chpr += printf(" length %lu",count);
261                 }
262                 else if(!at_offset && (PRINT_VALUE))
263                 {
264                     if(!(PRINT_OFFSET))
265                         chpr += printf("@%lu:%lu    # UNDEFINED",value_offset,count);
266                 }
267                 if((PRINT_SECTION) || (PRINT_SEGMENT))
268                     chpr = newline(chpr);
269                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
270                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
271                                     count,summary_entry,fulldirname,
272                                     prefix,indent+SMALLINDENT);
273                 if(at_offset)
274                 {
275                     if((PRINT_SECTION))
276                     {
277                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
278                             chpr = newline(chpr);
279                         jpeg_status(status);
280                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
281                                                     indent,"-");
282                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
283                         if((PRINT_ENTRY) && !(PRINT_VALUE))
284                             chpr = newline(chpr);
285                     }
286                 }
287                 print_jpeg_status();
288                 if(marker && summary_entry)
289                 {
290                     /* The new one is on the end of the chain         */
291                     if((summary_entry = last_summary_entry(summary_entry)))
292                     {
293                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
294                         summary_entry->datatype = MAKER_IFD;
295                         summary_entry->subfiletype = THUMBNAIL_TYPE;
296                     }
297                 }
298                 /* make certain we're at the end                      */
299                 clearerr(inptr);
300                 fseek(inptr,value_offset + count,0);
301                 break;
302             case 0x0e00: /* PrintIM (Epson Print Image matching)      */
303                 if(!at_offset && (PRINT_VALUE))
304                 {
305                     if(!(PRINT_OFFSET))
306                     {
307                         chpr += printf("@%lu:%lu",value_offset,count);
308                         chpr = newline(chpr);
309                     }
310                 }
311                 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
312                     count,nameoftag,parent_name,prefix,indent);
313                 break;
314             default:
315                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base,
316                                                     fulldirname,prefix,indent,
317                                                     make,model,at_offset);
318                 break;
319         }
320         if(fulldirname)
321             free(fulldirname);
322     }
323     setcharsprinted(chpr);
324 }
325 
326 void
asahi2_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)327 asahi2_offset_makervalue(FILE *inptr,unsigned short byteorder,
328     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
329     struct image_summary *summary_entry,char *parent_name,
330     char *prefix,int indent,int make,int model,int at_offset)
331 {
332     static unsigned long jpegthumbnaillength = 0UL;
333     unsigned long value_offset,max_offset;
334     unsigned short marker;
335     unsigned long count;
336     char *nameoftag;
337     char *fulldirname = CNULL;
338     int status = 0;
339     int chpr = 0;
340 
341     if(inptr && entry_ptr)
342     {
343         nameoftag = maker_tagname(entry_ptr->tag,make,model);
344         fulldirname = splice(parent_name,".",nameoftag);
345         value_offset = fileoffset_base + entry_ptr->value;
346         count = entry_ptr->count;
347 
348         switch(entry_ptr->tag)
349         {
350             case 0x0003:    /* JpegThumbnailLength                    */
351                 /* Just record it                                     */
352                 jpegthumbnaillength = entry_ptr->value;
353                 break;
354             case 0x0004:    /* JpegThumbnailOffset                    */
355                 if(jpegthumbnaillength)
356                 {
357                     count = jpegthumbnaillength;
358                     jpegthumbnaillength = 0;
359                 }
360                 if(at_offset && (PRINT_SECTION))
361                 {
362                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
363                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
364                     chpr += printf(" length %ld",count);
365                 }
366                 else if(!at_offset && (PRINT_VALUE))
367                 {
368                     if(!(PRINT_OFFSET))
369                         chpr += printf("@%lu:%lu",value_offset,count);
370                     else
371                         chpr = printf("length %lu",count);
372                 }
373                 if((PRINT_SECTION) || (PRINT_SEGMENT))
374                     chpr = newline(chpr);
375                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
376                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
377                                     count,summary_entry,fulldirname,
378                                     prefix,indent+SMALLINDENT);
379                 if(at_offset)
380                 {
381                     if((PRINT_SECTION))
382                     {
383                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
384                             chpr = newline(chpr);
385                         jpeg_status(status);
386                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
387                                                     indent,"-");
388                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
389                         if((PRINT_ENTRY) && !(PRINT_VALUE))
390                             chpr = newline(chpr);
391                     }
392                 }
393                 print_jpeg_status();
394                 if(marker && summary_entry)
395                 {
396                     /* The new one is on the end of the chain         */
397                     if((summary_entry = last_summary_entry(summary_entry)))
398                     {
399                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
400                         summary_entry->datatype = MAKER_IFD;
401                         summary_entry->subfiletype = THUMBNAIL_TYPE;
402                     }
403                 }
404                 /* make certain we're at the end                      */
405                 clearerr(inptr);
406                 fseek(inptr,value_offset + count,0);
407                 break;
408             case 0x0e00: /* PrintIM (Epson Print Image matching)      */
409                 if(!at_offset && (PRINT_VALUE))
410                 {
411                     if(!(PRINT_OFFSET))
412                         chpr += printf("@%lu",value_offset);
413                 }
414                 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
415                     count,nameoftag,parent_name,prefix,indent);
416                 break;
417             default:
418                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
419                                         fileoffset_base, fulldirname,prefix,indent,
420                                         make,model,at_offset);
421                 break;
422         }
423     }
424     setcharsprinted(chpr);
425 }
426 
427 
428 /* Asahi/Pentax-specific tagnames for makernotes.                     */
429 
430 char *
maker_asahi_tagname(unsigned short tag,int model)431 maker_asahi_tagname(unsigned short tag,int model)
432 {
433     char *tagname = (char *)0;
434     int noteversion = 0;
435 
436     /* Should have to do this only once, and only for unrecognized    */
437     /* models. If the model is recognized (or the user has forced a   */
438     /* noteversion) noteversion will already be set.                  */
439     /* This should already have been done in find_maker_scheme(), but */
440     /* there is no harm in checking noteversion after retrieving it.  */
441     if(((noteversion = getnoteversion()) == 0))
442         noteversion = set_asahi_noteversion();
443 
444     switch(noteversion)
445     {
446         case 1:
447             tagname = maker_asahi1_tagname(tag,model);
448             break;
449         case 2:
450             tagname = maker_asahi2_tagname(tag,model);
451             break;
452         case 3:
453             tagname = maker_asahi3_tagname(tag,model);
454             break;
455         default:
456             break;
457     }
458 
459     /* If no model-specific tag is found, check "generic" tags        */
460     if(tagname == NULL)
461     {
462         switch(tag)
463         {
464             case 0x0e00: tagname = "PrintIM"; break;
465             default: break;
466         }
467     }
468     return(tagname);
469 }
470 
471 
472 char *
maker_asahi1_tagname(unsigned short tag,int model)473 maker_asahi1_tagname(unsigned short tag,int model)
474 {
475     char *tagname = CNULL;
476 
477     switch(tag)
478     {
479         case 0x0001: tagname = "CaptureMode"; break;
480         case 0x0002: tagname = "Quality"; break;
481         case 0x0003: tagname = "FocusMode"; break;
482         case 0x0004: tagname = "FlashMode"; break;
483         case 0x0007: tagname = "WhiteBalance"; break;
484         case 0x000a: tagname = "DigitalZoom"; break;
485         case 0x000b: tagname = "Sharpness"; break;
486         case 0x000c: tagname = "Contrast"; break;
487         case 0x000d: tagname = "Saturation"; break;
488         case 0x0014: tagname = "ISOSpeedSetting"; break;
489         case 0x0017: tagname = "Color"; break;
490         case 0x1000: tagname = "TimeZone"; break;
491         case 0x1001: tagname = "DaylightSavings"; break;
492     }
493     setnotetagset(1);
494     return(tagname);
495 }
496 
497 char *
maker_asahi2_tagname(unsigned short tag,int model)498 maker_asahi2_tagname(unsigned short tag,int model)
499 {
500     char *tagname = CNULL;
501 
502     /* This is the same as Casio note version 2                       */
503     switch(tag)
504     {
505         case 0x0002: tagname = "JpegThumbnailDimensions"; break;
506         case 0x0003: tagname = "JpegThumbnailLength"; break;
507         case 0x0004: tagname = "JpegThumbnailOffset"; break;
508         case 0x0008: tagname = "QualityMode"; break;
509         case 0x0009: tagname = "ImageSize"; break;
510         case 0x000D: tagname = "FocusMode"; break;
511         case 0x0014: tagname = "IsoSensitivity"; break;
512         case 0x0019: tagname = "WhiteBalance"; break;
513         case 0x001D: tagname = "FocalLength"; break; /* units .1mm   */
514         case 0x001F: tagname = "Saturation"; break;
515         case 0x0020: tagname = "Contrast"; break;
516         case 0x0021: tagname = "Sharpness"; break;
517         case 0x2000: tagname = "JpegThumbnail"; break;
518         case 0x2011: tagname = "WhiteBalanceBias"; break;
519         case 0x2012: tagname = "WhiteBalance"; break;
520         case 0x2022: tagname = "ObjectDistance"; break;
521         case 0x2034: tagname = "FlashDistance"; break;
522         case 0x3000: tagname = "RecordMode"; break;
523         case 0x3001: tagname = "SelfTimer?"; break;
524         case 0x3002: tagname = "Quality"; break;
525         case 0x3003: tagname = "FocusMode"; break;
526         case 0x3006: tagname = "TimeZone"; break;
527         case 0x3007: tagname = "BestshotMode"; break;
528         case 0x3014: tagname = "CCDSensitivity"; break;
529         case 0x3015: tagname = "ColorMode"; break;
530         case 0x3016: tagname = "Enhancement"; break;
531         case 0x3017: tagname = "Filter"; break;
532         default: break;
533     }
534     setnotetagset(2);
535     return(tagname);
536 }
537 
538 char *
maker_asahi3_tagname(unsigned short tag,int model)539 maker_asahi3_tagname(unsigned short tag,int model)
540 {
541     char *tagname = CNULL;
542 
543     switch(tag)
544     {
545         case 0x0001: tagname = "CaptureMode"; break;
546         case 0x0002: tagname = "JpegThumbnailDimensions"; break;
547         case 0x0003: tagname = "JpegThumbnailLength"; break;
548         case 0x0004: tagname = "JpegThumbnailOffset"; break;
549         case 0x0006: tagname = "Date"; break;
550         case 0x0007: tagname = "Time"; break;
551         case 0x0008: tagname = "QualityMode"; break;
552         case 0x0009: tagname = "ImageSize"; break;
553         case 0x000B: tagname = "PictureMode"; break;
554         case 0x000D: tagname = "FocusMode"; break;
555         case 0x0014: tagname = "IsoSensitivity"; break;
556         case 0x0017: tagname = "MeteringMode"; break;
557         case 0x0019: tagname = "WhiteBalance"; break;
558         case 0x001D: tagname = "FocalLength"; break;
559         case 0x001E: tagname = "DigitalZoom"; break;
560         case 0x001F: tagname = "Saturation"; break;
561         case 0x0020: tagname = "Contrast"; break;
562         case 0x0021: tagname = "Sharpness"; break;
563         case 0x0029: tagname = "FrameNumber"; break;
564         case 0x0039: tagname = "RawImageSize"; break;
565         case 0x003F: tagname = "LensType"; break;
566         case 0x0200: tagname = "BlackPoint"; break;
567         case 0x0201: tagname = "WhitePoint"; break;
568         case 0x0402: tagname = "ToneCurve"; break;
569         case 0x0403: tagname = "ToneCurves"; break;
570         default: break;
571     }
572     setnotetagset(3);
573     return(tagname);
574 }
575 
576 /* Report the "meaning" of tag values found at offsets in an          */
577 /* Asahi/Pentax MakerNote IFD entry (not at an offset).               */
578 
579 void
asahi1_interpret_value(struct ifd_entry * entry_ptr)580 asahi1_interpret_value(struct ifd_entry *entry_ptr)
581 {
582     int chpr = 0;
583 
584     if(entry_ptr && (PRINT_VALUE))
585     {
586         switch(entry_ptr->tag)
587         {
588             case 0x0001:    /* CaptureMode */
589                 print_startvalue();
590                 switch(entry_ptr->value)
591                 {
592                     case 0: chpr += printf("Auto"); break;
593                     case 1: chpr += printf("Night-scene"); break;
594                     case 2: chpr += printf("Manual"); break;
595                     case 4: chpr += printf("Multiple"); break;
596                     default: break;
597                 }
598                 print_endvalue();
599                 break;
600             case 0x0002:    /* Quality */
601                 print_startvalue();
602                 switch(entry_ptr->value)
603                 {
604                     case 0: chpr += printf("Good"); break;
605                     case 1: chpr += printf("Better"); break;
606                     case 2: chpr += printf("Best"); break;
607                     default: break;
608                 }
609                 print_endvalue();
610                 break;
611             case 0x0003:    /* Focus Mode */
612                 print_startvalue();
613                 switch(entry_ptr->value)
614                 {
615                     case 2: chpr += printf("Custom"); break;
616                     case 3: chpr += printf("Auto"); break;
617                     default: break;
618                 }
619                 print_endvalue();
620                 break;
621             case 0x0004:    /* Flash Mode */
622                 print_startvalue();
623                 switch(entry_ptr->value)
624                 {
625                     case 1: chpr += printf("Auto"); break;
626                     case 2: chpr += printf("On"); break;
627                     case 4: chpr += printf("Off"); break;
628                     case 6: chpr += printf("Red-eye"); break;
629                     default: break;
630                 }
631                 print_endvalue();
632                 break;
633             case 0x0007:    /* White Balance */
634                 print_startvalue();
635                 switch(entry_ptr->value)
636                 {
637                     case 0: chpr += printf("Auto"); break;
638                     case 1: chpr += printf("Daylight"); break;
639                     case 2: chpr += printf("Shade"); break;
640                     case 3: chpr += printf("Tungsten"); break;
641                     case 4: chpr += printf("Fluorescent"); break;
642                     case 5: chpr += printf("Manual"); break;
643                     default: break;
644                 }
645                 print_endvalue();
646                 break;
647             case 0x000a:    /* Digital Zoom */
648                 if(entry_ptr->value == 0)
649                 {
650                     print_startvalue();
651                     chpr += printf("Off");
652                     print_endvalue();
653                 }
654                 break;
655             case 0x000b:    /* Sharpness */
656                 print_startvalue();
657                 switch(entry_ptr->value)
658                 {
659                     case 0: chpr += printf("Normal"); break;
660                     case 1: chpr += printf("Soft"); break;
661                     case 2: chpr += printf("Hard"); break;
662                     default: break;
663                 }
664                 print_endvalue();
665                 break;
666             case 0x000c:    /* Contrast */
667                 print_startvalue();
668                 switch(entry_ptr->value)
669                 {
670                     case 0: chpr += printf("Normal"); break;
671                     case 1: chpr += printf("Low"); break;
672                     case 2: chpr += printf("High"); break;
673                     default: break;
674                 }
675                 print_endvalue();
676                 break;
677             case 0x000d:    /* Saturation */
678                 print_startvalue();
679                 switch(entry_ptr->value)
680                 {
681                     case 0: chpr += printf("Normal"); break;
682                     case 1: chpr += printf("Low"); break;
683                     case 2: chpr += printf("High"); break;
684                     default: break;
685                 }
686                 print_endvalue();
687                 break;
688             case 0x0014:    /* ISO Speed Setting */
689                 print_startvalue();
690                 switch(entry_ptr->value)
691                 {
692                     case 10: chpr += printf("ISO 100"); break;
693                     case 16: chpr += printf("ISO 200"); break;
694                     case 100: chpr += printf("ISO 100"); break;
695                     case 200: chpr += printf("ISO 200"); break;
696                     default: break;
697                 }
698                 print_endvalue();
699                 break;
700             case 0x0017:    /* Color */
701                 print_startvalue();
702                 switch(entry_ptr->value)
703                 {
704                     case 1: chpr += printf("Normal"); break;
705                     case 2: chpr += printf("Black & White"); break;
706                     case 3: chpr += printf("Sepia"); break;
707                     default: break;
708                 }
709                 print_endvalue();
710                 break;
711             default:
712                 break;
713         }
714     }
715     setcharsprinted(chpr);
716 }
717 
718 void
asahi2_interpret_value(struct ifd_entry * entry_ptr)719 asahi2_interpret_value(struct ifd_entry *entry_ptr)
720 {
721     int chpr = 0;
722 
723     if(entry_ptr && (PRINT_VALUE))
724     {
725         switch(entry_ptr->tag)
726         {
727             case 0x0002: /* ThumbnailDimensions" */
728                 chpr += printf(" pixels");
729                 break;
730             case 0x0008: /* QualityMode" */
731                 print_startvalue();
732                 switch(entry_ptr->value)
733                 {
734                     case 1: chpr += printf("Fine"); break;
735                     case 2: chpr += printf("Super Fine"); break;
736                     default: chpr += printf("unknown"); break;
737                 }
738                 print_endvalue();
739                 break;
740             case 0x0009: /* ImageSize" */
741                 print_startvalue();
742                 switch(entry_ptr->value)
743                 {
744                     case 1: chpr += printf("640x480"); break;
745                     case 4: chpr += printf("1600x1200"); break;
746                     case 5: chpr += printf("2048x1536"); break;
747                     case 8: chpr += printf("2560x1920"); break;
748                     case 20: chpr += printf("2288x1712"); break;
749                     case 21: chpr += printf("2592x1944"); break;
750                     case 22: chpr += printf("2304x1728"); break;
751                     case 23: chpr += printf("2296x3056"); break;
752                     case 36: chpr += printf("3008x2008"); break;
753                     default: chpr += printf("unknown"); break;
754                 }
755                 print_endvalue();
756                 break;
757             case 0x000D: /* FocusMode" */
758                 print_startvalue();
759                 switch(entry_ptr->value)
760                 {
761                     case 1: chpr += printf("Normal"); break;
762                     case 2: chpr += printf("Macro"); break;
763                     default: chpr += printf("unknown"); break;
764                 }
765                 print_endvalue();
766                 break;
767             case 0x0014: /* IsoSensitivity" */
768                 print_startvalue();
769                 switch(entry_ptr->value)
770                 {
771                     case 3: chpr += printf("50"); break;
772                     case 4: chpr += printf("64"); break;
773                     case 6: chpr += printf("100"); break;
774                     case 9: chpr += printf("200"); break;
775                     default: chpr += printf("unknown"); break;
776                 }
777                 print_endvalue();
778                 break;
779             case 0x0019: /* WhiteBalance" */
780                 print_startvalue();
781                 switch(entry_ptr->value)
782                 {
783                     case 0: chpr += printf("Auto"); break;
784                     case 1: chpr += printf("Daylight"); break;
785                     case 2: chpr += printf("Shade"); break;
786                     case 3: chpr += printf("Tungsten"); break;
787                     case 4: chpr += printf("Fluorescent"); break;
788                     case 5: chpr += printf("Manual"); break;
789                     default: chpr += printf("unknown"); break;
790                 }
791                 print_endvalue();
792                 break;
793             case 0x001D: chpr += printf(" x .1 mm"); break;
794             case 0x001F: /* Saturation" */
795                 print_startvalue();
796                 switch(entry_ptr->value)
797                 {
798                     case 0: chpr += printf("-1"); break;
799                     case 1: chpr += printf("Normal"); break;
800                     case 2: chpr += printf("+1"); break;
801                     default: chpr += printf("unknown"); break;
802                 }
803                 print_endvalue();
804                 break;
805             case 0x0020: /* Contrast" */
806                 print_startvalue();
807                 switch(entry_ptr->value)
808                 {
809                     case 0: chpr += printf("-1"); break;
810                     case 1: chpr += printf("Normal"); break;
811                     case 2: chpr += printf("+1"); break;
812                     default: chpr += printf("unknown"); break;
813                 }
814                 print_endvalue();
815                 break;
816             case 0x0021: /* Sharpness" */
817                 print_startvalue();
818                 switch(entry_ptr->value)
819                 {
820                     case 0: chpr += printf("-1"); break;
821                     case 1: chpr += printf("Normal"); break;
822                     case 2: chpr += printf("+1"); break;
823                     default: chpr += printf("unknown"); break;
824                 }
825                 print_endvalue();
826                 break;
827             case 0x2012: /* WhiteBalance" */
828                 print_startvalue();
829                 switch(entry_ptr->value)
830                 {
831                     case 0: chpr += printf("Manual"); break;
832                     case 1: chpr += printf("Auto"); break;
833                     case 4: chpr += printf("Flash"); break;
834                     case 12: chpr += printf("Flash"); break;
835                     default: chpr += printf("unknown"); break;
836                 }
837                 print_endvalue();
838                 break;
839             case 0x2022: /* ObjectDistance" */
840                 chpr += printf("mm");
841                 break;
842             case 0x2034: /* FlashDistance" */
843 #if 0
844     Off?
845                 if(entry_ptr->value == 0)
846                 {
847                     print_startvalue();
848                     chpr += printf("Off");
849                     print_endvalue();
850                 }
851 #endif
852                 break;
853             case 0x3000: /* RecordMode" */
854                 print_startvalue();
855                 switch(entry_ptr->value)
856                 {
857                     case 2: chpr += printf("Normal"); break;
858                     default: chpr += printf("unknown"); break;
859                 }
860                 print_endvalue();
861                 break;
862             case 0x3001: /* SelfTimer?" */
863                 print_startvalue();
864                 switch(entry_ptr->value)
865                 {
866                     case 1: chpr += printf("Off"); break;
867                     default: chpr += printf("unknown"); break;
868                 }
869                 print_endvalue();
870                 break;
871             case 0x3002: /* Quality" */
872                 print_startvalue();
873                 switch(entry_ptr->value)
874                 {
875                     case 1: chpr += printf("Economy"); break;
876                     case 2: chpr += printf("Normal"); break;
877                     case 3: chpr += printf("Fine"); break;
878                     default: chpr += printf("unknown"); break;
879                 }
880                 print_endvalue();
881                 break;
882             case 0x3003: /* FocusMode" */
883                 print_startvalue();
884                 switch(entry_ptr->value)
885                 {
886                     case 1: chpr += printf("Fixed"); break;
887                     case 3: chpr += printf("Single-Area Auto"); break;
888                     case 6: chpr += printf("Multi-Area Auto"); break;
889                     default: chpr += printf("unknown"); break;
890                 }
891                 print_endvalue();
892                 break;
893             case 0x3007: /* BestshotMode" */
894                 print_startvalue();
895                 switch(entry_ptr->value)
896                 {
897                     case 0: chpr += printf("Off"); break;
898                     default: chpr += printf("unknown"); break;
899                 }
900                 print_endvalue();
901                 break;
902             case 0x3015: /* ColorMode" */
903                 print_startvalue();
904                 switch(entry_ptr->value)
905                 {
906                     case 0: chpr += printf("Off*"); break;
907                     default: chpr += printf("unknown"); break;
908                 }
909                 print_endvalue();
910                 break;
911             case 0x3016: /* Enhancement" */
912                 print_startvalue();
913                 switch(entry_ptr->value)
914                 {
915                     case 0: chpr += printf("Off"); break;
916                     default: chpr += printf("unknown"); break;
917                 }
918                 print_endvalue();
919                 break;
920             case 0x3017: /* Filter" */
921                 print_startvalue();
922                 switch(entry_ptr->value)
923                 {
924                     case 0: chpr += printf("Off"); break;
925                     default: chpr += printf("unknown"); break;
926                 }
927                 print_endvalue();
928                 break;
929             default: break;
930         }
931     }
932     setcharsprinted(chpr);
933 }
934 
935 void
asahi3_interpret_value(struct ifd_entry * entry_ptr)936 asahi3_interpret_value(struct ifd_entry *entry_ptr)
937 {
938     int year,month,day;
939     int chpr = 0;
940 
941     if(entry_ptr && (PRINT_VALUE))
942     {
943         switch(entry_ptr->tag)
944         {
945             case 0x0001:    /* CaptureMode */
946                 print_startvalue();
947                 switch(entry_ptr->value)
948                 {
949                     case 0: chpr += printf("Auto"); break;
950                     case 1: chpr += printf("Night-scene"); break;
951                     case 2: chpr += printf("Manual"); break;
952                     case 4: chpr += printf("Multiple"); break;
953                     default: break;
954                 }
955                 print_endvalue();
956                 break;
957             case 0x0002: /* ThumbnailDimensions" */
958                 chpr += printf(" pixels");
959                 break;
960             case 0x0006:
961                 year = ((entry_ptr->value & 0xff) << 8) | ((entry_ptr->value & 0xff00) >> 8);
962                 month = ((entry_ptr->value & 0xff0000) >> 16) & 0x7f;
963                 day = ((entry_ptr->value & 0xff000000) >> 24) & 0x7f;
964                 chpr += printf(" = %4d:%02d:%02d",year,month,day);
965                 break;
966             case 0x0008: /* QualityMode" */
967                 print_startvalue();
968                 switch(entry_ptr->value)
969                 {
970                     case 0: chpr += printf("Good"); break;
971                     case 1: chpr += printf("Better"); break;
972                     case 2: chpr += printf("Best"); break;
973                     case 3: chpr += printf("TIFF"); break;
974                     case 4: chpr += printf("RAW"); break;
975                     default: chpr += printf("unknown"); break;
976                 }
977                 print_endvalue();
978                 break;
979             case 0x0009: /* ImageSize" */
980                 print_startvalue();
981                 switch(entry_ptr->value)
982                 {
983                     case 0: chpr += printf("640x480"); break;
984                     case 1: chpr += printf("Full"); break;
985                     case 2: chpr += printf("1024x768"); break;
986                     case 4: chpr += printf("1600x1200"); break;
987                     case 5: chpr += printf("2048x1536"); break;
988                     case 20: chpr += printf("2288x1712"); break;
989                     case 21: chpr += printf("2592x1944"); break;
990                     case 22: chpr += printf("2304x1728"); break;
991                     case 36: chpr += printf("3008x2008"); break;
992                     default: chpr += printf("unknown"); break;
993                 }
994                 print_endvalue();
995                 break;
996             case 0x000D: /* FocusMode" */
997                 print_startvalue();
998                 switch(entry_ptr->value)
999                 {
1000                     case 0: chpr += printf("Normal"); break;
1001                     case 1: chpr += printf("Macro(1)"); break;
1002                     case 2: chpr += printf("Macro(2)"); break;
1003                     case 3: chpr += printf("Infinity"); break;
1004                     default: chpr += printf("unknown"); break;
1005                 }
1006                 print_endvalue();
1007                 break;
1008             case 0x0014: /* IsoSensitivity" */
1009                 print_startvalue();
1010                 switch(entry_ptr->value)
1011                 {
1012                     case 3: chpr += printf("50"); break;
1013                     case 4: chpr += printf("64"); break;
1014                     case 6: chpr += printf("100"); break;
1015                     case 9: chpr += printf("200"); break;
1016                     case 12: chpr += printf("400"); break;
1017                     case 15: chpr += printf("800"); break;
1018                     case 18: chpr += printf("1600"); break;
1019                     case 21: chpr += printf("3200"); break;
1020                     case 50: chpr += printf("50"); break;
1021                     case 100: chpr += printf("100"); break;
1022                     case 200: chpr += printf("200"); break;
1023                     case 400: chpr += printf("400"); break;
1024                     case 800: chpr += printf("800"); break;
1025                     case 1600: chpr += printf("1600"); break;
1026                     case 3200: chpr += printf("3200"); break;
1027                     default: chpr += printf("unknown"); break;
1028                 }
1029                 print_endvalue();
1030                 break;
1031             case 0x0017: /* MeteringMode" */
1032                 print_startvalue();
1033                 switch(entry_ptr->value)
1034                 {
1035                     case 0: chpr += printf("Multi Segment"); break;
1036                     case 1: chpr += printf("Center Weighted"); break;
1037                     case 2: chpr += printf("Spot"); break;
1038                     default: chpr += printf("unknown"); break;
1039                 }
1040                 print_endvalue();
1041                 break;
1042             case 0x0019: /* WhiteBalance" */
1043                 print_startvalue();
1044                 switch(entry_ptr->value)
1045                 {
1046                     case 0: chpr += printf("Auto"); break;
1047                     case 1: chpr += printf("Daylight"); break;
1048                     case 2: chpr += printf("Shade"); break;
1049                     case 3: chpr += printf("Fluorescent"); break;
1050                     case 4: chpr += printf("Tungsten"); break;
1051                     case 5: chpr += printf("Manual"); break;
1052                     default: chpr += printf("unknown"); break;
1053                 }
1054                 print_endvalue();
1055                 break;
1056             case 0x001D: chpr += printf(" x .1 mm");
1057                 break;
1058 
1059             case 0x001F: /* Saturation" */
1060                 print_startvalue();
1061                 switch(entry_ptr->value)
1062                 {
1063                     case 0: chpr += printf("Normal"); break;
1064                     case 1: chpr += printf("Low"); break;
1065                     case 2: chpr += printf("High"); break;
1066                     default: chpr += printf("unknown"); break;
1067                 }
1068                 print_endvalue();
1069                 break;
1070             case 0x0020: /* Contrast" */
1071                 print_startvalue();
1072                 switch(entry_ptr->value)
1073                 {
1074                     case 0: chpr += printf("Normal"); break;
1075                     case 1: chpr += printf("Low"); break;
1076                     case 0x10: chpr += printf("Low"); break;
1077                     case 2: chpr += printf("High"); break;
1078                     case 0x20: chpr += printf("High"); break;
1079                     case 3: chpr += printf("Medium Low"); break;
1080                     case 0x30: chpr += printf("Medium High"); break;
1081                     default: chpr += printf("unknown"); break;
1082                 }
1083                 print_endvalue();
1084                 break;
1085             case 0x0021: /* Sharpness" */
1086                 print_startvalue();
1087                 switch(entry_ptr->value)
1088                 {
1089                     case 0: chpr += printf("Normal"); break;
1090                     case 1: chpr += printf("Soft"); break;
1091                     case 0x10: chpr += printf("Soft"); break;
1092                     case 2: chpr += printf("Hard"); break;
1093                     case 0x20: chpr += printf("Hard"); break;
1094                     case 3: chpr += printf("Medium Soft"); break;
1095                     case 0x30: chpr += printf("Medium Hard"); break;
1096                     default: chpr += printf("unknown"); break;
1097                 }
1098                 print_endvalue();
1099                 break;
1100             default: break;
1101         }
1102     }
1103     setcharsprinted(chpr);
1104 }
1105 
1106 /* Some makernotes record offsets as LONG values rather than simply   */
1107 /* using UNDEFINED with a size; the same technique used for           */
1108 /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc.          */
1109 /* This routine hardcodes such tags so that the print_makerentry()    */
1110 /* routine will present them as offsets.                              */
1111 
1112 /* Asahi has the unfortunate characteristic that tag numbers are      */
1113 /* re-used for different purposes in the second version, and one of   */
1114 /* those tags is an offset masquerading as a long.                    */
1115 
1116 int
maker_asahi_value_is_offset(struct ifd_entry * entry_ptr,int model)1117 maker_asahi_value_is_offset(struct ifd_entry *entry_ptr,int model)
1118 {
1119     int is_offset = 0;
1120     int noteversion = 0;
1121 
1122     if(entry_ptr)
1123     {
1124         noteversion = getnoteversion();
1125 
1126         switch(noteversion)
1127         {
1128             case 2:
1129                 switch(entry_ptr->tag)
1130                 {
1131                     case 0x0004: is_offset = 1; break;
1132                     default: break;
1133                 }
1134                 break;
1135             case 3:
1136                 /* A negative value here forces call of the maker offset  */
1137                 /* value routine, so that the routine may record          */
1138                 /* information it will need later; the value is not       */
1139                 /* treated as an offset.                                  */
1140                 switch(entry_ptr->tag)
1141                 {
1142                     case 0x0003: is_offset = -1; break;
1143                     case 0x0004: is_offset = 1; break;
1144                     default: break;
1145                 }
1146                 break;
1147             case 1:
1148             default:
1149                 break;
1150         }
1151     }
1152 
1153     return(is_offset);
1154 }
1155 
1156 /*
1157     Tagset 1: 0x01-0x19,0xE00,0x1000,0x1001  330,430
1158     Tagset 2: 0x02-0x04,0x2000-0x2003,0x2011-0x2013,0x2021-0x2023,0x2031-0x2034,03000-0x3007,0x3011-0x3018
1159                (first 4 tags thumbnail, even jpeg, both methods)  330RS,430RS
1160     Tagset 3: 0x01-0x0029,0x0E00,0x002E,...,0x002A,0x002C,0x0031,0x0032  Optio550
1161     Tagset 3: 0x01-0x0029,....0x0049,0x0200-0x0216,0x03FF,0x0402  starist
1162                 (CaptureMode, next 3 thumbnail, dim/length/offset), date & time (6,7)
1163  */
1164