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_casio.c,v 1.19 2005/07/24 22:56:26 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Casio camera maker-specific routines.                              */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* Most of the information coded here is due to Eckhard Henkel        */
17 /* (eckhard.henkel@t-online.de) as shown by TsuruZoh Tachibanaya at:  */
18 /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html   */
19 /* (now found at:                                                     */
20 /*   http://landscapeimage.com/ThumbHTML/help/exif_file_format.html)  */
21 /* Additional information:                                            */
22 /*  http://www.dicasoft.de/casiomn.htm                                */
23 
24 /* EP-600 info: (added Jan 05)                                        */
25 /* evan@ozhiker.com                                                   */
26 /*    http://www.ozhiker.com/electronics/pjmt/jpeg_info/casio_mn.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 
43 extern struct camera_id casio_model_id[];
44 
45 int
casio_model_number(char * model,char * software)46 casio_model_number(char *model,char *software)
47 {
48     struct camera_id *model_id;
49     int number = NO_MODEL;
50 
51     for(model_id = &casio_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 /* Determine and set note version from detected scheme.               */
65 /* Notes with ID scheme use noteversion 2                             */
66 /* Notes with Plain use noteversion 1                                 */
67 
68 int
set_casio_noteversion()69 set_casio_noteversion()
70 {
71     struct maker_scheme *scheme;
72     int noteversion = 0;
73     int tagset = 0;
74 
75     scheme = retrieve_makerscheme();
76     if(scheme->note_version <= 0)
77     {
78         noteversion = -1;
79         tagset = -1;
80         switch(scheme->scheme_type)
81         {
82             case HAS_ID_SCHEME:     /* "QVC" */
83                 tagset = 2;
84                 noteversion = 2;
85                 break;
86             case PLAIN_IFD_SCHEME:
87                 tagset = 1;
88                 noteversion = 1;
89                 break;
90             case UNKNOWN_SCHEME:
91                 break;
92             default:
93                 break;
94         }
95         setnotetagset(tagset);
96         setnoteversion(noteversion);
97     }
98     else
99         noteversion = scheme->note_version;
100     return(noteversion);
101 }
102 
103 
104 /* Dispatch a Casio print routine based upon noteversion              */
105 
106 void
print_casio_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)107 print_casio_makervalue(struct ifd_entry *entry_ptr,int make, int model,
108                     char *prefix)
109 {
110     int noteversion = 0;
111 
112     noteversion = getnoteversion();
113 
114     if(entry_ptr && (PRINT_VALUE))
115     {
116         switch(noteversion)
117         {
118             case 2:
119                 print_casio1_makervalue(entry_ptr,make,model,prefix);
120                 casio2_interpret_value(entry_ptr);
121                 break;
122             case 1:
123                 print_casio1_makervalue(entry_ptr,make,model,prefix);
124                 casio1_interpret_value(entry_ptr);
125                 break;
126             default:
127                 print_value(entry_ptr,PREFIX);
128                 break;
129         }
130     }
131 }
132 
133 /* Model-specific print routine for Casio cameras. This routine is    */
134 /* responsible for picking off any direct entry tags which are        */
135 /* peculiar and will not be handled properly by print_value()         */
136 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
137 /* there are no such entries, this function simply calls              */
138 /* print_value().                                                     */
139 
140 void
print_casio1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)141 print_casio1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
142                     char *prefix)
143 {
144     if(entry_ptr && (PRINT_VALUE))
145     {
146         switch(entry_ptr->tag)
147         {
148             default:
149                 print_value(entry_ptr,PREFIX);
150                 break;
151         }
152     }
153 }
154 
155 
156 /* Dispatch a routine to decode and print offset values for Casio     */
157 /* cameras.                                                           */
158 
159 void
print_casio_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)160 print_casio_offset_makervalue(FILE *inptr,unsigned short byteorder,
161     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
162     struct image_summary *summary_entry,char *parent_name,char*prefix,
163     int indent,int make,int model,int at_offset)
164 {
165     int noteversion = 0;
166 
167     noteversion = getnoteversion();
168 
169     if(entry_ptr)
170     {
171         switch(noteversion)
172         {
173             case 1:
174                 casio1_offset_makervalue(inptr,byteorder,entry_ptr,
175                                             fileoffset_base,summary_entry,
176                                             parent_name,prefix,indent,
177                                             make,model,at_offset);
178                 break;
179             case 2:
180                 casio2_offset_makervalue(inptr,byteorder,entry_ptr,
181                                             fileoffset_base,summary_entry,
182                                             parent_name,prefix,indent,
183                                             make,model,at_offset);
184                 break;
185             default:
186                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
187                                         fileoffset_base,parent_name,prefix,
188                                         indent,make,model,at_offset);
189                 break;
190         }
191     }
192 }
193 
194 /* Model-specific routine to print UNDEFINED values found at offsets  */
195 /* in Casio makernotes.                                               */
196 
197 void
casio1_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)198 casio1_offset_makervalue(FILE *inptr,unsigned short byteorder,
199     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
200     struct image_summary *summary_entry,char *parent_name,char*prefix,
201     int indent,int make,int model,int at_offset)
202 {
203     char *nameoftag;
204     unsigned long value_offset,current_offset;
205     unsigned long count;
206     int chpr = 0;
207     char *fulldirname = NULL;
208 
209     if(entry_ptr)
210     {
211         value_offset = fileoffset_base + entry_ptr->value;
212         nameoftag = maker_tagname(entry_ptr->tag,make,model);
213         fulldirname = splice(parent_name,".",nameoftag);
214         count = entry_ptr->count;
215 
216         switch(entry_ptr->tag)
217         {
218             case 0x0e00: /* PrintIM (Epson Print Image matching)  */
219                 if(!at_offset && (PRINT_VALUE))
220                 {
221                     if(!(PRINT_OFFSET))
222                     {
223                         chpr += printf("@%lu:%lu",value_offset,count);
224                         chpr = newline(chpr);
225                     }
226                 }
227                 current_offset = ftell(inptr);
228                 if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
229                     count,nameoftag,parent_name,prefix,indent) == 0)
230                 {
231                     /* At least one QV4000 image uses a PIM offset    */
232                     /* relative to the entry address, even though     */
233                     /* other entries in the note are TIFF-relative;   */
234                     /* check for a PIM entry at that location if the  */
235                     /* previous one failed. GROSS HACK!               */
236                     fileoffset_base = current_offset - 12;
237                     PUSHCOLOR(HI_BLACK);
238                     chpr += printf(" checking for entry-relative offset bug");
239                     POPCOLOR();
240                     if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
241                                     count,nameoftag,parent_name,
242                                     prefix,indent))
243                     {
244                         if(!(PRINT_SECTION))
245                         {
246                             chpr = newline(chpr);
247                             printred("# WARNING:");
248                         }
249                         PUSHCOLOR(HI_BLACK);
250                         chpr += printf(" %s data found at offset %lu - ",nameoftag,
251                                                 entry_ptr->value + fileoffset_base);
252                         printred("start offset is incorrect!");
253                         POPCOLOR();
254                         if(!(PRINT_SECTION))
255                         {
256                             chpr = newline(chpr);
257                             print_filename();
258                             if((PRINT_TAGINFO))
259                             {
260                                 if((PRINT_LONGNAMES))
261                                     chpr += printf("%s.",fulldirname);
262                                 chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag);
263                             }
264                             if((PRINT_VALUE))
265                                 chpr += printf(" = @%lu:%lu",entry_ptr->value + fileoffset_base,
266                                                                                         count);
267                         }
268                     }
269                 }
270                 break;
271             default:
272                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
273                                         fileoffset_base,fulldirname,prefix,indent,
274                                         make,model,at_offset);
275                 break;
276         }
277         if(fulldirname)
278             free(fulldirname);
279     }
280     setcharsprinted(chpr);
281 }
282 
283 void
casio2_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)284 casio2_offset_makervalue(FILE *inptr,unsigned short byteorder,
285     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
286     struct image_summary *summary_entry,char *parent_name,char*prefix,
287     int indent,int make,int model,int at_offset)
288 {
289     unsigned long value_offset,current_offset;
290     unsigned long count;
291     unsigned short marker;
292     char *nameoftag;
293     char *fulldirname = NULL;
294     unsigned long max_offset = 0;
295     int status = 0;
296     int chpr = 0;
297 
298     if(entry_ptr)
299     {
300         nameoftag = maker_tagname(entry_ptr->tag,make,model);
301         fulldirname = splice(parent_name,".",nameoftag);
302         value_offset = fileoffset_base + entry_ptr->value;
303         count = entry_ptr->count;
304 
305         switch(entry_ptr->tag)
306         {
307             case 0x0004:    /* JpegThumbnailOffset                    */
308                 /* When this tag is present, the 0x2000 tag is        */
309                 /* present as well. Both entries point to the same    */
310                 /* thumbnail, so just print values for length and     */
311                 /* offset tags, and display the thumbnail on the      */
312                 /* (self-contained) 0x2000 tag                        */
313                 if(!at_offset && (PRINT_VALUE))
314                 {
315                     if(!(PRINT_OFFSET))
316                         chpr += printf("@%lu",value_offset);
317                 }
318                 break;
319             case 0x2000:   /* JpegThumbnail                           */
320                 if(at_offset && (PRINT_SECTION))
321                 {
322                     print_tag_address(SECTION,value_offset,indent,prefix);
323                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
324                     chpr += printf(" length %ld",count);
325                 }
326                 else if(!at_offset && (PRINT_VALUE))
327                 {
328                     if(!(PRINT_OFFSET))
329                         chpr += printf("@%lu:%lu",value_offset,entry_ptr->count);
330                     else
331                         chpr += printf("length %lu", entry_ptr->count);
332                 }
333                 if((PRINT_SECTION) || (PRINT_SEGMENT))
334                     chpr = newline(chpr);
335                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
336                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
337                                     count,summary_entry,fulldirname,
338                                     prefix,indent+SMALLINDENT);
339                 if(at_offset)
340                 {
341                     if((PRINT_SECTION))
342                     {
343                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
344                             chpr = newline(chpr);
345                         jpeg_status(status);
346                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
347                                                     indent,prefix);
348                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
349                         if((PRINT_ENTRY) && !(PRINT_VALUE))
350                             chpr = newline(chpr);
351                     }
352                 }
353                 print_jpeg_status();
354                 if(marker && summary_entry)
355                 {
356                     /* The new one is on the end of the chain         */
357                     if((summary_entry = last_summary_entry(summary_entry)))
358                     {
359                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
360                         summary_entry->datatype = MAKER_IFD;
361                         summary_entry->subfiletype = THUMBNAIL_TYPE;
362                     }
363                 }
364                 /* make certain we're at the end                      */
365                 clearerr(inptr);
366                 fseek(inptr,value_offset + count,0);
367                 break;
368             case 0x0e00: /* PrintIM (Epson Print Image matching)  */
369                 nameoftag = maker_tagname(entry_ptr->tag,make,model);
370                 if(!at_offset && (PRINT_VALUE))
371                 {
372                     if(!(PRINT_OFFSET))
373                         chpr += printf("@%lu",value_offset);
374                 }
375                 current_offset = ftell(inptr);
376                 if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
377                     entry_ptr->count,nameoftag,parent_name,prefix,indent) == 0)
378                 {
379                     /* At least one QV4000 image uses a PIM offset    */
380                     /* relative to the entry address, even though     */
381                     /* other entries in the note are TIFF-relative;   */
382                     /* check for a PIM entry at that location if the  */
383                     /* previous one failed. GROSS HACK!               */
384                     fileoffset_base = current_offset - 12;
385                     PUSHCOLOR(HI_BLACK);
386                     /* We've already seen an error message            */
387                     chpr += printf(" checking for entry-relative offset bug");
388                     POPCOLOR();
389                     if(process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
390                                     entry_ptr->count,nameoftag,parent_name,
391                                     prefix,indent))
392                     {
393                         if(!(PRINT_OFFSET))
394                         {
395                             chpr = newline(chpr);
396                             chpr += printf("# WARNING:");
397                         }
398                         PUSHCOLOR(HI_BLACK);
399                         chpr += printf(" PrintImage data found at offset %lu - ",
400                                                     entry_ptr->value + fileoffset_base);
401                         printred("start offset is incorrect!");
402                         POPCOLOR();
403                         if(!(PRINT_SECTION))
404                         {
405                             chpr = newline(chpr);
406                             print_tag_address(VALUE_AT_OFFSET,entry_ptr->value + fileoffset_base,
407                                                         indent,"-");
408                             if((PRINT_TAGINFO))
409                             {
410                                 if((PRINT_LONGNAMES))
411                                     chpr += printf("%s.",fulldirname);
412                                 chpr += printf("%-*.*s",MAKERTAGWIDTH,MAKERTAGWIDTH,nameoftag);
413                             }
414                             if((PRINT_VALUE))
415                                 chpr += printf(" = @%lu",entry_ptr->value + fileoffset_base);
416                         }
417                     }
418                 }
419                 break;
420             default:
421                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
422                                         fileoffset_base,fulldirname,prefix,indent,
423                                         make,model,at_offset);
424                 break;
425         }
426         if(fulldirname)
427             free(fulldirname);
428     }
429     setcharsprinted(chpr);
430 }
431 
432 
433 /* Casio-specific tagnames for makernotes.                            */
434 
435 /* The tagname routine is the first place in the code path which      */
436 /* requires knowledge of the note version. If the version is not      */
437 /* given in the model table (e.g. the model is unknown), then switch  */
438 /* code in find_maker_scheme() should have set it. This routine       */
439 /* repeats the check for non-zero noteversion and is prepared to set  */
440 /* the noteversion first time through, but should never need to do    */
441 /* so. Noteversion should always be non-zero; it should be set to -1  */
442 /* if generic processing is required.                                 */
443 
444 char *
maker_casio_tagname(unsigned short tag,int model)445 maker_casio_tagname(unsigned short tag,int model)
446 {
447     char *tagname = (char *)0;
448     int noteversion = 0;
449 
450     if((noteversion = getnoteversion()) == 0)
451     {
452         noteversion = set_casio_noteversion();
453         setnoteversion(noteversion);
454     }
455 
456     /* Check noteversions first                                       */
457     switch(noteversion)
458     {
459         case 1:
460             tagname = maker_casio1_tagname(tag,model);
461             break;
462         case 2:
463             tagname = maker_casio2_tagname(tag,model);
464             break;
465         default:
466             break;
467     }
468 
469     /* If no version-specific tag is found, check "generic" tags      */
470     if(tagname == NULL)
471     {
472         switch(tag)
473         {
474             case 0x0e00: tagname = "PrintIM"; break;
475             default: break;
476         }
477     }
478     return(tagname);
479 }
480 
481 
482 char *
maker_casio1_tagname(unsigned short tag,int model)483 maker_casio1_tagname(unsigned short tag,int model)
484 {
485     char *tagname = CNULL;
486 
487     switch(tag)
488     {
489         case 0x0001: tagname = "RecordingMode"; break;
490         case 0x0002: tagname = "Quality"; break;
491         case 0x0003: tagname = "FocusingMode"; break;
492         case 0x0004: tagname = "FlashMode"; break;
493         case 0x0005: tagname = "FlashIntensity"; break;
494         case 0x0006: tagname = "ObjectDistance"; break;
495         case 0x0007: tagname = "WhiteBalance"; break;
496         case 0x000a: tagname = "DigitalZoom"; break;
497         case 0x000b: tagname = "Sharpness"; break;
498         case 0x000c: tagname = "Contrast"; break;
499         case 0x000d: tagname = "Saturation"; break;
500         case 0x0014: tagname = "CCDSensitivity"; break;
501         default: break;
502     }
503     setnotetagset(1);
504     return(tagname);
505 }
506 
507 
508 char *
maker_casio2_tagname(unsigned short tag,int model)509 maker_casio2_tagname(unsigned short tag,int model)
510 {
511     char *tagname = CNULL;
512 
513     /* This is the same as Asahi/Pentax note version 2                */
514     switch(tag)
515     {
516         case 0x0002: tagname = "JpegThumbnailDimensions"; break;
517         case 0x0003: tagname = "JpegThumbnailLength"; break;
518         case 0x0004: tagname = "JpegThumbnailOffset"; break;
519         case 0x0008: tagname = "QualityMode"; break;
520         case 0x0009: tagname = "ImageSize"; break;
521         case 0x000D: tagname = "FocusMode"; break;
522         case 0x0014: tagname = "IsoSensitivity"; break;
523         case 0x0019: tagname = "WhiteBalance"; break;
524         case 0x001D: tagname = "FocalLength"; break; /* units .1mm   */
525         case 0x001F: tagname = "Saturation"; break;
526         case 0x0020: tagname = "Contrast"; break;
527         case 0x0021: tagname = "Sharpness"; break;
528         case 0x2000: tagname = "JpegThumbnail"; break;
529         case 0x2011: tagname = "WhiteBalanceBias"; break;
530         case 0x2012: tagname = "WhiteBalance"; break;
531         case 0x2022: tagname = "ObjectDistance"; break;
532         case 0x2034: tagname = "FlashDistance"; break;
533         case 0x3000: tagname = "RecordMode"; break;
534         case 0x3001: tagname = "SelfTimer?"; break;
535         case 0x3002: tagname = "Quality"; break;
536         case 0x3003: tagname = "FocusMode"; break;
537         case 0x3006: tagname = "TimeZone"; break;
538         case 0x3007: tagname = "BestshotMode"; break;
539         case 0x3014: tagname = "CCDSensitivity"; break;
540         case 0x3015: tagname = "ColorMode"; break;
541         case 0x3016: tagname = "Enhancement"; break;
542         case 0x3017: tagname = "Filter"; break;
543         default: break;
544     }
545     setnotetagset(2);
546     return(tagname);
547 }
548 
549 /* Report the "meaning" of tag values found directly in a Casio       */
550 /* MakerNote IFD entry (not at an offset).                            */
551 
552 void
casio1_interpret_value(struct ifd_entry * entry_ptr)553 casio1_interpret_value(struct ifd_entry *entry_ptr)
554 {
555     int chpr = 0;
556 
557     if(entry_ptr && (PRINT_VALUE))
558     {
559         switch(entry_ptr->tag)
560         {
561             case 0x0001:    /* RecordingMode */
562                 print_startvalue();
563                 switch(entry_ptr->value)
564                 {
565                     case 1: chpr += printf("Single Shutter"); break;
566                     case 2: chpr += printf("Panorama"); break;
567                     case 3: chpr += printf("Night Scene"); break;
568                     case 4: chpr += printf("Portrait"); break;
569                     case 5: chpr += printf("Landscape"); break;
570                     default: printred("undefined"); break;
571                 }
572                 print_endvalue();
573                 break;
574             case 0x0002:    /* Quality */
575                 print_startvalue();
576                 switch(entry_ptr->value)
577                 {
578                     case 1: chpr += printf("Economy"); break;
579                     case 2: chpr += printf("Normal"); break;
580                     case 3: chpr += printf("Fine"); break;
581                     default: printred("undefined"); break;
582                 }
583                 print_endvalue();
584                 break;
585             case 0x0003:    /* Focusing Mode */
586                 print_startvalue();
587                 switch(entry_ptr->value)
588                 {
589                     case 2: chpr += printf("Macro"); break;
590                     case 3: chpr += printf("Auto"); break;
591                     case 4: chpr += printf("Manual"); break;
592                     case 5: chpr += printf("Infinity"); break;
593                     default: printred("undefined"); break;
594                 }
595                 print_endvalue();
596                 break;
597             case 0x0004:    /* Flash Mode */
598                 print_startvalue();
599                 switch(entry_ptr->value)
600                 {
601                     case 1: chpr += printf("Auto"); break;
602                     case 2: chpr += printf("On"); break;
603                     case 3: chpr += printf("Off"); break;
604                     case 4: chpr += printf("Redeye"); break;
605                     default: printred("undefined"); break;
606                 }
607                 print_endvalue();
608                 break;
609             case 0x0005:    /* Flash Intensity */
610                 print_startvalue();
611                 switch(entry_ptr->value)
612                 {
613                     case 11: chpr += printf("Weak"); break;
614                     case 13: chpr += printf("Normal"); break;
615                     case 15: chpr += printf("Strong"); break;
616                     default: printred("undefined"); }
617                 break;
618             case 0x0006:    /* Object Distance */
619                 PUSHCOLOR(UNCERTAIN_COLOR);
620                 chpr += printf(" mm");
621                 POPCOLOR();
622                 break;
623             case 0x0007:    /* White Balance */
624                 print_startvalue();
625                 switch(entry_ptr->value)
626                 {
627                     case 1: chpr += printf("Auto"); break;
628                     case 2: chpr += printf("Tungsten"); break;
629                     case 3: chpr += printf("Daylight"); break;
630                     case 4: chpr += printf("Fluorescent"); break;
631                     case 5: chpr += printf("Shade"); break;
632                     case 129: chpr += printf("Manual"); break;
633                     default: printred("undefined"); break;
634                 }
635                 print_endvalue();
636                 break;
637             case 0x000a:    /* Digital Zoom */
638                 print_startvalue();
639                 switch(entry_ptr->value)
640                 {
641                     case 0x10000: chpr += printf("Off"); break;
642                     case 0x10001: chpr += printf("On"); break;
643                     default: printred("undefined"); break;
644                 }
645                 print_endvalue();
646                 break;
647             case 0x000b:    /* Sharpness */
648                 print_startvalue();
649                 switch(entry_ptr->value)
650                 {
651                     case 0: chpr += printf("Normal"); break;
652                     case 1: chpr += printf("Soft"); break;
653                     case 2: chpr += printf("Hard"); break;
654                     default: printred("undefined"); break;
655                 }
656                 print_endvalue();
657                 break;
658             case 0x000c:    /* Contrast */
659                 print_startvalue();
660                 switch(entry_ptr->value)
661                 {
662                     case 0: chpr += printf("Normal"); break;
663                     case 1: chpr += printf("Low"); break;
664                     case 2: chpr += printf("High"); break;
665                     default: printred("undefined"); break;
666                 }
667                 print_endvalue();
668                 break;
669             case 0x000d:    /* Saturation */
670                 print_startvalue();
671                 switch(entry_ptr->value)
672                 {
673                     case 0: chpr += printf("Normal"); break;
674                     case 1: chpr += printf("Low"); break;
675                     case 2: chpr += printf("High"); break;
676                     default: printred("undefined"); break;
677                 }
678                 print_endvalue();
679                 break;
680             default:
681                 break;
682         }
683     }
684     setcharsprinted(chpr);
685 }
686 
687 void
casio2_interpret_value(struct ifd_entry * entry_ptr)688 casio2_interpret_value(struct ifd_entry *entry_ptr)
689 {
690     int chpr = 0;
691 
692     if(entry_ptr && (PRINT_VALUE))
693     {
694         switch(entry_ptr->tag)
695         {
696             case 0x0002: /* ThumbnailDimensions" */
697                 chpr += printf(" pixels");
698                 break;
699             case 0x0008: /* QualityMode" */
700                 print_startvalue();
701                 switch(entry_ptr->value)
702                 {
703                     case 1: chpr += printf("Fine"); break;
704                     case 2: chpr += printf("Super Fine"); break;
705                     default: chpr += printf("unknown"); break;
706                 }
707                 print_endvalue();
708                 break;
709             case 0x0009: /* ImageSize" */
710                 print_startvalue();
711                 switch(entry_ptr->value)
712                 {
713                     case 1: chpr += printf("640x480"); break;
714                     case 4: chpr += printf("1600x1200"); break;
715                     case 5: chpr += printf("2048x1536"); break;
716                     case 20: chpr += printf("2288x1712"); break;
717                     case 21: chpr += printf("2592x1944"); break;
718                     case 22: chpr += printf("2304x1728"); break;
719                     case 36: chpr += printf("3008x2008"); break;
720                     default: chpr += printf("unknown"); break;
721                 }
722                 print_endvalue();
723                 break;
724             case 0x000D: /* FocusMode" */
725                 print_startvalue();
726                 switch(entry_ptr->value)
727                 {
728                     case 1: chpr += printf("Normal"); break;
729                     case 2: chpr += printf("Macro"); break;
730                     default: chpr += printf("unknown"); break;
731                 }
732                 print_endvalue();
733                 break;
734             case 0x0014: /* IsoSensitivity" */
735                 print_startvalue();
736                 switch(entry_ptr->value)
737                 {
738                     case 3: chpr += printf("50"); break;
739                     case 4: chpr += printf("64"); break;
740                     case 6: chpr += printf("100"); break;
741                     case 9: chpr += printf("200"); break;
742                     default: chpr += printf("unknown"); break;
743                 }
744                 print_endvalue();
745                 break;
746             case 0x0019: /* WhiteBalance" */
747                 print_startvalue();
748                 switch(entry_ptr->value)
749                 {
750                     case 1: chpr += printf("Fine"); break;
751                     case 2: chpr += printf("Shade"); break;
752                     case 3: chpr += printf("Tungsten"); break;
753                     case 4: chpr += printf("Fluorescent"); break;
754                     case 5: chpr += printf("Manual"); break;
755                     default: chpr += printf("unknown"); break;
756                 }
757                 print_endvalue();
758                 break;
759             /* rational? case 0x001D: tagname = "FocalLength"; break;  units .1mm   */
760             case 0x001F: /* Saturation" */
761                 print_startvalue();
762                 switch(entry_ptr->value)
763                 {
764                     case 0: chpr += printf("-1"); break;
765                     case 1: chpr += printf("Normal"); break;
766                     case 2: chpr += printf("+1"); break;
767                     default: chpr += printf("unknown"); break;
768                 }
769                 print_endvalue();
770                 break;
771             case 0x0020: /* Contrast" */
772                 print_startvalue();
773                 switch(entry_ptr->value)
774                 {
775                     case 0: chpr += printf("-1"); break;
776                     case 1: chpr += printf("Normal"); break;
777                     case 2: chpr += printf("+1"); break;
778                     default: chpr += printf("unknown"); break;
779                 }
780                 print_endvalue();
781                 break;
782             case 0x0021: /* Sharpness" */
783                 print_startvalue();
784                 switch(entry_ptr->value)
785                 {
786                     case 0: chpr += printf("-1"); break;
787                     case 1: chpr += printf("Normal"); break;
788                     case 2: chpr += printf("+1"); break;
789                     default: chpr += printf("unknown"); break;
790                 }
791                 print_endvalue();
792                 break;
793             case 0x2012: /* WhiteBalance" */
794                 print_startvalue();
795                 switch(entry_ptr->value)
796                 {
797                     case 0: chpr += printf("Manual"); break;
798                     case 1: chpr += printf("Auto"); break;
799                     case 4: chpr += printf("Flash"); break;
800                     case 12: chpr += printf("Flash"); break;
801                     default: chpr += printf("unknown"); break;
802                 }
803                 print_endvalue();
804                 break;
805             case 0x2022: /* ObjectDistance" */
806                 chpr += printf("mm");
807                 break;
808             case 0x2034: /* FlashDistance" */
809 #if 0
810     Off?
811                 if(entry_ptr->value == 0)
812                 {
813                     print_startvalue();
814                     chpr += printf("Off");
815                     print_endvalue();
816                 }
817 #endif
818                 break;
819             case 0x3000: /* RecordMode" */
820                 print_startvalue();
821                 switch(entry_ptr->value)
822                 {
823                     case 2: chpr += printf("Normal"); break;
824                     default: chpr += printf("unknown"); break;
825                 }
826                 print_endvalue();
827                 break;
828             case 0x3001: /* SelfTimer?" */
829                 print_startvalue();
830                 switch(entry_ptr->value)
831                 {
832                     case 1: chpr += printf("Off"); break;
833                     default: chpr += printf("unknown"); break;
834                 }
835                 print_endvalue();
836                 break;
837             case 0x3002: /* Quality" */
838                 print_startvalue();
839                 switch(entry_ptr->value)
840                 {
841                     case 1: chpr += printf("Economy"); break;
842                     case 2: chpr += printf("Normal"); break;
843                     case 3: chpr += printf("Fine"); break;
844                     default: chpr += printf("unknown"); break;
845                 }
846                 print_endvalue();
847                 break;
848             case 0x3003: /* FocusMode" */
849                 print_startvalue();
850                 switch(entry_ptr->value)
851                 {
852                     case 1: chpr += printf("Fixed"); break;
853                     case 3: chpr += printf("Single-Area Auto"); break;
854                     case 6: chpr += printf("Multi-Area Auto"); break;
855                     default: chpr += printf("unknown"); break;
856                 }
857                 print_endvalue();
858                 break;
859             case 0x3007: /* BestshotMode" */
860                 print_startvalue();
861                 switch(entry_ptr->value)
862                 {
863                     case 0: chpr += printf("Off"); break;
864                     default: chpr += printf("unknown"); break;
865                 }
866                 print_endvalue();
867                 break;
868             case 0x3015: /* ColorMode" */
869 #if 0
870 Off???
871                 print_startvalue();
872                 switch(entry_ptr->value)
873                 {
874                     case 0: chpr += printf("Off"); break;
875                     default: chpr += printf("unknown"); break;
876                 }
877                 print_endvalue();
878 #endif
879                 break;
880             case 0x3016: /* Enhancement" */
881                 print_startvalue();
882                 switch(entry_ptr->value)
883                 {
884                     case 0: chpr += printf("Off"); break;
885                     default: chpr += printf("unknown"); break;
886                 }
887                 print_endvalue();
888                 break;
889             case 0x3017: /* Filter" */
890                 print_startvalue();
891                 switch(entry_ptr->value)
892                 {
893                     case 0: chpr += printf("Off"); break;
894                     default: chpr += printf("unknown"); break;
895                 }
896                 print_endvalue();
897                 break;
898             default: break;
899         }
900     }
901     setcharsprinted(chpr);
902 }
903 
904 /* Some makernotes record offsets as LONG values rather than simply   */
905 /* using UNDEFINED with a size; the same technique used for           */
906 /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc.          */
907 /* This routine hardcodes such tags so that the print_makerentry()    */
908 /* routine will present them as offsets.                              */
909 
910 int
maker_casio_value_is_offset(struct ifd_entry * entry_ptr,int model)911 maker_casio_value_is_offset(struct ifd_entry *entry_ptr,int model)
912 {
913     int is_offset = 0;
914     int noteversion = 0;
915 
916     if(entry_ptr)
917     {
918         noteversion = getnoteversion();
919         switch(noteversion)
920         {
921             case 2:
922                 switch(entry_ptr->tag)
923                 {
924                     case 0x0004: is_offset = 1; break;
925                     default: break;
926                 }
927                 break;
928             default:
929                 break;
930         }
931     }
932     return(is_offset);
933 }
934