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_canon.c,v 1.29 2005/07/24 22:56:26 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Canon camera maker-specific routines                               */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* The information coded here is derived from information provided by */
17 /* David Burren at:                                                   */
18 /*     http://www.burren.cx/david/canon.html                          */
19 
20 /* April 05: new tag information and CustomFunctions for additional   */
21 /* models from Phil Harvey's exiftool pages at:                       */
22 /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html   */
23 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 
30 #include "defs.h"
31 #include "datadefs.h"
32 #include "maker_datadefs.h"
33 #include "summary.h"
34 #include "maker.h"
35 #include "misc.h"
36 #include "tags.h"
37 #include "maker_extern.h"
38 #include "extern.h"
39 
40 extern struct camera_id canon_model_id[];
41 
42 
43 /* Find the identifying number assigned to known Canon camera models. */
44 /* This number is used to dispatch appropriate print and interpret    */
45 /* routines approopriate to the current image.                        */
46 
47 int
canon_model_number(char * model,char * software)48 canon_model_number(char *model,char *software)
49 {
50     struct camera_id *model_id;
51     int number = NO_MODEL;
52 
53     for(model_id = &canon_model_id[0]; model_id && model_id->name; ++model_id)
54     {
55         if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
56         {
57             number = model_id->id;
58             setnoteversion(model_id->noteversion);
59             setnotetagset(model_id->notetagset);    /* info only      */
60             break;
61         }
62     }
63     return(number);
64 }
65 
66 /* Dispatch a print routine based upon previously set noteversion     */
67 /* Everything is (currently) mapped to one set of routines.           */
68 
69 void
print_canon_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)70 print_canon_makervalue(struct ifd_entry *entry_ptr,int make, int model,
71                     char *prefix)
72 {
73     int noteversion = 0;
74 
75     noteversion = getnoteversion();
76 
77     if(entry_ptr && (PRINT_VALUE))
78     {
79         switch(noteversion)
80         {
81             case 1:
82             case 2:
83             case 3:
84             case 4:
85             case 5:
86                 print_canon1_makervalue(entry_ptr,make,model,prefix);
87                 canon1_interpret_value(entry_ptr);
88                 break;
89             default:
90                 print_value(entry_ptr,PREFIX);
91                 break;
92         }
93     }
94 }
95 
96 /* Model-specific print routine for Canon cameras. This routine is    */
97 /* responsible for picking off any direct entry tags which are        */
98 /* peculiar and will not be handled properly by print_value()         */
99 /* (usually UNDEFINED values which fit in the 4-byte entry value). If */
100 /* there are no such entries, this function simply calls              */
101 /* print_value().                                                     */
102 
103 void
print_canon1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)104 print_canon1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
105                                                             char *prefix)
106 {
107     if(entry_ptr && (PRINT_VALUE))
108     {
109         switch(entry_ptr->tag)
110         {
111             case 0x000C:    /* Camera serial number                   */
112                 print_value(entry_ptr,PREFIX);
113                 /* ###%%%                                             */
114                 /* perhaps this should be in canon1_interpret_value() */
115                 (void)print_canon_serialno(entry_ptr->value);
116                 break;
117             default:
118                 print_value(entry_ptr,PREFIX);
119                 break;
120         }
121     }
122 }
123 
124 /* Canon serial numbers are encoded. It is not clear that this is     */
125 /* consistent across all models, but since the "raw" value is         */
126 /* displayed as well, it will do no harm to display this              */
127 /* unconditionally.                                                   */
128 
129 int
print_canon_serialno(unsigned long value)130 print_canon_serialno(unsigned long value)
131 {
132     unsigned long tmp;
133     int chpr = 0;
134 
135     print_startvalue();
136     tmp = (value & 0xffff0000) >> 16;
137     chpr += printf("%04lX",value & 0xffff);
138     tmp = value & 0xffff;
139     chpr += printf("%05lu",value & 0xffff);
140     print_endvalue();
141     setcharsprinted(chpr);
142     return(chpr);
143 }
144 
145 /* Dispatch a routine to decode and print offset values for Canon     */
146 /* cameras. There is currently only one tagset, and 1 interpretation  */
147 /* of each tag, except that there are 4 different varieties of custom */
148 /* functions. The canon_customfunctions() routine will do the         */
149 /* selection on noteversion; everything is handled the same here.     */
150 
151 void
print_canon_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)152 print_canon_offset_makervalue(FILE *inptr,unsigned short byteorder,
153                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
154                     struct image_summary *summary_entry,char *parent_name,
155                     char *prefix,int indent,int make,int model,
156                     int at_offset)
157 {
158     int noteversion = 0;
159 
160     noteversion = getnoteversion();
161 
162     if(entry_ptr)
163     {
164         switch(noteversion)
165         {
166             /* noteversion 1 assumes the single known tagset is       */
167             /* correct, but imposes a "generic" routine for           */
168             /* CustomFunctions (which presents values but interprets  */
169             /* nothing) for unrecognized models or those for which no */
170             /* information is available.                              */
171             case 1:
172             case 2:
173             case 3:
174             case 4:
175             case 5:
176                 canon1_offset_makervalue(inptr,byteorder,entry_ptr,
177                                             fileoffset_base,summary_entry,
178                                             parent_name,prefix,indent,
179                                             make,model,at_offset);
180                 break;
181             default:
182                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base,
183                                                 parent_name,prefix,indent,
184                                                 make,model,at_offset);
185                 break;
186         }
187     }
188 }
189 
190 /* Model-specific routine to print UNDEFINED values found at offsets  */
191 /* in canon makernotes.                                               */
192 
193 void
canon1_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)194 canon1_offset_makervalue(FILE *inptr,unsigned short byteorder,
195     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
196     struct image_summary *summary_entry,char *parent_name,char*prefix,
197     int indent,int make,int model,int at_offset)
198 {
199     unsigned long value_offset;
200     unsigned long count;
201     unsigned long max_offset = 0;
202     unsigned long filesize = 0UL;
203     unsigned short marker;
204     char *nameoftag,*tagprefix;
205     char *fulldirname = NULL;
206     int status = 0;
207     int chpr = 0;
208 
209     if(entry_ptr)
210     {
211         nameoftag = maker_tagname(entry_ptr->tag,make,model);
212         fulldirname = splice(parent_name,".",nameoftag);
213         value_offset = fileoffset_base + entry_ptr->value;
214         count = entry_ptr->count;
215         filesize = get_filesize(inptr);
216 
217         switch(entry_ptr->tag)
218         {
219             case 0x0001:    /* Camera Settings                        */
220                 if(at_offset)
221                 {
222                     if((PRINT_SECTION))
223                     {
224                         print_tag_address(SECTION,value_offset,indent,prefix);
225                         chpr += printf("<%s> ",nameoftag);
226                         chpr += printf("%lu entries",entry_ptr->count - 1);
227                     }
228                 }
229                 else if((PRINT_VALUE))
230                     chpr += printf("\'%lu entries\'",entry_ptr->count - 1);
231                 if((PRINT_LONGNAMES))
232                     tagprefix = fulldirname;
233                 else
234                     tagprefix = nameoftag;
235                 setcharsprinted(chpr);
236                 chpr = 0;
237                 (void)canon_camera_settings(inptr,byteorder,tagprefix,value_offset,
238                                         entry_ptr->count * sizeof(unsigned short),
239                                                             indent + MEDIUMINDENT);
240                 if(PRINT_SECTION)
241                 {
242                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
243                                                             indent,prefix);
244                     chpr += printf("</%s> ",nameoftag);
245                 }
246                 break;
247             case 0x0002:    /* Focus Info                             */
248                if(at_offset)
249                 {
250                     if((PRINT_SECTION))
251                     {
252                         print_tag_address(SECTION,value_offset,indent,prefix);
253                         chpr += printf("<%s> ",nameoftag);
254                         chpr += printf("%lu entries",entry_ptr->count);
255                     }
256                 }
257                 else if((PRINT_VALUE))
258                     chpr += printf("\'%lu entries\'",entry_ptr->count);
259                 if((PRINT_LONGNAMES))
260                     tagprefix = fulldirname;
261                 else
262                     tagprefix = nameoftag;
263                 setcharsprinted(chpr);
264                 chpr = 0;
265                 (void)canon_focusinfo(inptr,byteorder,tagprefix,value_offset,
266                                     entry_ptr->count * sizeof(unsigned short),
267                                                             indent + MEDIUMINDENT);
268                 if(PRINT_SECTION)
269                 {
270                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
271                                                             indent,prefix);
272                     chpr += printf("</%s> ",nameoftag);
273                 }
274                 break;
275             case 0x0004:    /* Shot Info                              */
276                 if(at_offset)
277                 {
278                     if((PRINT_SECTION))
279                     {
280                         print_tag_address(SECTION,value_offset,indent,prefix);
281                         chpr += printf("<%s> ",nameoftag);
282                         chpr += printf("%lu entries",entry_ptr->count - 1);
283                     }
284                 }
285                 else if((PRINT_VALUE))
286                     chpr += printf("\'%lu entries\'",entry_ptr->count - 1);
287                 if((PRINT_LONGNAMES))
288                     tagprefix = fulldirname;
289                 else
290                     tagprefix = nameoftag;
291                 setcharsprinted(chpr);
292                 chpr = 0;
293                 (void)canon_shotinfo(inptr,byteorder,tagprefix,value_offset,
294                                     entry_ptr->count * sizeof(unsigned short),
295                                                         indent + MEDIUMINDENT);
296                 if(PRINT_SECTION)
297                 {
298                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
299                                                             indent,prefix);
300                     chpr += printf("</%s> ",nameoftag);
301                 }
302                 break;
303             case 0x0090:    /* Custom Functions                       */
304             case 0x000F:    /* Custom Functions                       */
305                 if(at_offset)
306                 {
307                     if((PRINT_SECTION))
308                     {
309                         print_tag_address(SECTION,value_offset,indent,prefix);
310                         chpr += printf("<%s> ",nameoftag);
311                         chpr += printf("%lu entries",entry_ptr->count - 1);
312                     }
313                 }
314                 else if((PRINT_VALUE))
315                     chpr += printf("\'%lu entries\'",entry_ptr->count - 1);
316                 if((PRINT_LONGNAMES))
317                     tagprefix = fulldirname;
318                 else
319                     tagprefix = nameoftag;
320                 setcharsprinted(chpr);
321                 chpr = 0;
322                 (void)canon_customfunctions(inptr,byteorder,tagprefix,value_offset,
323                                         entry_ptr->count * sizeof(unsigned short),
324                                         model,indent + MEDIUMINDENT);
325                 if(PRINT_SECTION)
326                 {
327                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
328                                     indent,prefix);
329                     chpr += printf("</%s> ",nameoftag);
330                 }
331                 break;
332             case 0x00E0:    /* Sensor Info                            */
333                 if(at_offset)
334                 {
335                     if((PRINT_SECTION))
336                     {
337                         print_tag_address(SECTION,value_offset,indent,prefix);
338                         chpr += printf("<%s> ",nameoftag);
339                         chpr += printf("%lu entries",entry_ptr->count - 1);
340                     }
341                 }
342                 else if((PRINT_VALUE))
343                     chpr += printf("\'%lu entries\'",entry_ptr->count - 1);
344                 if((PRINT_LONGNAMES))
345                     tagprefix = fulldirname;
346                 else
347                     tagprefix = nameoftag;
348                 setcharsprinted(chpr);
349                 chpr = 0;
350                 (void)canon_sensorinfo(inptr,byteorder,tagprefix,value_offset,
351                                     entry_ptr->count * sizeof(unsigned short),
352                                     indent + MEDIUMINDENT);
353                 if(PRINT_SECTION)
354                 {
355                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
356                                                             indent,prefix);
357                     chpr += printf("</%s> ",nameoftag);
358                 }
359                 break;
360             case 0x0012:    /* Picture Info                           */
361                 if(at_offset)
362                 {
363                     if((PRINT_SECTION))
364                     {
365                         print_tag_address(SECTION,value_offset,indent,prefix);
366                         chpr += printf("<%s> ",nameoftag);
367                         chpr += printf("%lu entries",entry_ptr->count - 1);
368                     }
369                 }
370                 else if((PRINT_VALUE))
371                     chpr += printf("\'%lu entries\'",entry_ptr->count - 1);
372                 if((PRINT_LONGNAMES))
373                     tagprefix = fulldirname;
374                 else
375                     tagprefix = nameoftag;
376                 setcharsprinted(chpr);
377                 chpr = 0;
378                 (void)canon_pictureinfo(inptr,byteorder,tagprefix,value_offset,
379                                     entry_ptr->count * sizeof(unsigned short),
380                                     indent + MEDIUMINDENT);
381                 if(PRINT_SECTION)
382                 {
383                     print_tag_address(SECTION,value_offset + (entry_ptr->count * 2) - 1,
384                                         indent,prefix);
385                     chpr += printf("</%s> ",nameoftag);
386                 }
387                 break;
388             case 0x0081:    /* JPEG image offset                      */
389                 if(at_offset && (PRINT_SECTION))
390                 {
391                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
392                     chpr += printf("# Start of JPEG image from MakerNote");
393                 }
394                 else if(!at_offset && (PRINT_VALUE))
395                 {
396                     if(!(PRINT_OFFSET))
397                         chpr += printf("@%lu",value_offset);
398                 }
399                 if((PRINT_SECTION) || (PRINT_SEGMENT))
400                     chpr = newline(chpr);
401                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
402                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
403                                     0,summary_entry,fulldirname,
404                                     prefix,indent+SMALLINDENT);
405                 if(at_offset)
406                 {
407                     if((PRINT_SECTION))
408                     {
409                         if(max_offset == 0UL)
410                             max_offset = filesize;
411                         if(max_offset)
412                         {
413                             if((status = jpeg_status(0)) == JPEG_EARLY_EOI)
414                                 chpr = newline(chpr);
415                             jpeg_status(status);
416                             print_tag_address(VALUE_AT_OFFSET,max_offset - 1,indent,"-");
417                             chpr += printf("# End of JPEG image from MakerNote");
418                             chpr += printf(" length %lu",max_offset - value_offset);
419                         }
420                         if(!(PRINT_VALUE) && (status == JPEG_NO_ERROR))
421                             chpr = newline(chpr);
422                     }
423                 }
424                 print_jpeg_status();
425                 if(marker && summary_entry)
426                 {
427                     /* The new one is on the end of the chain         */
428                     if((summary_entry = last_summary_entry(summary_entry)))
429                     {
430                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
431                         summary_entry->datatype = MAKER_IFD;
432                         if((summary_entry->compression == JPEG_SOF_3) && (max_offset == 0))
433                             summary_entry->length = filesize - value_offset;
434                     }
435                 }
436                 clearerr(inptr);
437                 break;
438             default:
439                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,fileoffset_base,
440                                                 fulldirname,prefix,indent,
441                                                 make,model,at_offset);
442                 break;
443         }
444         if(fulldirname)
445             free(fulldirname);
446     }
447     setcharsprinted(chpr);
448 }
449 
450 
451 /* Canon-specific tagnames for makernotes.                            */
452 /* There is currently only one tagset, but there are (at least) 4     */
453 /* different sets of custom functions.                                */
454 
455 char *
maker_canon_tagname(unsigned short tag,int model)456 maker_canon_tagname(unsigned short tag,int model)
457 {
458     char *tagname = CNULL;
459     int noteversion = 0;
460 
461     /* Should have to do this only once, and only for unrecognized    */
462     /* models. If the model is recognized (or the user has forced a   */
463     /* noteversion) noteversion will already be set.                  */
464     if(((noteversion = getnoteversion()) == 0))
465     {
466         /* Assume the tagset is correct, but use the generic          */
467         /* CustomFunctions routine if required (some models don't     */
468         /* have custom functions)                                     */
469         noteversion = 1;
470         setnoteversion(1);
471     }
472 
473     switch(noteversion)
474     {
475         case 1:
476         case 2:
477         case 3:
478         case 4:
479         case 5:
480             tagname = maker_canon1_tagname(tag,model);
481             break;
482         default:
483             /* This essentially turns off tagname interpretation; it  */
484             /* should happen only if the user has deliberately set a  */
485             /* non-existent version (e.g. -1)                         */
486             break;
487     }
488 
489     /* If no model-specific tag is found, check "generic" tags        */
490     if(tagname == NULL)
491     {
492         switch(tag)
493         {
494             case 0x0e00: tagname = "PrintIM"; break;
495             default: break;
496         }
497     }
498     return(tagname);
499 }
500 
501 char *
maker_canon1_tagname(unsigned short tag,int model)502 maker_canon1_tagname(unsigned short tag,int model)
503 {
504     char *tagname = CNULL;
505 
506     switch(tag)
507     {
508         case 0x0001: tagname = "CameraSettings"; break;
509         case 0x0002: tagname = "FocusInfo"; break;
510         case 0x0004: tagname = "ShotInfo"; break;
511         case 0x0006: tagname = "ImageType"; break;
512         case 0x0007: tagname = "FirmwareVersion"; break;
513         case 0x0008: tagname = "ImageNumber"; break;
514         case 0x0009: tagname = "OwnerName"; break;
515         case 0x000a: tagname = "ColorInfoD30*"; break;
516         case 0x000c: tagname = "CameraSerialNo"; break;
517         case 0x000e: tagname = "FileLength"; break;
518         case 0x000f: tagname = "CustomFunctions"; break;
519         case 0x0012: tagname = "PictureInfo"; break;
520         case 0x0081: tagname = "JpegImage"; break;
521         case 0x0090: tagname = "CustomFunctions"; break;
522         case 0x0093: tagname = "FileInfo**"; break;   /* exiftool shows wrong type */
523         case 0x00a0: tagname = "ColorInfo**"; break;  /* exiftool - wrong # values */
524         case 0x00a9: tagname = "WhiteBalanceTable"; break;
525         case 0x00ae: tagname = "ColorTemperature"; break;
526         case 0x00b6: tagname = "PreviewImageInfo"; break;
527         case 0x00e0: tagname = "SensorInfo"; break;
528         default: break;
529     }
530     setnotetagset(1);
531     return(tagname);
532 }
533 
534 /* Report the "meaning" of tag values found directly in a Canon       */
535 /* MakerNote IFD entry (not at an offset).                            */
536 
537 /* There are currently no direct entry tags for which the meaning is  */
538 /* known, so this routine is null, empty, void. There are observed    */
539 /* tags with unknown meaning, so this routine will be necessary.      */
540 
541 /* I suspect that ImageNumber could be decomposed into a DCF folder   */
542 /* number and sequence number),                                       */
543 
544 void
canon1_interpret_value(struct ifd_entry * entry_ptr)545 canon1_interpret_value(struct ifd_entry *entry_ptr)
546 {
547     switch(entry_ptr->tag)
548     {
549         default: break;
550     }
551 }
552 
553 /* ###%%% FIXIT: none of the routines below honor the PRINT_TAGNAMES  */
554 /* or PRINT_VALUE options.                                            */
555 
556 /* Interpret the "Camera Settings" tag data from Canon MakerNotes.    */
557 
558 unsigned long
canon_camera_settings(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)559 canon_camera_settings(FILE *inptr,unsigned short byteorder,char *tagprefix,
560                     unsigned long offset,unsigned long dirlength,int indent)
561 {
562     unsigned long count;
563     unsigned long end_offset;
564     struct fileheader *header = NULL;
565     unsigned short length,value;
566     char *sep;
567     int i;
568     int chpr = 0;
569 
570 
571     end_offset = offset + dirlength;
572     length = read_ushort(inptr,byteorder,offset);
573     if(PRINT_SECTION)
574     {
575         chpr += printf(" length %lu",dirlength);
576         if(length != dirlength)
577         {
578             chpr = newline(chpr);
579             PUSHCOLOR(RED);
580             print_tag_address(SECTION,offset,indent,"@");
581             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
582                         length,dirlength);
583             POPCOLOR();
584         }
585     }
586     chpr = newline(chpr);
587     offset += 2;
588     count = (dirlength / sizeof(unsigned short)) - 1;
589 
590     if((PRINT_ENTRY))
591     {
592         for(i = 1; i <= count; ++i)
593         {
594             value = read_ushort(inptr,byteorder,offset);
595             print_tag_address(ENTRY,offset,indent,"@");
596             /* tagprefix has already been adjusted according to the   */
597             /* setting of PRINT_LONGNAMES.                            */
598             if((PRINT_TAGINFO))
599                 chpr += printf("%s",tagprefix);
600             offset += 2;
601             switch(i)
602             {
603                 case 1:
604                     if((PRINT_TAGINFO))
605                         chpr += printf(".%02d_%-23.23s",i,"MacroMode");
606                     if((PRINT_VALUE))
607                     {
608                         chpr += printf(" = %u",value);
609                         print_startvalue();
610                         switch(value)
611                         {
612                             case 1: chpr += printf("macro"); break;
613                             case 2: chpr += printf("normal"); break;
614                             default: printred("undefined"); break;
615                         }
616                         print_endvalue();
617                     }
618                     break;
619                 case 2:
620                     if((PRINT_TAGINFO))
621                         chpr += printf(".%02d_%-23.23s",i,"SelfTimer");
622                     if((PRINT_VALUE))
623                     {
624                         chpr += printf(" = %u",value);
625                         print_startvalue();
626                         if(value)
627                             chpr += printf(".%u sec",value); /* ###%%% ?  */
628                         else
629                             chpr += printf("off");
630                         print_endvalue();
631                     }
632                     break;
633                 case 3:
634                     if((PRINT_TAGINFO))
635                         chpr += printf(".%02d_%-23.23s",i,"Quality");
636                     if((PRINT_VALUE))
637                     {
638                         chpr += printf(" = %u",value);
639                         print_startvalue();
640                         switch(value)
641                         {
642                             case 2: chpr += printf("normal"); break;
643                             case 3: chpr += printf("fine"); break;
644                             case 4: header = read_imageheader(inptr,0);
645                                     switch(header->probe_magic)
646                                     {
647                                         case TIFF_MAGIC:
648                                         case PROBE_JPEGMAGIC:
649                                             chpr += printf("Lossless JPEG");
650                                             break;
651                                         case PROBE_CIFFMAGIC:
652                                         default:
653                                             chpr += printf("RAW");
654                                             break;
655                                     }
656                                     break;
657                             case 5: chpr += printf("super fine"); break;
658                             default: printred("unknown"); break;
659                         }
660                         print_endvalue();
661                     }
662                     break;
663                 case 4:
664                     if((PRINT_TAGINFO))
665                         chpr += printf(".%02d_%-23.23s",i,"FlashMode");
666                     if((PRINT_VALUE))
667                     {
668                         chpr += printf(" = %u",value);
669                         print_startvalue();
670                         switch(value)
671                         {
672                             case 0: chpr += printf("flash did not fire"); break;
673                             case 1: chpr += printf("auto"); break;
674                             case 2: chpr += printf("on"); break;
675                             case 3: chpr += printf("redeye"); break;
676                             case 4: chpr += printf("slow sync"); break;
677                             case 5: chpr += printf("auto + redeye"); break;
678                             case 6: chpr += printf("on + redeye"); break;
679                             case 16: chpr += printf("external flash"); break;
680                             default: printred("undefined"); break;
681                         }
682                         print_endvalue();
683                     }
684                     break;
685                 case 5:
686                     if((PRINT_TAGINFO))
687                         chpr += printf(".%02d_%-23.23s",i,"ContinuousMode");
688                     if((PRINT_VALUE))
689                     {
690                         chpr += printf(" = %u",value);
691                         print_startvalue();
692                         switch(value)
693                         {
694                             case 0: chpr += printf("single or timer"); break;
695                             case 1: chpr += printf("continuous"); break;
696                             default: printred("undefined"); break;
697                         }
698                         print_endvalue();
699                     }
700                     break;
701                 case 6:
702                     if((PRINT_TAGINFO))
703                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
704                     if((PRINT_VALUE))
705                         chpr += printf(" = %u",value);
706                     break;
707                 case 7:
708                     if((PRINT_TAGINFO))
709                         chpr += printf(".%02d_%-23.23s",i,"FocusMode");
710                     if((PRINT_VALUE))
711                     {
712                         chpr += printf(" = %u",value);
713                         print_startvalue();
714                         switch(value)
715                         {
716                             case 0: chpr += printf("One Shot AF"); break;
717                             case 1: chpr += printf("AI Servo AF"); break;
718                             case 2: chpr += printf("AI Focus AF"); break;
719                             case 3: chpr += printf("Manual Focus"); break;
720                             case 4: chpr += printf("single"); break;
721                             case 5: chpr += printf("Continuous"); break;
722                             default: printred("undefined"); break;
723                         }
724                         print_endvalue();
725                     }
726                     break;
727                 case 8:
728                     if((PRINT_TAGINFO))
729                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
730                     if((PRINT_VALUE))
731                         chpr += printf(" = %u",value);
732                     break;
733                 case 9:
734                     if((PRINT_TAGINFO))
735                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
736                     if((PRINT_VALUE))
737                         chpr += printf(" = %u",value);
738                     break;
739                 case 10:
740                     if((PRINT_TAGINFO))
741                         chpr += printf(".%02d_%-23.23s",i,"ImageSize");
742                     if((PRINT_VALUE))
743                     {
744                         chpr += printf(" = %u",value);
745                         print_startvalue();
746                         switch(value)
747                         {
748                             case 0: chpr += printf("Large"); break;
749                             case 1: chpr += printf("Medium"); break;
750                             case 2: chpr += printf("Small"); break;
751                             default: printred("undefined"); break;
752                         }
753                         print_endvalue();
754                     }
755                     break;
756                 case 11:
757                     if((PRINT_TAGINFO))
758                         chpr += printf(".%02d_%-23.23s",i,"EasyShootMode");
759                     if((PRINT_VALUE))
760                     {
761                         chpr += printf(" = %u",value);
762                         print_startvalue();
763                         switch(value)
764                         {
765                             case 0: chpr += printf("Full Auto"); break;
766                             case 1: chpr += printf("Manual"); break;
767                             case 2: chpr += printf("Landscape"); break;
768                             case 3: chpr += printf("Fast Shutter"); break;
769                             case 4: chpr += printf("Slow Shutter"); break;
770                             case 5: chpr += printf("Night"); break;
771                             case 6: chpr += printf("B & W"); break;
772                             case 7: chpr += printf("Sepia"); break;
773                             case 8: chpr += printf("Portrait"); break;
774                             case 9: chpr += printf("Sports"); break;
775                             case 10: chpr += printf("Macro/CloseUp"); break;
776                             case 11: chpr += printf("Pan Focus"); break;
777                             default: printred("undefined"); break;
778                         }
779                         print_endvalue();
780                     }
781                     break;
782                 case 12:
783                     if((PRINT_TAGINFO))
784                         chpr += printf(".%02d_%-23.23s",i,"DigitalZoom");
785                     if((PRINT_VALUE))
786                     {
787                         chpr += printf(" = %u",value);
788                         print_startvalue();
789                         switch(value)
790                         {
791                             case 0: chpr += printf("none"); break;
792                             case 1: chpr += printf("2x"); break;
793                             case 2: chpr += printf("4x"); break;
794                             default: printred("(2 * ZoomedResBase) / ZoomedResValue**"); break;
795                         }
796                         print_endvalue();
797                     }
798                     break;
799                 case 13:
800                     if((PRINT_TAGINFO))
801                         chpr += printf(".%02d_%-23.23s",i,"Contrast");
802                     if((PRINT_VALUE))
803                     {
804                         chpr += printf(" = %u",value);
805                         print_startvalue();
806                         switch(value)
807                         {
808                             case 0: chpr += printf("Normal"); break;
809                             case 1: chpr += printf("High"); break;
810                             case 0xffff: chpr += printf("Low"); break;
811                             default: printred("undefined"); break;
812                         }
813                         print_endvalue();
814                     }
815                     break;
816                 case 14:
817                     if((PRINT_TAGINFO))
818                         chpr += printf(".%02d_%-23.23s",i,"Saturation");
819                     if((PRINT_VALUE))
820                     {
821                         chpr += printf(" = %u",value);
822                         print_startvalue();
823                         switch(value)
824                         {
825                             case 0: chpr += printf("Normal"); break;
826                             case 1: chpr += printf("High"); break;
827                             case 0xffff: chpr += printf("Low"); break;
828                             default: printred("undefined"); break;
829                         }
830                         print_endvalue();
831                     }
832                     break;
833                 case 15:
834                     if((PRINT_TAGINFO))
835                         chpr += printf(".%02d_%-23.23s",i,"Sharpness");
836                     if((PRINT_VALUE))
837                     {
838                         chpr += printf(" = %u",value);
839                         print_startvalue();
840                         switch(value)
841                         {
842                             case 0: chpr += printf("Normal"); break;
843                             case 1: chpr += printf("High"); break;
844                             case 0xffff: chpr += printf("Low"); break;
845                             default: printred("undefined"); break;
846                         }
847                         print_endvalue();
848                     }
849                     break;
850                 case 16:
851                     if((PRINT_TAGINFO))
852                         chpr += printf(".%02d_%-23.23s",i,"ISO");
853                     if((PRINT_VALUE))
854                     {
855                         chpr += printf(" = %#x/%u",value,value);
856                         print_startvalue();
857                         switch(value)
858                         {
859                             case 0: chpr += printf("Use Exif ISOSpeedRating"); break;
860                             case 15: chpr += printf("Auto"); break;
861                             case 16: chpr += printf("50"); break;
862                             case 17: chpr += printf("100"); break;
863                             case 18: chpr += printf("200"); break;
864                             case 19: chpr += printf("400"); break;
865                             default: printred("undefined"); break;
866                         }
867                         print_endvalue();
868                     }
869                     break;
870                 case 17:
871                     if((PRINT_TAGINFO))
872                         chpr += printf(".%02d_%-23.23s",i,"MeteringMode");
873                     if((PRINT_VALUE))
874                     {
875                         chpr += printf(" = %u",value);
876                         print_startvalue();
877                         switch(value)
878                         {
879                             case 0: chpr += printf("Default"); break;
880                             case 1: chpr += printf("Spot"); break;
881                             case 3: chpr += printf("Evaluative"); break;
882                             case 4: chpr += printf("Partial"); break;
883                             case 5: chpr += printf("Center-weighted"); break;
884                             default: printred("undefined"); break;
885                         }
886                         print_endvalue();
887                     }
888                     break;
889                 case 18:
890                     if((PRINT_TAGINFO))
891                         chpr += printf(".%02d_%-23.23s",i,"FocusType");
892                     if((PRINT_VALUE))
893                     {
894                         chpr += printf(" = %u",value);
895                         print_startvalue();
896                         switch(value)
897                         {
898                             case 0: chpr += printf("Manual"); break;
899                             case 1: chpr += printf("Auto1"); break;
900                             case 2: chpr += printf("Auto2"); break;
901                             case 3: chpr += printf("Macro"); break;
902                             case 7: chpr += printf("Infinity"); break;
903                             case 8: chpr += printf("Locked (pan mode)"); break;
904                             default: printred("undefined"); break;
905                         }
906                         print_endvalue();
907                     }
908                     break;
909                 case 19:
910                     if((PRINT_TAGINFO))
911                         chpr += printf(".%02d_%-23.23s",i,"AFPositionSelected");
912                     if((PRINT_VALUE))
913                     {
914                         chpr += printf(" = %#x",value);
915                         print_startvalue();
916                         switch(value)
917                         {
918                             case 0x2005: chpr += printf("Manual AF Point select"); break;
919                             case 0x3000: chpr += printf("None (manual focus)"); break;
920                             case 0x3001: chpr += printf("Auto-selected"); break;
921                             case 0x3002: chpr += printf("Right"); break;
922                             case 0x3003: chpr += printf("Center"); break;
923                             case 0x3004: chpr += printf("Left"); break;
924                             case 0x4001: chpr += printf("Auto AF Point select"); break;
925                             default: printred("undefined");
926                         }
927                         print_endvalue();
928                     }
929                     break;
930                 case 20:
931                     if((PRINT_TAGINFO))
932                         chpr += printf(".%02d_%-23.23s",i,"ExposureMode");
933                     if((PRINT_VALUE))
934                     {
935                         chpr += printf(" = %u",value);
936                         print_startvalue();
937                         switch(value)
938                         {
939                             case 0: chpr += printf("Easy Shooting"); break;
940                             case 1: chpr += printf("Program AE"); break;
941                             case 2: chpr += printf("Shutter priority AE"); break;
942                             case 3: chpr += printf("Aperture priority AE"); break;
943                             case 4: chpr += printf("Manual"); break;
944                             case 5: chpr += printf("Depth of field AE"); break;
945                             default: printred("undefined"); break;
946                         }
947                         print_endvalue();
948                     }
949                     break;
950                 case 21:
951                     if((PRINT_TAGINFO))
952                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
953                     if((PRINT_VALUE))
954                         chpr += printf(" = %u",value);
955                     break;
956                 case 22:
957                     if((PRINT_TAGINFO))
958                         chpr += printf(".%02d_%-23.23s",i,"LensType");
959                     if((PRINT_VALUE))
960                         chpr += printf(" = %u",value);
961                     /* ###%% Phil Harvey gives a massive Lens type    */
962                     /* table                                          */
963                     break;
964                 case 23:
965                     if((PRINT_TAGINFO))
966                         chpr += printf(".%02d_%-23.23s",i,"FocalLength_long");
967                     if((PRINT_VALUE))
968                         chpr += printf(" = %u units",value);
969                     break;
970                 case 24:
971                     if((PRINT_TAGINFO))
972                         chpr += printf(".%02d_%-23.23s",i,"FocalLength_short");
973                     if((PRINT_VALUE))
974                         chpr += printf(" = %u units",value);
975                     break;
976                 case 25:
977                     if((PRINT_TAGINFO))
978                         chpr += printf(".%02d_%-23.23s",i,"FocalUnits*");
979                     if((PRINT_VALUE))
980                     {
981                         if(value > 1)
982                             chpr += printf(" = %u units per mm*",value);
983                         else
984                             chpr += printf(" = %u unit per mm",value);
985                     }
986                     break;
987                 case 26:
988                     if((PRINT_TAGINFO))
989                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
990                     if((PRINT_VALUE))
991                         chpr += printf(" = %u",value);
992                     break;
993                 case 27:
994                     if((PRINT_TAGINFO))
995                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
996                     if((PRINT_VALUE))
997                         chpr += printf(" = %u",value);
998                     break;
999                 case 28:
1000                     if((PRINT_TAGINFO))
1001                         chpr += printf(".%02d_%-23.23s",i,"FlashActivity");
1002                     if((PRINT_VALUE))
1003                     {
1004                         chpr += printf(" = %#x",value);
1005                         print_startvalue();
1006                         switch(value)
1007                         {
1008                             case 0: chpr += printf("did not fire"); break;
1009                             case 1: chpr += printf("fired"); break;
1010                             default: printred("undefined"); break;
1011                         }
1012                         print_endvalue();
1013                     }
1014                     break;
1015                 case 29:
1016                     if((PRINT_TAGINFO))
1017                         chpr += printf(".%02d_%-23.23s",i,"FlashDetails");
1018                     if((PRINT_VALUE))
1019                     {
1020                         chpr += printf(" = %#x",value);
1021                         print_startvalue();
1022                         sep = "";
1023                         if(value & 0x0e)
1024                         {
1025                             chpr += printf("%sexternal E-TTL",sep);
1026                             sep = ",";
1027                         }
1028                         if(value & 0x0d)
1029                         {
1030                             chpr += printf("%sInternal flash**",sep);
1031                             sep = ",";
1032                         }
1033                         if(value & 0x0b)
1034                         {
1035                             chpr += printf("%sFP sync used",sep);
1036                             sep = ",";
1037                         }
1038                         if(value & 0x07)
1039                         {
1040                             chpr += printf("%s2nd-curtain sync used",sep);
1041                             sep = ",";
1042                         }
1043                         if(value & 0x04)
1044                         {
1045                             chpr += printf("%sFP sync enabled",sep);
1046                             sep = ",";
1047                         }
1048                         if(value & 0x03)
1049                         {
1050                             chpr += printf("%sOn",sep);
1051                             sep = ",";
1052                         }
1053                         print_endvalue();
1054                     }
1055                     break;
1056                 case 30:
1057                     if((PRINT_TAGINFO))
1058                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
1059                     if((PRINT_VALUE))
1060                         chpr += printf(" = %u",value);
1061                     break;
1062                 case 31:
1063                     if((PRINT_TAGINFO))
1064                         chpr += printf(".%02d_%-23.23s",i,"Unknown");
1065                     if((PRINT_VALUE))
1066                         chpr += printf(" = %u",value);
1067                     break;
1068                 case 32:
1069                     if((PRINT_TAGINFO))
1070                         chpr += printf(".%02d_%-23.23s",i,"FocusMode");
1071                     if((PRINT_VALUE))
1072                     {
1073                         chpr += printf(" = %u",value);
1074                         print_startvalue();
1075                         switch(value)
1076                         {
1077                             case 0: chpr += printf("Single"); break;
1078                             case 1: chpr += printf("Continuous"); break;
1079                             default: printred("undefined"); break;
1080                         }
1081                         print_endvalue();
1082                     }
1083                     break;
1084                 case 36:
1085                     if((PRINT_TAGINFO))
1086                         chpr += printf(".%02d_%-23.23s",i,"ZoomedResValue**");
1087                     if((PRINT_VALUE))
1088                         chpr += printf(" = %u",value);
1089                     break;
1090                 case 37:
1091                     if((PRINT_TAGINFO))
1092                         chpr += printf(".%02d_%-23.23s",i,"ZoomedResBase**");
1093                     if((PRINT_VALUE))
1094                         chpr += printf(" = %u",value);
1095                     break;
1096                 case 42:
1097                     if((PRINT_TAGINFO))
1098                         chpr += printf(".%02d_%-23.23s",i,"ColorTone**");
1099                     if((PRINT_VALUE))
1100                         chpr += printf(" = %#x/%u",value,value);
1101                     break;
1102                 default:
1103                     if((PRINT_TAGINFO))
1104                         chpr += printf(".%02d_%-23.23s",i,"undefined");
1105                     if((PRINT_VALUE))
1106                         chpr += printf(" = %#x/%u",value,value);
1107                     break;
1108             }
1109             chpr = newline(chpr);
1110         }
1111     }
1112     setcharsprinted(chpr);
1113     return(end_offset);
1114 }
1115 
1116 /* Interpret the "ShotInfo" settings in a Cannon MakerNote or         */
1117 /* CIFF file                                                          */
1118 
1119 unsigned long
canon_shotinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)1120 canon_shotinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
1121                             unsigned long offset,unsigned long dirlength,int indent)
1122 {
1123     unsigned long count;
1124     unsigned long end_offset;
1125     unsigned short length,value;
1126     int i;
1127     int chpr = 0;
1128 
1129     end_offset = offset + dirlength;
1130     length = read_ushort(inptr,byteorder,offset);
1131     if(PRINT_SECTION)
1132     {
1133         chpr += printf(" length %lu",dirlength);
1134         if(length != dirlength)
1135         {
1136             chpr = newline(chpr);
1137             PUSHCOLOR(RED);
1138             print_tag_address(SECTION,offset,indent,"@");
1139             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
1140                         length,dirlength);
1141             POPCOLOR();
1142         }
1143     }
1144     chpr = newline(chpr);
1145 
1146     if((PRINT_ENTRY))
1147     {
1148         offset += 2;
1149         count = (dirlength / sizeof(unsigned short)) - 1;
1150 
1151         for(i = 1; i <= count; ++i)
1152         {
1153             value = read_ushort(inptr,byteorder,offset);
1154             print_tag_address(ENTRY,offset,indent,"@");
1155             if((PRINT_TAGINFO))
1156                 chpr += printf("%s",tagprefix);
1157             offset += 2;
1158             switch(i)
1159             {
1160                 case 1:
1161                     if((PRINT_TAGINFO))
1162                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1163                     if((PRINT_VALUE))
1164                         chpr += printf(" = %#x%u",value,value);
1165                     break;
1166                 case 2:
1167                     if((PRINT_TAGINFO))
1168                         chpr += printf(".%02d_%-28.28s",i,"ISO");
1169                     if((PRINT_VALUE))
1170                         chpr += printf(" = %u",value);
1171                     break;
1172                 case 3:
1173                     if((PRINT_TAGINFO))
1174                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1175                     if((PRINT_VALUE))
1176                         chpr += printf(" = %#x%u",value,value);
1177                     break;
1178                 case 4:
1179                     if((PRINT_TAGINFO))
1180                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1181                     if((PRINT_VALUE))
1182                         chpr += printf(" = %#x%u",value,value);
1183                     break;
1184                 case 5:
1185                     if((PRINT_TAGINFO))
1186                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1187                     if((PRINT_VALUE))
1188                         chpr += printf(" = %#x%u",value,value);
1189                     break;
1190                 case 6:
1191                     if((PRINT_TAGINFO))
1192                         chpr += printf(".%02d_%-28.28s",i,"ExposureCompensation**");
1193                     if((PRINT_VALUE))
1194                         chpr += printf(" = %u",value);
1195                     break;
1196                 case 7:
1197                     if((PRINT_TAGINFO))
1198                         chpr += printf(".%02d_%-28.28s",i,"WhiteBalance");
1199                     if((PRINT_VALUE))
1200                     {
1201                         chpr += printf(" = %u",value);
1202                         print_startvalue();
1203                         switch(value)
1204                         {
1205                             case 0: chpr += printf("Auto"); break;
1206                             case 1: chpr += printf("Sunny"); break;
1207                             case 2: chpr += printf("Cloudy"); break;
1208                             case 3: chpr += printf("Tungsten"); break;
1209                             case 4: chpr += printf("Fluorescent"); break;
1210                             case 5: chpr += printf("Flash"); break;
1211                             case 6: chpr += printf("Custom"); break;
1212                             default: printred("undefined"); break;
1213                         }
1214                         print_endvalue();
1215                     }
1216                     break;
1217                 case 8:
1218                     if((PRINT_TAGINFO))
1219                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1220                     if((PRINT_VALUE))
1221                         chpr += printf(" = %#x%u",value,value);
1222                     break;
1223                 case 9:
1224                     if((PRINT_TAGINFO))
1225                         chpr += printf(".%02d_%-28.28s",i,"SequenceNumber");
1226                     if((PRINT_VALUE))
1227                         chpr += printf(" = %u",value);
1228                     break;
1229                 case 10:
1230                     if((PRINT_TAGINFO))
1231                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1232                     if((PRINT_VALUE))
1233                         chpr += printf(" = %#x%u",value,value);
1234                     break;
1235                 case 11:
1236                     if((PRINT_TAGINFO))
1237                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1238                     if((PRINT_VALUE))
1239                         chpr += printf(" = %#x%u",value,value);
1240                     break;
1241                 case 12:
1242                     if((PRINT_TAGINFO))
1243                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1244                     if((PRINT_VALUE))
1245                         chpr += printf(" = %#x%u",value,value);
1246                     break;
1247                 case 13:
1248                     if((PRINT_TAGINFO))
1249                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1250                     if((PRINT_VALUE))
1251                         chpr += printf(" = %#x%u",value,value);
1252                     break;
1253                 case 14:
1254                     if((PRINT_TAGINFO))
1255                         chpr += printf(".%02d_%-28.28s",i,"AFPositionUsed");
1256                     if((PRINT_VALUE))
1257                     {
1258                         chpr += printf(" = %#x",value);
1259                         print_startvalue();
1260                         if(value & 0xf000)
1261                         {
1262                             switch(value & 0x7)
1263                             {
1264                                 case 0: chpr += printf("none (MF)"); break;
1265                                 case 1: chpr += printf("right"); break;
1266                                 case 2: chpr += printf("center"); break;
1267                                 case 3: chpr += printf("center+right"); break;
1268                                 case 4: chpr += printf("left"); break;
1269                                 case 5: chpr += printf("left+right"); break;
1270                                 case 6: chpr += printf("left+center"); break;
1271                                 case 7: chpr += printf("all"); break;
1272                                 default: printred("undefined"); break;
1273                             }
1274                             chpr += printf(" of %d points",(value & 0xf000) >> 12);
1275                         }
1276                         else
1277                             chpr += printf("MF");
1278                         print_endvalue();
1279                     }
1280                     break;
1281                 case 15:
1282                     if((PRINT_TAGINFO))
1283                         chpr += printf(".%02d_%-28.28s",i,"FlashBias");
1284                     if((PRINT_VALUE))
1285                     {
1286                         chpr += printf(" = %#x",value);
1287                         print_startvalue();
1288                         switch(value)
1289                         {
1290                             case 0xffc0: chpr += printf("-2 EV"); break;
1291                             case 0xffcc: chpr += printf("-1.67 EV"); break;
1292                             case 0xffd0: chpr += printf("-1.50 EV"); break;
1293                             case 0xffd4: chpr += printf("-1.33 EV"); break;
1294                             case 0xffe0: chpr += printf("-1 EV"); break;
1295                             case 0xffec: chpr += printf("-0.67 EV"); break;
1296                             case 0xfff0: chpr += printf("-0.50 EV"); break;
1297                             case 0xfff4: chpr += printf("-0.33 EV"); break;
1298                             case 0x0000: chpr += printf("0 EV"); break;
1299                             case 0x000c: chpr += printf("+0.33 EV"); break;
1300                             case 0x0010: chpr += printf("+0.50 EV"); break;
1301                             case 0x0014: chpr += printf("+0.67 EV"); break;
1302                             case 0x0020: chpr += printf("+1 EV"); break;
1303                             case 0x002c: chpr += printf("+1.33 EV"); break;
1304                             case 0x0030: chpr += printf("+1.50 EV"); break;
1305                             case 0x0034: chpr += printf("+1.67 EV"); break;
1306                             case 0x0040: chpr += printf("+2 EV"); break;
1307                             default: printred("undefined"); break;
1308                         }
1309                         print_endvalue();
1310                     }
1311                     break;
1312                 case 16:
1313                     if((PRINT_TAGINFO))
1314                         chpr += printf(".%02d_%-28.28s",i,"AutoExposureBracketing**");
1315                     if((PRINT_VALUE))
1316                         chpr += printf(" = %u",value);
1317                     break;
1318                 case 17:
1319                     if((PRINT_TAGINFO))
1320                         chpr += printf(".%02d_%-28.28s",i,"AEBracketValue**");
1321                     if((PRINT_VALUE))
1322                         chpr += printf(" = %u",value);
1323                     break;
1324                 case 18:
1325                     if((PRINT_TAGINFO))
1326                         chpr += printf(".%02d_%-28.28s",i,"Unknown");
1327                     if((PRINT_VALUE))
1328                         chpr += printf(" = %#x%u",value,value);
1329                     break;
1330                 case 19:
1331                     if((PRINT_TAGINFO))
1332                         chpr += printf(".%02d_%-28.28s",i,"FocusDistanceMax**");
1333                     if((PRINT_VALUE))
1334                         chpr += printf(" = %u mm",value);
1335                     break;
1336                 case 20:
1337                     if((PRINT_TAGINFO))
1338                         chpr += printf(".%02d_%-28.28s",i,"FocusDistanceMin**");
1339                     if((PRINT_VALUE))
1340                         chpr += printf(" = %u mm",value);
1341                     break;
1342                 case 21:
1343                     if((PRINT_TAGINFO))
1344                         chpr += printf(".%02d_%-28.28s",i,"ApertureValue**");
1345                     if((PRINT_VALUE))
1346                         chpr += printf(" = %u",value);
1347                     break;
1348                 case 22:
1349                     if((PRINT_TAGINFO))
1350                         chpr += printf(".%02d_%-28.28s",i,"ExposureTime**");
1351                     if((PRINT_VALUE))
1352                         chpr += printf(" = %u",value);
1353                     break;
1354                 case 24:
1355                     if((PRINT_TAGINFO))
1356                         chpr += printf(".%02d_%-28.28s",i,"BulbDuration**");
1357                     if((PRINT_VALUE))
1358                         chpr += printf(" = %u",value);
1359                     break;
1360                 case 27:
1361                     if((PRINT_TAGINFO))
1362                         chpr += printf(".%02d_%-28.28s",i,"AutoRotate**");
1363                     if((PRINT_VALUE))
1364                         chpr += printf(" = %u",value);
1365                     break;
1366                 case 29:
1367                     if((PRINT_TAGINFO))
1368                         chpr += printf(".%02d_%-28.28s",i,"SelfTimer2**");
1369                     if((PRINT_VALUE))
1370                         chpr += printf(" = %u",value);
1371                     break;
1372                 default:
1373                     if((PRINT_TAGINFO))
1374                         chpr += printf(".%02d_%-28.28s",i,"Undefined");
1375                     if((PRINT_VALUE))
1376                         chpr += printf(" = %#x%u",value,value);
1377                     break;
1378             }
1379             chpr = newline(chpr);
1380         }
1381     }
1382     setcharsprinted(chpr);
1383     return(end_offset);
1384 }
1385 
1386 /* Interpret Canon Custom Functions                                   */
1387 unsigned long
canon_customfunctions(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int model,int indent)1388 canon_customfunctions(FILE *inptr,unsigned short byteorder,
1389     char *tagprefix,unsigned long offset,
1390     unsigned long dirlength,int model,int indent)
1391 {
1392     unsigned long max_offset;
1393     int noteversion = 0;
1394 
1395     noteversion = getnoteversion();
1396 
1397     switch(noteversion)
1398     {
1399     case 5:  /* 20 entries (or 21,22) */
1400         max_offset = canon_customfunctions1D(inptr,byteorder,tagprefix,offset,dirlength,indent);
1401         break;
1402     case 4:  /* 18 entries                                            */
1403         max_offset = canon_customfunctions20D(inptr,byteorder,tagprefix,offset,dirlength,indent);
1404         break;
1405     case 3:  /* 17 entries starting at 1*/
1406         max_offset = canon_customfunctions10D(inptr,byteorder,tagprefix,offset,dirlength,indent);
1407         break;
1408     case 2:  /* 16 entries                                            */
1409         max_offset = canon_customfunctionsD30(inptr,byteorder,tagprefix,offset,dirlength,indent);
1410         break;
1411     case 1:  /* unknown customfuctions                                */
1412     default:
1413         max_offset = canon_customfunctions_unk(inptr,byteorder,tagprefix,offset,dirlength,indent);
1414         break;
1415     }
1416     return(max_offset);
1417 }
1418 
1419 /* A "generic" version of customfunctions; just prints the data, with */
1420 /* no interpretation.                                                 */
1421 
1422 unsigned long
canon_customfunctions_unk(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)1423 canon_customfunctions_unk(FILE *inptr,unsigned short byteorder,char *tagprefix,
1424                         unsigned long offset,unsigned long dirlength,int indent)
1425 {
1426     unsigned long count;
1427     unsigned long end_offset;
1428     unsigned short length,value;
1429     int i,cfn,cfv;
1430     int chpr = 0;
1431 
1432     length = read_ushort(inptr,byteorder,offset);
1433     end_offset = offset + dirlength;
1434     if(PRINT_SECTION)
1435     {
1436         chpr += printf(" length %lu",dirlength);
1437         if(length != dirlength)
1438         {
1439             chpr = newline(chpr);
1440             PUSHCOLOR(RED);
1441             print_tag_address(SECTION,offset,indent,"@");
1442             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
1443                         length,dirlength);
1444             POPCOLOR();
1445         }
1446     }
1447     chpr = newline(chpr);
1448 
1449     if((PRINT_ENTRY))
1450     {
1451         offset += 2;
1452         count = (dirlength / sizeof(unsigned short)) - 1;
1453         for(i = 0; i < count; ++i)
1454         {
1455             value = read_ushort(inptr,byteorder,offset);
1456             print_tag_address(ENTRY,offset,indent,"@");
1457             chpr += printf("%s",tagprefix);
1458             offset += 2;
1459             cfn = (value & 0xff00) >> 8;
1460             cfv = value & 0xff;
1461             if(PRINT_SECTION)
1462                 chpr += printf("Unk.%02d: = %#x/%u",cfn,cfv,cfv);
1463             else
1464                 chpr += printf("Unk.%02d = %#x/%u",cfn,cfv,cfv);
1465             chpr = newline(chpr);
1466         }
1467     }
1468     setcharsprinted(chpr);
1469     return(end_offset);
1470 }
1471 
1472 /* CustomFunctions for Canon D30                                      */
1473 
1474 unsigned long
canon_customfunctionsD30(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)1475 canon_customfunctionsD30(FILE *inptr,unsigned short byteorder,char *tagprefix,
1476                         unsigned long offset,unsigned long dirlength,int indent)
1477 {
1478     unsigned long count;
1479     unsigned long end_offset;
1480     unsigned short length,value;
1481     int i,cfn,cfv;
1482     int chpr = 0;
1483 
1484     length = read_ushort(inptr,byteorder,offset);
1485     end_offset = offset + dirlength;
1486     if(PRINT_SECTION)
1487     {
1488         chpr += printf(" length %lu",dirlength);
1489         if(length != dirlength)
1490         {
1491             chpr = newline(chpr);
1492             PUSHCOLOR(RED);
1493             print_tag_address(SECTION,offset,indent,"@");
1494             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
1495                         length,dirlength);
1496             POPCOLOR();
1497         }
1498     }
1499     chpr = newline(chpr);
1500 
1501     if((PRINT_ENTRY))
1502     {
1503         offset += 2;
1504         count = (dirlength / sizeof(unsigned short)) - 1;
1505         for(i = 0; i < count; ++i)
1506         {
1507             value = read_ushort(inptr,byteorder,offset);
1508             print_tag_address(ENTRY,offset,indent,"@");
1509             if((PRINT_TAGINFO))
1510                 chpr += printf("%s",tagprefix);
1511             offset += 2;
1512             cfn = (value & 0xff00) >> 8;
1513             cfv = value & 0xff;
1514             switch(cfn)
1515             {
1516                 case 1:
1517                     if((PRINT_TAGINFO))
1518                         chpr += printf("D30.%02d:%-30.30s",cfn,"LongExposureNoiseReduction");
1519                     if((PRINT_VALUE))
1520                     {
1521                         chpr += printf(" = %u",cfv);
1522                         print_startvalue();
1523                         switch(cfv)
1524                         {
1525                             case 0: chpr += printf("Off"); break;
1526                             case 1: chpr += printf("On"); break;
1527                             default: printred("undefined"); break;
1528                         }
1529                         print_endvalue();
1530                     }
1531                     break;
1532                 case 2:
1533                     if((PRINT_TAGINFO))
1534                         chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterAElockButtons");
1535                     if((PRINT_VALUE))
1536                     {
1537                         chpr += printf(" = %u",cfv);
1538                         print_startvalue();
1539                         switch(cfv)
1540                         {
1541                             case 0: chpr += printf("AF/AE lock"); break;
1542                             case 1: chpr += printf("AE lock/AF"); break;
1543                             case 2: chpr += printf("AF/AF lock"); break;
1544                             case 3: chpr += printf("AE+release/AE+AF"); break;
1545                             default: printred("undefined"); break;
1546                         }
1547                         print_endvalue();
1548                     }
1549                     break;
1550                 case 3:
1551                     if((PRINT_TAGINFO))
1552                         chpr += printf("D30.%02d_%-30.30s",cfn,"MirrorLockup");
1553                     if((PRINT_VALUE))
1554                     {
1555                         chpr += printf(" = %u",cfv);
1556                         print_startvalue();
1557                         switch(cfv)
1558                         {
1559                             case 0: chpr += printf("Disabled"); break;
1560                             case 1: chpr += printf("Enabled"); break;
1561                             default: printred("undefined"); break;
1562                         }
1563                         print_endvalue();
1564                     }
1565                     break;
1566                 case 4:
1567                     if((PRINT_TAGINFO))
1568                         chpr += printf("D30.%02d_%-30.30s",cfn,"TvAvAndExposureLevel");
1569                     if((PRINT_VALUE))
1570                     {
1571                         chpr += printf(" = %u",cfv);
1572                         print_startvalue();
1573                         switch(cfv)
1574                         {
1575                             case 0: chpr += printf("1/2 stop"); break;
1576                             case 1: chpr += printf("1/3 stop"); break;
1577                             default: printred("undefined"); break;
1578                         }
1579                         print_endvalue();
1580                     }
1581                     break;
1582                 case 5:
1583                     if((PRINT_TAGINFO))
1584                         chpr += printf("D30.%02d_%-30.30s",cfn,"AFAssistLight");
1585                     if((PRINT_VALUE))
1586                     {
1587                         chpr += printf(" = %u",cfv);
1588                         print_startvalue();
1589                         switch(cfv)
1590                         {
1591                             case 0: chpr += printf("On (auto)"); break;
1592                             case 1: chpr += printf("Off"); break;
1593                             default: printred("undefined"); break;
1594                         }
1595                         print_endvalue();
1596                     }
1597                     break;
1598                 case 6:
1599                     if((PRINT_TAGINFO))
1600                         chpr += printf("D30.%02d_%-30.30s",cfn,"FlashSyncSpeedAv");
1601                     if((PRINT_VALUE))
1602                     {
1603                         chpr += printf(" = %u",cfv);
1604                         print_startvalue();
1605                         switch(cfv)
1606                         {
1607                             case 0: chpr += printf("Auto"); break;
1608                             case 1: chpr += printf("D30/200 (fixed)"); break;
1609                             default: printred("undefined"); break;
1610                         }
1611                         print_endvalue();
1612                     }
1613                     break;
1614                 case 7:
1615                     if((PRINT_TAGINFO))
1616                         chpr += printf("D30.%02d_%-30.30s",cfn,"AEBSequenceAutoCancellation");
1617                     if((PRINT_VALUE))
1618                     {
1619                         chpr += printf(" = %u",cfv);
1620                         print_startvalue();
1621                         switch(cfv)
1622                         {
1623                             case 0: chpr += printf("0,-,+/Enabled"); break;
1624                             case 1: chpr += printf("0,-,+/Disabled"); break;
1625                             case 2: chpr += printf("-,0,+/Enabled"); break;
1626                             case 3: chpr += printf("-,0,+/Disabled"); break;
1627                             default: printred("undefined"); break;
1628                         }
1629                         print_endvalue();
1630                     }
1631                     break;
1632                 case 8:
1633                     if((PRINT_TAGINFO))
1634                         chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterCurtainSync");
1635                     if((PRINT_VALUE))
1636                     {
1637                         chpr += printf(" = %u",cfv);
1638                         print_startvalue();
1639                         switch(cfv)
1640                         {
1641                             case 0: chpr += printf("D30-curtain sync"); break;
1642                             case 1: chpr += printf("2nd-curtain sync"); break;
1643                             default: printred("undefined"); break;
1644                         }
1645                         print_endvalue();
1646                     }
1647                     break;
1648                 case 9:
1649                     if((PRINT_TAGINFO))
1650                         chpr += printf("D30.%02d_%-30.30s",cfn,"LensAFStopButtonFnSwitch");
1651                     if((PRINT_VALUE))
1652                     {
1653                         chpr += printf(" = %u",cfv);
1654                         print_startvalue();
1655                         switch(cfv)
1656                         {
1657                             case 0: chpr += printf("AF Stop"); break;
1658                             case 1: chpr += printf("Operate AF"); break;
1659                             case 2: chpr += printf("Lock AE and start timer"); break;
1660                             default: printred("undefined"); break;
1661                         }
1662                         print_endvalue();
1663                     }
1664                     break;
1665                 case 10:
1666                     if((PRINT_TAGINFO))
1667                         chpr += printf("D30.%02d_%-30.30s",cfn,"AutoReductionOfFillFlash");
1668                     if((PRINT_VALUE))
1669                     {
1670                         chpr += printf(" = %u",cfv);
1671                         print_startvalue();
1672                         switch(cfv)
1673                         {
1674                             case 0: chpr += printf("Enabled"); break;
1675                             case 1: chpr += printf("Disabled"); break;
1676                             default: printred("undefined"); break;
1677                         }
1678                         print_endvalue();
1679                     }
1680                     break;
1681                 case 11:
1682                     if((PRINT_TAGINFO))
1683                         chpr += printf("D30.%02d_%-30.30s",cfn,"MenuButtonReturnPosition");
1684                     if((PRINT_VALUE))
1685                     {
1686                         chpr += printf(" = %u",cfv);
1687                         print_startvalue();
1688                         switch(cfv)
1689                         {
1690                             case 0: chpr += printf("Top"); break;
1691                             case 1: chpr += printf("Previous (volatile)"); break;
1692                             case 2: chpr += printf("Previous"); break;
1693                             default: printred("undefined"); break;
1694                         }
1695                         print_endvalue();
1696                     }
1697                     break;
1698                 case 12:
1699                     if((PRINT_TAGINFO))
1700                         chpr += printf("D30.%02d_%-30.30s",cfn,"SETButtonFuncWhenShooting");
1701                     if((PRINT_VALUE))
1702                     {
1703                         chpr += printf(" = %u",cfv);
1704                         print_startvalue();
1705                         switch(cfv)
1706                         {
1707                             case 0: chpr += printf("Not assigned"); break;
1708                             case 1: chpr += printf("Change quality"); break;
1709                             case 2: chpr += printf("Change ISO speed"); break;
1710                             case 3: chpr += printf("PreviouSelect parameters"); break;
1711                             default: printred("undefined"); break;
1712                         }
1713                         print_endvalue();
1714                     }
1715                     break;
1716                 case 13:
1717                     if((PRINT_TAGINFO))
1718                         chpr += printf("D30.%02d_%-30.30s",cfn,"SensorCleaning");
1719                     if((PRINT_VALUE))
1720                     {
1721                         chpr += printf(" = %u",cfv);
1722                         print_startvalue();
1723                         switch(cfv)
1724                         {
1725                             case 0: chpr += printf("Disabled"); break;
1726                             case 1: chpr += printf("Enabled"); break;
1727                             default: printred("undefined"); break;
1728                         }
1729                         print_endvalue();
1730                     }
1731                     break;
1732                 case 14:
1733                     if((PRINT_TAGINFO))
1734                         chpr += printf("D30.%02d_%-30.30s",cfn,"SuperimposedDisplay*");
1735                     if((PRINT_VALUE))
1736                     {
1737                         chpr += printf(" = %u",cfv);
1738                         print_startvalue();
1739                         switch(cfv)
1740                         {
1741                             case 0: chpr += printf("On"); break;
1742                             case 1: chpr += printf("Off"); break;
1743                             default: printred("undefined"); break;
1744                         }
1745                         print_endvalue();
1746                     }
1747                     break;
1748                 case 15:
1749                     if((PRINT_TAGINFO))
1750                         chpr += printf("D30.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard*");
1751                     if((PRINT_VALUE))
1752                     {
1753                         chpr += printf(" = %u",cfv);
1754                         print_startvalue();
1755                         switch(cfv)
1756                         {
1757                             case 0: chpr += printf("Yes"); break;
1758                             case 1: chpr += printf("No"); break;
1759                             default: printred("undefined"); break;
1760                         }
1761                         print_endvalue();
1762                     }
1763                     break;
1764                 default:
1765                     if((PRINT_TAGINFO))
1766                         chpr += printf("D30.%02d_%-30.30s",cfn,"undefined");
1767                     if((PRINT_VALUE))
1768                         chpr += printf(" = %#x/%u",cfv,cfv);
1769                     break;
1770             }
1771             chpr = newline(chpr);
1772         }
1773     }
1774     setcharsprinted(chpr);
1775     return(end_offset);
1776 }
1777 
1778 /* CustomFunctions for Canon 10D                                      */
1779 
1780 unsigned long
canon_customfunctions10D(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)1781 canon_customfunctions10D(FILE *inptr,unsigned short byteorder,char *tagprefix,
1782                         unsigned long offset,unsigned long dirlength,int indent)
1783 {
1784     unsigned long count;
1785     unsigned long end_offset;
1786     unsigned short length,value;
1787     int i,cfn,cfv;
1788     int chpr = 0;
1789 
1790     end_offset = offset + dirlength;
1791     length = read_ushort(inptr,byteorder,offset);
1792     if(PRINT_SECTION)
1793     {
1794         chpr += printf(" length %lu",dirlength);
1795         if(length != dirlength)
1796         {
1797             chpr = newline(chpr);
1798             PUSHCOLOR(RED);
1799             print_tag_address(SECTION,offset,indent,"@");
1800             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
1801                         length,dirlength);
1802             POPCOLOR();
1803         }
1804     }
1805     chpr = newline(chpr);
1806 
1807     if((PRINT_ENTRY))
1808     {
1809         offset += 2;
1810         count = (dirlength / sizeof(unsigned short)) - 1;
1811 
1812         for(i = 0; i < count; ++i)
1813         {
1814             value = read_ushort(inptr,byteorder,offset);
1815             print_tag_address(ENTRY,offset,indent,"@");
1816             if((PRINT_TAGINFO))
1817                 chpr += printf("%s",tagprefix);
1818             offset += 2;
1819             cfn = (value & 0xff00) >> 8;
1820             cfv = value & 0xff;
1821             switch(cfn)
1822             {
1823                 case 1:
1824                     if((PRINT_TAGINFO))
1825                         chpr += printf("10D.%02d_%-30.30s",cfn,"Set Button Function");
1826                     if((PRINT_VALUE))
1827                     {
1828                         chpr += printf(" = %u",cfv);
1829                         print_startvalue();
1830                         switch(cfv)
1831                         {
1832                             case 0: chpr += printf("Not assigned"); break;
1833                             case 1: chpr += printf("Change quality"); break;
1834                             case 2: chpr += printf("Change parameters"); break;
1835                             case 3: chpr += printf("Menu display"); break;
1836                             case 4: chpr += printf("Image replay"); break;
1837                             default: printred("undefined"); break;
1838                         }
1839                         print_endvalue();
1840                     }
1841                     break;
1842                 case 2:
1843                     if((PRINT_TAGINFO))
1844                         chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard");
1845                     if((PRINT_VALUE))
1846                     {
1847                         chpr += printf(" = %u",cfv);
1848                         print_startvalue();
1849                         switch(cfv)
1850                         {
1851                             case 0: chpr += printf("Yes"); break;
1852                             case 1: chpr += printf("No"); break;
1853                             default: printred("undefined"); break;
1854                         }
1855                         print_endvalue();
1856                     }
1857                     break;
1858                 case 3:
1859                     if((PRINT_TAGINFO))
1860                         chpr += printf("10D.%02d_%-30.30s",cfn,"FlashSyncSpeedAv");
1861                     if((PRINT_VALUE))
1862                     {
1863                         chpr += printf(" = %u",cfv);
1864                         print_startvalue();
1865                         switch(cfv)
1866                         {
1867                             case 0: chpr += printf("Auto"); break;
1868                             case 1: chpr += printf("1/200 (fixed)"); break;
1869                             default: printred("undefined"); break;
1870                         }
1871                         print_endvalue();
1872                     }
1873                     break;
1874                 case 4:
1875                     if((PRINT_TAGINFO))
1876                         chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterAElockButtons");
1877                     if((PRINT_VALUE))
1878                     {
1879                         chpr += printf(" = %u",cfv);
1880                         print_startvalue();
1881                         switch(cfv)
1882                         {
1883                             case 0: chpr += printf("AF/AE lock"); break;
1884                             case 1: chpr += printf("AE lock/AF"); break;
1885                             case 2: chpr += printf("AF/AF lock"); break;
1886                             case 3: chpr += printf("AE/AF"); break;
1887                             default: printred("undefined"); break;
1888                         }
1889                         print_endvalue();
1890                     }
1891                     break;
1892                 case 5:
1893                     if((PRINT_TAGINFO))
1894                         chpr += printf("10D.%02d_%-30.30s",cfn,"AFAssistLight");
1895                     if((PRINT_VALUE))
1896                     {
1897                         chpr += printf(" = %u",cfv);
1898                         print_startvalue();
1899                         switch(cfv)
1900                         {
1901                             case 0: chpr += printf("Emits/Fires"); break;
1902                             case 1: chpr += printf("Does not emit/Fires"); break;
1903                             case 2: chpr += printf("Only ext flash emits/Fires"); break;
1904                             case 3: chpr += printf("Emits/Does not fire"); break;
1905                             default: printred("undefined"); break;
1906                         }
1907                         print_endvalue();
1908                     }
1909                     break;
1910                 case 6:
1911                     if((PRINT_TAGINFO))
1912                         chpr += printf("10D.%02d_%-30.30s",cfn,"ExposureLevelIncrements");
1913                     if((PRINT_VALUE))
1914                     {
1915                         chpr += printf(" = %u",cfv);
1916                         print_startvalue();
1917                         switch(cfv)
1918                         {
1919                             case 0: chpr += printf("1/2 stop"); break;
1920                             case 1: chpr += printf("1/3 stop"); break;
1921                             default: printred("undefined"); break;
1922                         }
1923                         print_endvalue();
1924                     }
1925                     break;
1926                 case 7:
1927                     if((PRINT_TAGINFO))
1928                         chpr += printf("10D.%02d_%-30.30s",cfn,"AFPointRegistration");
1929                     if((PRINT_VALUE))
1930                     {
1931                         chpr += printf(" = %u",cfv);
1932                         print_startvalue();
1933                         switch(cfv)
1934                         {
1935                             case 0: chpr += printf("Center"); break;
1936                             case 1: chpr += printf("Bottom"); break;
1937                             case 2: chpr += printf("Right"); break;
1938                             case 3: chpr += printf("Extreme Right"); break;
1939                             case 4: chpr += printf("Automatic"); break;
1940                             case 5: chpr += printf("Extreme Left"); break;
1941                             case 6: chpr += printf("Left"); break;
1942                             case 7: chpr += printf("Top"); break;
1943                             default: printred("undefined"); break;
1944                         }
1945                         print_endvalue();
1946                     }
1947                     break;
1948                 case 8:
1949                     if((PRINT_TAGINFO))
1950                         chpr += printf("10D.%02d_%-30.30s",cfn,"RawandJpegRecording");
1951                     if((PRINT_VALUE))
1952                     {
1953                         chpr += printf(" = %u",cfv);
1954                         print_startvalue();
1955                         switch(cfv)
1956                         {
1957                             case 0: chpr += printf("RAW+Small/Normal"); break;
1958                             case 1: chpr += printf("RAW+Small/Fine"); break;
1959                             case 2: chpr += printf("RAW+Medium/Normal"); break;
1960                             case 3: chpr += printf("RAW+Medium/Fine"); break;
1961                             case 4: chpr += printf("RAW+Large/Normal"); break;
1962                             case 5: chpr += printf("RAW+Large/Fine"); break;
1963                             default: printred("undefined"); break;
1964                         }
1965                         print_endvalue();
1966                     }
1967                     break;
1968                 case 9:
1969                     if((PRINT_TAGINFO))
1970                         chpr += printf("10D.%02d_%-30.30s",cfn,"AEBSequence");
1971                     if((PRINT_VALUE))
1972                     {
1973                         chpr += printf(" = %u",cfv);
1974                         print_startvalue();
1975                         switch(cfv)
1976                         {
1977                             case 0: chpr += printf("0,-,+/Enabled"); break;
1978                             case 1: chpr += printf("0,-,+/Disabled"); break;
1979                             case 2: chpr += printf("-,0,+/Enabled"); break;
1980                             case 3: chpr += printf("-,0,+/Disabled"); break;
1981                             default: printred("undefined"); break;
1982                         }
1983                         print_endvalue();
1984                     }
1985                     break;
1986                 case 10:
1987                     if((PRINT_TAGINFO))
1988                         chpr += printf("10D.%02d_%-30.30s",cfn,"SuperimposedDisplay");
1989                     if((PRINT_VALUE))
1990                     {
1991                         chpr += printf(" = %u",cfv);
1992                         print_startvalue();
1993                         switch(cfv)
1994                         {
1995                             case 0: chpr += printf("On"); break;
1996                             case 1: chpr += printf("Off"); break;
1997                             default: printred("undefined"); break;
1998                         }
1999                         print_endvalue();
2000                     }
2001                     break;
2002                 case 11:
2003                     if((PRINT_TAGINFO))
2004                         chpr += printf("10D.%02d_%-30.30s",cfn,"MenuButtonDisplayPosition");
2005                     if((PRINT_VALUE))
2006                     {
2007                         chpr += printf(" = %u",cfv);
2008                         print_startvalue();
2009                         switch(cfv)
2010                         {
2011                             case 0: chpr += printf("Previous (volatile)"); break;
2012                             case 1: chpr += printf("Previous"); break;
2013                             case 2: chpr += printf("Top"); break;
2014                             default: printred("undefined"); break;
2015                         }
2016                         print_endvalue();
2017                     }
2018                     break;
2019                 case 12:
2020                     if((PRINT_TAGINFO))
2021                         chpr += printf("10D.%02d_%-30.30s",cfn,"MirrorLockup");
2022                     if((PRINT_VALUE))
2023                     {
2024                         chpr += printf(" = %u",cfv);
2025                         print_startvalue();
2026                         switch(cfv)
2027                         {
2028                             case 0: chpr += printf("Disabled"); break;
2029                             case 1: chpr += printf("Enabled"); break;
2030                             default: printred("undefined"); break;
2031                         }
2032                         print_endvalue();
2033                     }
2034                     break;
2035                 case 13:
2036                     if((PRINT_TAGINFO))
2037                         chpr += printf("10D.%02d_%-30.30s",cfn,"AssistButtonFunction");
2038                     if((PRINT_VALUE))
2039                     {
2040                         chpr += printf(" = %u",cfv);
2041                         print_startvalue();
2042                         switch(cfv)
2043                         {
2044                             case 0: chpr += printf("Normal"); break;
2045                             case 1: chpr += printf("Select home position"); break;
2046                             case 2: chpr += printf("Select HP (while pressing)"); break;
2047                             case 3: chpr += printf("Ax+/-(AF point by QCD)"); break;
2048                             case 4: chpr += printf("FE lock"); break;
2049                             default: printred("undefined"); break;
2050                         }
2051                         print_endvalue();
2052                     }
2053                     break;
2054                 case 14:
2055                     if((PRINT_TAGINFO))
2056                         chpr += printf("10D.%02d_%-30.30s",cfn,"FillFlashAutoReduction");
2057                     if((PRINT_VALUE))
2058                     {
2059                         chpr += printf(" = %u",cfv);
2060                         print_startvalue();
2061                         switch(cfv)
2062                         {
2063                             case 0: chpr += printf("Enabled"); break;
2064                             case 1: chpr += printf("Disabled"); break;
2065                             default: printred("undefined"); break;
2066                         }
2067                         print_endvalue();
2068                     }
2069                     break;
2070                 case 15:
2071                     if((PRINT_TAGINFO))
2072                         chpr += printf("10D.%02d_%-30.30s",cfn,"ShutterCurtainSync");
2073                     if((PRINT_VALUE))
2074                     {
2075                         chpr += printf(" = %u",cfv);
2076                         print_startvalue();
2077                         switch(cfv)
2078                         {
2079                             case 0: chpr += printf("1st-curtain sync"); break;
2080                             case 1: chpr += printf("2nd-curtain sync"); break;
2081                             default: printred("undefined"); break;
2082                         }
2083                         print_endvalue();
2084                     }
2085                     break;
2086                 case 16:
2087                     if((PRINT_TAGINFO))
2088                         chpr += printf("10D.%02d_%-30.30s",cfn,"SafetyShiftInAvOrTv");
2089                     if((PRINT_VALUE))
2090                     {
2091                         chpr += printf(" = %u",cfv);
2092                         print_startvalue();
2093                         switch(cfv)
2094                         {
2095                             case 0: chpr += printf("Disable"); break;
2096                             case 1: chpr += printf("Enable"); break;
2097                             default: printred("undefined"); break;
2098                         }
2099                         print_endvalue();
2100                     }
2101                     break;
2102                 case 17:
2103                     if((PRINT_TAGINFO))
2104                         chpr += printf("10D.%02d_%-30.30s",cfn,"LensAFStopButton");
2105                     if((PRINT_VALUE))
2106                     {
2107                         chpr += printf(" = %u",cfv);
2108                         print_startvalue();
2109                         switch(cfv)
2110                         {
2111                             case 0: chpr += printf("AF Stop"); break;
2112                             case 1: chpr += printf("Operate AF"); break;
2113                             case 2: chpr += printf("Lock AE and start timer"); break;
2114                             default: printred("undefined"); break;
2115                         }
2116                         print_endvalue();
2117                     }
2118                     break;
2119                 default:
2120                     if((PRINT_TAGINFO))
2121                         chpr += printf("10D.%02d_%-30.30s",cfn,"undefined");
2122                     if((PRINT_VALUE))
2123                         chpr += printf(" = %#x/%u",cfv,cfv);
2124                     break;
2125             }
2126             chpr = newline(chpr);
2127         }
2128     }
2129     setcharsprinted(chpr);
2130     return(end_offset);
2131 }
2132 
2133 /* CustomFunctions for Canon 20D                                      */
2134 
2135 unsigned long
canon_customfunctions20D(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)2136 canon_customfunctions20D(FILE *inptr,unsigned short byteorder,char *tagprefix,
2137                         unsigned long offset,unsigned long dirlength,int indent)
2138 {
2139     unsigned long count;
2140     unsigned long end_offset;
2141     unsigned short length,value;
2142     int i,cfn,cfv;
2143     int chpr = 0;
2144 
2145     end_offset = offset + dirlength;
2146     length = read_ushort(inptr,byteorder,offset);
2147     if(PRINT_SECTION)
2148     {
2149         chpr += printf(" length %lu",dirlength);
2150         if(length != dirlength)
2151         {
2152             chpr = newline(chpr);
2153             PUSHCOLOR(RED);
2154             print_tag_address(SECTION,offset,indent,"@");
2155             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
2156                         length,dirlength);
2157             POPCOLOR();
2158         }
2159     }
2160     chpr = newline(chpr);
2161 
2162     if((PRINT_ENTRY))
2163     {
2164         offset += 2;
2165         count = (dirlength / sizeof(unsigned short)) - 1;
2166 
2167         for(i = 0; i < count; ++i)
2168         {
2169             value = read_ushort(inptr,byteorder,offset);
2170             print_tag_address(ENTRY,offset,indent,"@");
2171             if((PRINT_TAGINFO))
2172                 chpr += printf("%s",tagprefix);
2173             offset += 2;
2174             cfn = (value & 0xff00) >> 8;
2175             cfv = value & 0xff;
2176             switch(cfn)
2177             {
2178                 case 0:
2179                     if((PRINT_TAGINFO))
2180                         chpr += printf("20D.%02d_%-30.30s",cfn,"SetButtonFunctionWhenShooting");
2181                     if((PRINT_VALUE))
2182                     {
2183                         chpr += printf(" = %u",cfv);
2184                         print_startvalue();
2185                         switch(cfv)
2186                         {
2187                             case 0: chpr += printf("(no function)"); break;
2188                             case 1: chpr += printf("change quality"); break;
2189                             case 2: chpr += printf("change parameters"); break;
2190                             case 3: chpr += printf("menu display"); break;
2191                             case 4: chpr += printf("image replay"); break;
2192                             default: printred("undefined"); break;
2193                         }
2194                     }
2195                     print_endvalue();
2196                     break;
2197                 case 1:
2198                     if((PRINT_TAGINFO))
2199                         chpr += printf("20D.%02d_%-30.30s",cfn,"LongExposureNoiseReduction");
2200                     if((PRINT_VALUE))
2201                     {
2202                         chpr += printf(" = %u",cfv);
2203                         print_startvalue();
2204                         switch(cfv)
2205                         {
2206                             case 0: chpr += printf("Off"); break;
2207                             case 1: chpr += printf("On"); break;
2208                             default: printred("undefined"); break;
2209                         }
2210                         print_endvalue();
2211                     }
2212                     break;
2213                 case 2:
2214                     if((PRINT_TAGINFO))
2215                         chpr += printf("20D.%02d_%-30.30s",cfn,"FlashSyncSpeedAv");
2216                     if((PRINT_VALUE))
2217                     {
2218                         chpr += printf(" = %u",cfv);
2219                         print_startvalue();
2220                         switch(cfv)
2221                         {
2222                             case 0: chpr += printf("Auto"); break;
2223                             case 1: chpr += printf("1/200 (fixed)"); break;
2224                             default: printred("undefined"); break;
2225                         }
2226                         print_endvalue();
2227                     }
2228                     break;
2229                 case 3:
2230                     if((PRINT_TAGINFO))
2231                         chpr += printf("20D.%02d_%-30.30s",cfn,"ShutterAElockButtons");
2232                     if((PRINT_VALUE))
2233                     {
2234                         chpr += printf(" = %u",cfv);
2235                         print_startvalue();
2236                         switch(cfv)
2237                         {
2238                             case 0: chpr += printf("AF/AE lock"); break;
2239                             case 1: chpr += printf("AE lock/AF"); break;
2240                             case 2: chpr += printf("AF/AF lock"); break;
2241                             case 3: chpr += printf("AE+release/AE+AF"); break;
2242                             default: printred("undefined"); break;
2243                         }
2244                         print_endvalue();
2245                     }
2246                     break;
2247                 case 4:
2248                     if((PRINT_TAGINFO))
2249                         chpr += printf("20D.%02d_%-30.30s",cfn,"AFAssistLight");
2250                     if((PRINT_VALUE))
2251                     {
2252                         chpr += printf(" = %u",cfv);
2253                         print_startvalue();
2254                         switch(cfv)
2255                         {
2256                             case 0: chpr += printf("Emits"); break;
2257                             case 1: chpr += printf("Does not emit"); break;
2258                             case 2: chpr += printf("Only ext flash emits"); break;
2259                             default: printred("undefined"); break;
2260                         }
2261                         print_endvalue();
2262                     }
2263                     break;
2264                 case 5:
2265                     if((PRINT_TAGINFO))
2266                         chpr += printf("20D.%02d_%-30.30s",cfn,"ExposureLevelIncrements");
2267                     if((PRINT_VALUE))
2268                     {
2269                         chpr += printf(" = %u",cfv);
2270                         print_startvalue();
2271                         switch(cfv)
2272                         {
2273                             case 0: chpr += printf("1/2 stop"); break;
2274                             case 1: chpr += printf("1/3 stop"); break;
2275                             default: printred("undefined"); break;
2276                         }
2277                         print_endvalue();
2278                     }
2279                     break;
2280                 case 6:
2281                     if((PRINT_TAGINFO))
2282                         chpr += printf("20D.%02d_%-30.30s",cfn,"FlashFiring");
2283                     if((PRINT_VALUE))
2284                     {
2285                         chpr += printf(" = %u",cfv);
2286                         print_startvalue();
2287                         switch(cfv)
2288                         {
2289                             case 0: chpr += printf("Fires"); break;
2290                             case 1: chpr += printf("Does not fire"); break;
2291                             default: printred("undefined"); break;
2292                         }
2293                         print_endvalue();
2294                     }
2295                     break;
2296                 case 7:
2297                     if((PRINT_TAGINFO))
2298                         chpr += printf("20D.%02d_%-30.30s",cfn,"ISOSpeedExpansion");
2299                     if((PRINT_VALUE))
2300                     {
2301                         chpr += printf(" = %u",cfv);
2302                         print_startvalue();
2303                         switch(cfv)
2304                         {
2305                             case 0: chpr += printf("Off"); break;
2306                             case 1: chpr += printf("On"); break;
2307                             default: printred("undefined"); break;
2308                         }
2309                         print_endvalue();
2310                     }
2311                     break;
2312                 case 8:
2313                     if((PRINT_TAGINFO))
2314                         chpr += printf("20D.%02d_%-30.30s",cfn,"AEBSequence");
2315                     if((PRINT_VALUE))
2316                     {
2317                         chpr += printf(" = %u",cfv);
2318                         print_startvalue();
2319                         switch(cfv)
2320                         {
2321                             case 0: chpr += printf("0,-,+/Enabled"); break;
2322                             case 1: chpr += printf("0,-,+/Disabled"); break;
2323                             case 2: chpr += printf("-,0,+/Enabled"); break;
2324                             case 3: chpr += printf("-,0,+/Disabled"); break;
2325                             default: printred("undefined"); break;
2326                         }
2327                         print_endvalue();
2328                     }
2329                     break;
2330                 case 9:
2331                     if((PRINT_TAGINFO))
2332                         chpr += printf("20D.%02d_%-30.30s",cfn,"SuperimposedDisplay");
2333                     if((PRINT_VALUE))
2334                     {
2335                         chpr += printf(" = %u",cfv);
2336                         print_startvalue();
2337                         switch(cfv)
2338                         {
2339                             case 0: chpr += printf("On"); break;
2340                             case 1: chpr += printf("Off"); break;
2341                             default: printred("undefined"); break;
2342                         }
2343                         print_endvalue();
2344                     }
2345                     break;
2346                 case 10:
2347                     if((PRINT_TAGINFO))
2348                         chpr += printf("20D.%02d_%-30.30s",cfn,"MenuButtonDisplayPosition");
2349                     if((PRINT_VALUE))
2350                     {
2351                         chpr += printf(" = %u",cfv);
2352                         print_startvalue();
2353                         switch(cfv)
2354                         {
2355                             case 0: chpr += printf("Top"); break;
2356                             case 1: chpr += printf("Previous (volatile)"); break;
2357                             case 2: chpr += printf("Previous"); break;
2358                             default: printred("undefined"); break;
2359                         }
2360                         print_endvalue();
2361                     }
2362                     break;
2363                 case 11:
2364                     if((PRINT_TAGINFO))
2365                         chpr += printf("20D.%02d_%-30.30s",cfn,"MirrorLockup");
2366                     if((PRINT_VALUE))
2367                     {
2368                         chpr += printf(" = %u",cfv);
2369                         print_startvalue();
2370                         switch(cfv)
2371                         {
2372                             case 0: chpr += printf("Disabled"); break;
2373                             case 1: chpr += printf("Enabled"); break;
2374                             default: printred("undefined"); break;
2375                         }
2376                         print_endvalue();
2377                     }
2378                     break;
2379                 case 12:
2380                     if((PRINT_TAGINFO))
2381                         chpr += printf("20D.%02d_%-30.30s",cfn,"AFPointSelectionMethod");
2382                     if((PRINT_VALUE))
2383                     {
2384                         chpr += printf(" = %u",cfv);
2385                         print_startvalue();
2386                         switch(cfv)
2387                         {
2388                             case 0: chpr += printf("Normal"); break;
2389                             case 1: chpr += printf("Multi-controller direct"); break;
2390                             case 2: chpr += printf("Quick control dial direct"); break;
2391                             default: printred("undefined"); break;
2392                         }
2393                         print_endvalue();
2394                     }
2395                     break;
2396                 case 13:
2397                     if((PRINT_TAGINFO))
2398                         chpr += printf("20D.%02d_%-30.30s",cfn,"ETTLII");
2399                     if((PRINT_VALUE))
2400                     {
2401                         chpr += printf(" = %u",cfv);
2402                         print_startvalue();
2403                         switch(cfv)
2404                         {
2405                             case 0: chpr += printf("Evaluative"); break;
2406                             case 1: chpr += printf("Average"); break;
2407                             default: printred("undefined"); break;
2408                         }
2409                         print_endvalue();
2410                     }
2411                     break;
2412                 case 14:
2413                     if((PRINT_TAGINFO))
2414                         chpr += printf("20D.%02d_%-30.30s",cfn,"ShutterCurtainSync");
2415                     if((PRINT_VALUE))
2416                     {
2417                         chpr += printf(" = %u",cfv);
2418                         print_startvalue();
2419                         switch(cfv)
2420                         {
2421                             case 0: chpr += printf("1st-curtain sync"); break;
2422                             case 1: chpr += printf("2nd-curtain sync"); break;
2423                             default: printred("undefined"); break;
2424                         }
2425                         print_endvalue();
2426                     }
2427                     break;
2428                 case 15:
2429                     if((PRINT_TAGINFO))
2430                         chpr += printf("20D.%02d_%-30.30s",cfn,"SafetyShiftInAvOrTv");
2431                     if((PRINT_VALUE))
2432                     {
2433                         chpr += printf(" = %u",cfv);
2434                         print_startvalue();
2435                         switch(cfv)
2436                         {
2437                             case 0: chpr += printf("Disable"); break;
2438                             case 1: chpr += printf("Enable"); break;
2439                             default: printred("undefined"); break;
2440                         }
2441                         print_endvalue();
2442                     }
2443                     break;
2444                 case 16:
2445                     if((PRINT_TAGINFO))
2446                         chpr += printf("20D.%02d_%-30.30s",cfn,"LensAFStopButton");
2447                     if((PRINT_VALUE))
2448                     {
2449                         chpr += printf(" = %u",cfv);
2450                         print_startvalue();
2451                         switch(cfv)
2452                         {
2453                             case 0: chpr += printf("AF Stop"); break;
2454                             case 1: chpr += printf("Operate AF"); break;
2455                             case 2: chpr += printf("Lock AE and start timer"); break;
2456                             default: printred("undefined"); break;
2457                         }
2458                         print_endvalue();
2459                     }
2460                     break;
2461                 case 17:
2462                     if((PRINT_TAGINFO))
2463                         chpr += printf("20D.%02d_%-30.30s",cfn,"AddOriginalDecisionData");
2464                     if((PRINT_VALUE))
2465                     {
2466                         chpr += printf(" = %u",cfv);
2467                         print_startvalue();
2468                         switch(cfv)
2469                         {
2470                             case 0: chpr += printf("Off"); break;
2471                             case 1: chpr += printf("On"); break;
2472                             default: printred("undefined"); break;
2473                         }
2474                         print_endvalue();
2475                     }
2476                     break;
2477                 default:
2478                     if((PRINT_TAGINFO))
2479                         chpr += printf("20D.%02d_%-30.30s",cfn,"undefined");
2480                     if((PRINT_VALUE))
2481                         chpr += printf(" = %#x/%u",cfv,cfv);
2482                     break;
2483             }
2484             chpr = newline(chpr);
2485         }
2486     }
2487     setcharsprinted(chpr);
2488     return(end_offset);
2489 }
2490 
2491 /* CustomFunctions for Canon 1D                                       */
2492 
2493 unsigned long
canon_customfunctions1D(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)2494 canon_customfunctions1D(FILE *inptr,unsigned short byteorder,char *tagprefix,
2495                             unsigned long offset,unsigned long dirlength,int indent)
2496 {
2497     unsigned long count;
2498     unsigned long end_offset;
2499     unsigned short length,value;
2500     int i,cfn,cfv;
2501     int chpr = 0;
2502 
2503     end_offset = offset + dirlength;
2504     length = read_ushort(inptr,byteorder,offset);
2505     if(PRINT_SECTION)
2506     {
2507         chpr += printf(" length %lu",dirlength);
2508         if(length != dirlength)
2509         {
2510             chpr = newline(chpr);
2511             PUSHCOLOR(RED);
2512             print_tag_address(SECTION,offset,indent,"@");
2513             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
2514                         length,dirlength);
2515             POPCOLOR();
2516         }
2517     }
2518     chpr = newline(chpr);
2519 
2520     if((PRINT_ENTRY))
2521     {
2522         offset += 2;
2523         count = (dirlength / sizeof(unsigned short)) - 1;
2524 
2525         for(i = 0; i < count; ++i)
2526         {
2527             value = read_ushort(inptr,byteorder,offset);
2528             print_tag_address(ENTRY,offset,indent,"@");
2529             chpr += printf("%s",tagprefix);
2530             offset += 2;
2531             cfn = (value & 0xff00) >> 8;
2532             cfv = value & 0xff;
2533             switch(cfn)
2534             {
2535                 case 0:
2536                     if((PRINT_TAGINFO))
2537                         chpr += printf("1D.%02d_%-30.30s",cfn,"FocusingScreen");
2538                     if((PRINT_VALUE))
2539                     {
2540                         chpr += printf(" = %u",cfv);
2541                         print_startvalue();
2542                         switch(cfv)
2543                         {
2544                             case 0: chpr += printf("Ec-N,R"); break;
2545                             case 1: chpr += printf("Ec-A,B,C,CII,CIII,D,H,I,L"); break;
2546                             default: printred("undefined"); break;
2547                         }
2548                         print_endvalue();
2549                     }
2550                     break;
2551                 case 1:
2552                     if((PRINT_TAGINFO))
2553                         chpr += printf("1D.%02d_%-30.30s",cfn,"FinderDisplayDuringExposure");
2554                     if((PRINT_VALUE))
2555                     {
2556                         chpr += printf(" = %u",cfv);
2557                         print_startvalue();
2558                         switch(cfv)
2559                         {
2560                             case 0: chpr += printf("Off"); break;
2561                             case 1: chpr += printf("On"); break;
2562                             default: printred("undefined"); break;
2563                         }
2564                         print_endvalue();
2565                     }
2566                     break;
2567                 case 2:
2568                     if((PRINT_TAGINFO))
2569                         chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterReleaseNoCFCard");
2570                     if((PRINT_VALUE))
2571                     {
2572                         chpr += printf(" = %u",cfv);
2573                         print_startvalue();
2574                         switch(cfv)
2575                         {
2576                             case 0: chpr += printf("Yes"); break;
2577                             case 1: chpr += printf("No"); break;
2578                             default: printred("undefined"); break;
2579                         }
2580                         print_endvalue();
2581                     }
2582                     break;
2583                 case 3:
2584                     if((PRINT_TAGINFO))
2585                         chpr += printf("1D.%02d_%-30.30s",cfn,"ISOSpeedExpansion");
2586                     if((PRINT_VALUE))
2587                     {
2588                         chpr += printf(" = %u",cfv);
2589                         print_startvalue();
2590                         switch(cfv)
2591                         {
2592                             case 0: chpr += printf("No"); break;
2593                             case 1: chpr += printf("Yes"); break;
2594                             default: printred("undefined"); break;
2595                         }
2596                         print_endvalue();
2597                     }
2598                     break;
2599                 case 4:
2600                     if((PRINT_TAGINFO))
2601                         chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterAElockButtons");
2602                     if((PRINT_VALUE))
2603                     {
2604                         chpr += printf(" = %u",cfv);
2605                         print_startvalue();
2606                         switch(cfv)
2607                         {
2608                             case 0: chpr += printf("AF/AE lock"); break;
2609                             case 1: chpr += printf("AE lock/AF"); break;
2610                             case 2: chpr += printf("AF/AF lock"); break;
2611                             case 3: chpr += printf("AE+release/AE+AF"); break;
2612                             default: printred("undefined"); break;
2613                         }
2614                         print_endvalue();
2615                     }
2616                     break;
2617                 case 5:
2618                     if((PRINT_TAGINFO))
2619                         chpr += printf("1D.%02d_%-30.30s",cfn,"ManualTv");
2620                     if((PRINT_VALUE))
2621                     {
2622                         chpr += printf(" = %u",cfv);
2623                         print_startvalue();
2624                         switch(cfv)
2625                         {
2626                             case 0: chpr += printf("Tv:Main/Av:Control"); break;
2627                             case 1: chpr += printf("Tv:Control/Av:Main"); break;
2628                             case 2: chpr += printf("Tv:Main/Av:Main w/o lens"); break;
2629                             case 3: chpr += printf("Tv:Control/Av:Main w/o lens"); break;
2630                             default: printred("undefined"); break;
2631                         }
2632                         print_endvalue();
2633                     }
2634                     break;
2635                 case 6:
2636                     if((PRINT_TAGINFO))
2637                         chpr += printf("1D.%02d_%-30.30s",cfn,"ExposureLevelIncrements");
2638                     if((PRINT_VALUE))
2639                     {
2640                         chpr += printf(" = %u",cfv);
2641                         print_startvalue();
2642                         switch(cfv)
2643                         {
2644                             case 0: chpr += printf("1/3-Stop set, 1/3-Stop comp"); break;
2645                             case 1: chpr += printf("1-Stop set, 1/3-Stop comp"); break;
2646                             case 2: chpr += printf("1/2-Stop set, 1/2-Stop comp"); break;
2647                             default: printred("undefined"); break;
2648                         }
2649                         print_endvalue();
2650                     }
2651                     break;
2652                 case 7:
2653                     if((PRINT_TAGINFO))
2654                         chpr += printf("1D.%02d_%-30.30s",cfn,"USMLensElectronicMF");
2655                     if((PRINT_VALUE))
2656                     {
2657                         chpr += printf(" = %u",cfv);
2658                         print_startvalue();
2659                         switch(cfv)
2660                         {
2661                             case 0: chpr += printf("Turns on after one-shot AF"); break;
2662                             case 1: chpr += printf("Turns off after one-shot AF"); break;
2663                             case 2: chpr += printf("Always off"); break;
2664                             default: printred("undefined"); break;
2665                         }
2666                         print_endvalue();
2667                     }
2668                     break;
2669                 case 8:
2670                     if((PRINT_TAGINFO))
2671                         chpr += printf("1D.%02d_%-30.30s",cfn,"LCDPanels");
2672                     if((PRINT_VALUE))
2673                     {
2674                         chpr += printf(" = %u",cfv);
2675                         print_startvalue();
2676                         switch(cfv)
2677                         {
2678                             case 0: chpr += printf("Remaining shots/File no"); break;
2679                             case 1: chpr += printf("ISO/Remaining shots"); break;
2680                             case 2: chpr += printf("ISO/File no"); break;
2681                             case 3: chpr += printf("Shots in folder/Remaining shots"); break;
2682                             default: printred("undefined"); break;
2683                         }
2684                         print_endvalue();
2685                     }
2686                     break;
2687                 case 9:
2688                     if((PRINT_TAGINFO))
2689                         chpr += printf("1D.%02d_%-30.30s",cfn,"AEBSequenceAutoCancellation");
2690                     if((PRINT_VALUE))
2691                     {
2692                         chpr += printf(" = %u",cfv);
2693                         print_startvalue();
2694                         switch(cfv)
2695                         {
2696                             case 0: chpr += printf("0,-,+/Enabled"); break;
2697                             case 1: chpr += printf("0,-,+/Disabled"); break;
2698                             case 2: chpr += printf("-,0,+/Enabled"); break;
2699                             case 3: chpr += printf("-,0,+/Disabled"); break;
2700                             default: printred("undefined"); break;
2701                         }
2702                         print_endvalue();
2703                     }
2704                     break;
2705                 case 10:
2706                     if((PRINT_TAGINFO))
2707                         chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointIllumination");
2708                     if((PRINT_VALUE))
2709                     {
2710                         chpr += printf(" = %u",cfv);
2711                         print_startvalue();
2712                         switch(cfv)
2713                         {
2714                             case 0: chpr += printf("On"); break;
2715                             case 1: chpr += printf("Off"); break;
2716                             case 2: chpr += printf("On without dimming"); break;
2717                             case 3: chpr += printf("Brighter"); break;
2718                             default: printred("undefined"); break;
2719                         }
2720                         print_endvalue();
2721                     }
2722                     break;
2723                 case 11:
2724                     if((PRINT_TAGINFO))
2725                         chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointSelection");
2726                     if((PRINT_VALUE))
2727                     {
2728                         chpr += printf(" = %u",cfv);
2729                         print_startvalue();
2730                         switch(cfv)
2731                         {
2732                             case 0: chpr += printf("H:AF+Main, V:AF+Command"); break;
2733                             case 1: chpr += printf("H:Comp+Main, V:AF+Comp+Command"); break;
2734                             case 2: chpr += printf("H:Command only, V:Assist+Main"); break;
2735                             case 3: chpr += printf("H:FEL_Main, V:FEL+Command"); break;
2736                             default: printred("undefined"); break;
2737                         }
2738                         print_endvalue();
2739                     }
2740                     break;
2741                 case 12:
2742                     if((PRINT_TAGINFO))
2743                         chpr += printf("1D.%02d_%-30.30s",cfn,"MirrorLockup");
2744                     if((PRINT_VALUE))
2745                     {
2746                         chpr += printf(" = %u",cfv);
2747                         print_startvalue();
2748                         switch(cfv)
2749                         {
2750                             case 0: chpr += printf("Disabled"); break;
2751                             case 1: chpr += printf("Enabled"); break;
2752                             default: printred("undefined"); break;
2753                         }
2754                         print_endvalue();
2755                     }
2756                     break;
2757                 case 13:
2758                     if((PRINT_TAGINFO))
2759                         chpr += printf("1D.%02d_%-30.30s",cfn,"AFPointSpotMetering");
2760                     if((PRINT_VALUE))
2761                     {
2762                         chpr += printf(" = %u",cfv);
2763                         print_startvalue();
2764                         switch(cfv)
2765                         {
2766                             case 0: chpr += printf("45/Center of Point"); break;
2767                             case 1: chpr += printf("11/Active AF point"); break;
2768                             case 2: chpr += printf("11/Center AF point"); break;
2769                             case 3: chpr += printf("9/Active af pOINT"); break;
2770                             default: printred("undefined"); break;
2771                         }
2772                         print_endvalue();
2773                     }
2774                     break;
2775                 case 14:
2776                     if((PRINT_TAGINFO))
2777                         chpr += printf("1D.%02d_%-30.30s",cfn,"FillFlashAutoReduction");
2778                     if((PRINT_VALUE))
2779                     {
2780                         chpr += printf(" = %u",cfv);
2781                         print_startvalue();
2782                         switch(cfv)
2783                         {
2784                             case 0: chpr += printf("Enabled"); break;
2785                             case 1: chpr += printf("Disabled"); break;
2786                             default: printred("undefined"); break;
2787                         }
2788                         print_endvalue();
2789                     }
2790                     break;
2791                 case 15:
2792                     if((PRINT_TAGINFO))
2793                         chpr += printf("1D.%02d_%-30.30s",cfn,"ShutterCurtainSync");
2794                     if((PRINT_VALUE))
2795                     {
2796                         chpr += printf(" = %u",cfv);
2797                         print_startvalue();
2798                         switch(cfv)
2799                         {
2800                             case 0: chpr += printf("1st-curtain sync"); break;
2801                             case 1: chpr += printf("2nd-curtain sync"); break;
2802                             default: printred("undefined"); break;
2803                         }
2804                         print_endvalue();
2805                     }
2806                     break;
2807                 case 16:
2808                     if((PRINT_TAGINFO))
2809                         chpr += printf("1D.%02d_%-30.30s",cfn,"SafetyShiftIn");
2810                     if((PRINT_VALUE))
2811                     {
2812                         chpr += printf(" = %u",cfv);
2813                         print_startvalue();
2814                         switch(cfv)
2815                         {
2816                             case 0: chpr += printf("Disable"); break;
2817                             case 1: chpr += printf("Enable"); break;
2818                             default: printred("undefined"); break;
2819                         }
2820                         print_endvalue();
2821                     }
2822                     break;
2823                 case 17:
2824                     if((PRINT_TAGINFO))
2825                         chpr += printf("1D.%02d_%-30.30s",cfn,"AF Point Activation Area");
2826                     if((PRINT_VALUE))
2827                     {
2828                         chpr += printf(" = %u",cfv);
2829                         print_startvalue();
2830                         switch(cfv)
2831                         {
2832                             case 0: chpr += printf("Single AF point"); break;
2833                             case 1: chpr += printf("Expanded (7 AF points)"); break;
2834                             case 2: chpr += printf("Auto expanded (max 13)"); break;
2835                             default: printred("undefined"); break;
2836                         }
2837                         print_endvalue();
2838                     }
2839                     break;
2840                 case 18:
2841                     if((PRINT_TAGINFO))
2842                         chpr += printf("1D.%02d_%-30.30s",cfn,"SwitchToRegisteredAFPoint");
2843                     if((PRINT_VALUE))
2844                     {
2845                         chpr += printf(" = %u",cfv);
2846                         print_startvalue();
2847                         switch(cfv)
2848                         {
2849                             case 0: chpr += printf("AF + assist"); break;
2850                             case 1: chpr += printf("Assist"); break;
2851                             case 2: chpr += printf("Only while pressing Assist"); break;
2852                             default: printred("undefined"); break;
2853                         }
2854                         print_endvalue();
2855                     }
2856                     break;
2857                 case 19:
2858                     if((PRINT_TAGINFO))
2859                         chpr += printf("1D.%02d_%-30.30s",cfn,"Lens AF Stop Button");
2860                     if((PRINT_VALUE))
2861                     {
2862                         chpr += printf(" = %u",cfv);
2863                         print_startvalue();
2864                         switch(cfv)
2865                         {
2866                             case 0: chpr += printf("AF Stop"); break;
2867                             case 1: chpr += printf("AF Start"); break;
2868                             case 2: chpr += printf("AE Lock whuile metering"); break;
2869                             case 3: chpr += printf("AF Point: M > Auto, Auto > Center"); break;
2870                             case 4: chpr += printf("AF Mode: oneshot/servo"); break;
2871                             case 5: chpr += printf("IS Start"); break;
2872                             default: printred("undefined"); break;
2873                         }
2874                         print_endvalue();
2875                     }
2876                     break;
2877                 case 20:
2878                     if((PRINT_TAGINFO))
2879                         chpr += printf("1D.%02d_%-30.30s",cfn,"AIServoTrackingSensitivity");
2880                     if((PRINT_VALUE))
2881                     {
2882                         chpr += printf(" = %u",cfv);
2883                         print_startvalue();
2884                         switch(cfv)
2885                         {
2886                             case 0: chpr += printf("Standard"); break;
2887                             case 1: chpr += printf("Slow"); break;
2888                             case 2: chpr += printf("Moderately slow"); break;
2889                             case 3: chpr += printf("Moderately fast"); break;
2890                             case 4: chpr += printf("Fast"); break;
2891                             default: printred("undefined"); break;
2892                         }
2893                         print_endvalue();
2894                     }
2895                     break;
2896                 default:
2897                     if((PRINT_TAGINFO))
2898                         chpr += printf("1D.%02d_%-30.30s",cfn,"undefined");
2899                     if((PRINT_VALUE))
2900                         chpr += printf(" = %#x/%u",cfv,cfv);
2901                     break;
2902             }
2903             chpr = newline(chpr);
2904         }
2905     }
2906     setcharsprinted(chpr);
2907     return(end_offset);
2908 }
2909 
2910 unsigned long
canon_sensorinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)2911 canon_sensorinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
2912                         unsigned long offset,unsigned long dirlength,int indent)
2913 {
2914     unsigned long count;
2915     unsigned long end_offset;
2916     unsigned short length,value;
2917     int i;
2918     int chpr = 0;
2919 
2920     end_offset = offset + dirlength;
2921     length = read_ushort(inptr,byteorder,offset);
2922     if(PRINT_SECTION)
2923     {
2924         chpr += printf(" length %lu",dirlength);
2925         if(length != dirlength)
2926         {
2927             chpr = newline(chpr);
2928             PUSHCOLOR(RED);
2929             print_tag_address(SECTION,offset,indent,"@");
2930             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
2931                         length,dirlength);
2932             POPCOLOR();
2933         }
2934     }
2935     chpr = newline(chpr);
2936 
2937     if((PRINT_ENTRY))
2938     {
2939         offset += 2;
2940         count = (dirlength / sizeof(unsigned short)) - 1;
2941 
2942         for(i = 1; i <= count; ++i)
2943         {
2944             value = read_ushort(inptr,byteorder,offset);
2945             print_tag_address(ENTRY,offset,indent,"@");
2946             if((PRINT_TAGINFO))
2947                 chpr += printf("%s",tagprefix);
2948             offset += 2;
2949             switch(i)
2950             {
2951                 case 1:
2952                     if((PRINT_TAGINFO))
2953                         chpr += printf(".%02d_%-26.26s",i,"SensorWidth");
2954                     if((PRINT_VALUE))
2955                         chpr += printf(" = %u",value);
2956                     break;
2957                 case 2:
2958                     if((PRINT_TAGINFO))
2959                         chpr += printf(".%02d_%-26.26s",i,"SensorHeight");
2960                     if((PRINT_VALUE))
2961                         chpr += printf(" = %u",value);
2962                     break;
2963                 case 3:
2964                     if((PRINT_TAGINFO))
2965                         chpr += printf(".%02d_%-26.26s",i,"Unknown");
2966                     if((PRINT_VALUE))
2967                         chpr += printf(" = %u",value);
2968                     break;
2969                 case 4:
2970                     if((PRINT_TAGINFO))
2971                         chpr += printf(".%02d_%-26.26s",i,"Unknown");
2972                     if((PRINT_VALUE))
2973                         chpr += printf(" = %u",value);
2974                     break;
2975                 case 5:
2976                     if((PRINT_TAGINFO))
2977                         chpr += printf(".%02d_%-26.26s",i,"SensorLeftBorder");
2978                     if((PRINT_VALUE))
2979                         chpr += printf(" = %u",value);
2980                     break;
2981                 case 6:
2982                     if((PRINT_TAGINFO))
2983                         chpr += printf(".%02d_%-26.26s",i,"SensorTopBorder");
2984                     if((PRINT_VALUE))
2985                         chpr += printf(" = %u",value);
2986                     break;
2987                 case 7:
2988                     if((PRINT_TAGINFO))
2989                         chpr += printf(".%02d_%-26.26s",i,"SensorRightBorder");
2990                     if((PRINT_VALUE))
2991                         chpr += printf(" = %u",value);
2992                     break;
2993                 case 8:
2994                     if((PRINT_TAGINFO))
2995                         chpr += printf(".%02d_%-26.26s",i,"SensorBottomBorder");
2996                     if((PRINT_VALUE))
2997                         chpr += printf(" = %u",value);
2998                     break;
2999                 default:
3000                     if((PRINT_TAGINFO))
3001                         chpr += printf(".%02d_%-26.26s",i,"Undefined");
3002                     if((PRINT_VALUE))
3003                         chpr += printf(" = %#x%u",value,value);
3004                     break;
3005             }
3006             chpr = newline(chpr);
3007         }
3008     }
3009     setcharsprinted(chpr);
3010     return(end_offset);
3011 }
3012 
3013 
3014 /* not a directory; an array of shorts used as rationals              */
3015 unsigned long
canon_whitebalancetable(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)3016 canon_whitebalancetable(FILE *inptr,unsigned short byteorder,char *tagprefix,
3017                             unsigned long offset,unsigned long dirlength,int indent)
3018 {
3019     unsigned long count;
3020     unsigned long end_offset;
3021     unsigned short length;
3022     unsigned short num,denom;
3023     float value;
3024     int i;
3025     int chpr = 0;
3026 
3027     end_offset = offset + dirlength;
3028     length = read_ushort(inptr,byteorder,offset);
3029     if(PRINT_SECTION)
3030     {
3031         chpr += printf(" length %lu",dirlength);
3032         if(length != dirlength)
3033         {
3034             chpr = newline(chpr);
3035             PUSHCOLOR(RED);
3036             print_tag_address(SECTION,offset,indent,"@");
3037             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
3038                         length,dirlength);
3039             POPCOLOR();
3040         }
3041         chpr = newline(chpr);
3042     }
3043 
3044     if((PRINT_ENTRY))
3045     {
3046         offset += 2;
3047         count = (dirlength - 2) / sizeof(float);
3048 
3049         for(i = 0; i < count; ++i)
3050         {
3051             num = read_ushort(inptr,byteorder,offset);
3052             denom = read_ushort(inptr,byteorder,offset+2);
3053             value = (float)num / (float)denom;
3054             print_tag_address(ENTRY,offset,indent,"@");
3055             if((PRINT_TAGINFO))
3056                 chpr += printf("%s",tagprefix);
3057             switch(i)
3058             {
3059                 case 0:
3060                     if((PRINT_TAGINFO))
3061                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceAuto");
3062                     if((PRINT_VALUE))
3063                         chpr += printf(" = %f",value);
3064                     break;
3065                 case 1:
3066                     if((PRINT_TAGINFO))
3067                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceAuto");
3068                     if((PRINT_VALUE))
3069                         chpr += printf(" = %f",value);
3070                     break;
3071                 case 2:
3072                     if((PRINT_TAGINFO))
3073                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceDaylight");
3074                     if((PRINT_VALUE))
3075                         chpr += printf(" = %f",value);
3076                     break;
3077                 case 3:
3078                     if((PRINT_TAGINFO))
3079                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceDaylight");
3080                     if((PRINT_VALUE))
3081                         chpr += printf(" = %f",value);
3082                     break;
3083                 case 4:
3084                     if((PRINT_TAGINFO))
3085                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceCloudy");
3086                     if((PRINT_VALUE))
3087                         chpr += printf(" = %f",value);
3088                     break;
3089                 case 5:
3090                     if((PRINT_TAGINFO))
3091                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceCloudy");
3092                     if((PRINT_VALUE))
3093                         chpr += printf(" = %f",value);
3094                     break;
3095                 case 6:
3096                     if((PRINT_TAGINFO))
3097                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceTungsten");
3098                     if((PRINT_VALUE))
3099                         chpr += printf(" = %f",value);
3100                     break;
3101                 case 7:
3102                     if((PRINT_TAGINFO))
3103                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceTungsten");
3104                     if((PRINT_VALUE))
3105                         chpr += printf(" = %f",value);
3106                     break;
3107                 case 8:
3108                     if((PRINT_TAGINFO))
3109                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceFluorescent");
3110                     if((PRINT_VALUE))
3111                         chpr += printf(" = %f",value);
3112                     break;
3113                 case 9:
3114                     if((PRINT_TAGINFO))
3115                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceFluorescent");
3116                     if((PRINT_VALUE))
3117                         chpr += printf(" = %f",value);
3118                     break;
3119                 case 10:
3120                     if((PRINT_TAGINFO))
3121                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceFlash");
3122                     if((PRINT_VALUE))
3123                         chpr += printf(" = %f",value);
3124                     break;
3125                 case 11:
3126                     if((PRINT_TAGINFO))
3127                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceFlash");
3128                     if((PRINT_VALUE))
3129                         chpr += printf(" = %f",value);
3130                     break;
3131                 case 12:
3132                     if((PRINT_TAGINFO))
3133                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceCustom");
3134                     if((PRINT_VALUE))
3135                         chpr += printf(" = %f",value);
3136                     break;
3137                 case 13:
3138                     if((PRINT_TAGINFO))
3139                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceCustom");
3140                     if((PRINT_VALUE))
3141                         chpr += printf(" = %f",value);
3142                     break;
3143                 case 14:
3144                     if((PRINT_TAGINFO))
3145                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceB&W");
3146                     if((PRINT_VALUE))
3147                         chpr += printf(" = %f",value);
3148                     break;
3149                 case 15:
3150                     if((PRINT_TAGINFO))
3151                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceB&W");
3152                     if((PRINT_VALUE))
3153                         chpr += printf(" = %f",value);
3154                     break;
3155                 case 16:
3156                     if((PRINT_TAGINFO))
3157                         chpr += printf(".%02d_%-22.22s",i,"RedBalanceShade");
3158                     if((PRINT_VALUE))
3159                         chpr += printf(" = %f",value);
3160                     break;
3161                 case 17:
3162                     if((PRINT_TAGINFO))
3163                         chpr += printf(".%02d_%-22.22s",i,"BlueBalanceShade");
3164                     if((PRINT_VALUE))
3165                         chpr += printf(" = %f",value);
3166                     break;
3167                 default:
3168                     if((PRINT_TAGINFO))
3169                         chpr += printf(".%02d_%-22.22s",i,"Undefined");
3170                     if((PRINT_VALUE))
3171                         chpr += printf(" = %f",value);
3172                     break;
3173             }
3174             offset += 4;
3175             chpr = newline(chpr);
3176         }
3177     }
3178     setcharsprinted(chpr);
3179     return(end_offset);
3180 }
3181 
3182 /* pictureinfo appears to be treated as a directory, except that the  */
3183 /* 'length' which should appear at the beginning of a ciff-style      */
3184 /* directory often does not agree with the length passed from the     */
3185 /* parent.                                                            */
3186 
3187 unsigned long
canon_pictureinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)3188 canon_pictureinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
3189                             unsigned long offset,unsigned long dirlength,int indent)
3190 {
3191     unsigned long count;
3192     unsigned long end_offset;
3193     unsigned short value,length;
3194     int i;
3195     int chpr = 0;
3196 
3197     end_offset = offset + dirlength;
3198     length = read_ushort(inptr,byteorder,offset);
3199     if(PRINT_SECTION)
3200     {
3201         chpr += printf(" length %lu",dirlength);
3202         if(length != dirlength)
3203         {
3204             chpr = newline(chpr);
3205             PUSHCOLOR(RED);
3206             print_tag_address(SECTION,offset,indent,"@");
3207             chpr += printf("# WARNING: length %u from segment does not match length %lu from directory",
3208                         length,dirlength);
3209             POPCOLOR();
3210         }
3211     }
3212     chpr = newline(chpr);
3213 
3214     if((PRINT_ENTRY))
3215     {
3216         offset += 2;
3217         count = (dirlength / sizeof(unsigned short)) - 1;
3218 
3219         for(i = 1; i <= count; ++i)
3220         {
3221             value = read_ushort(inptr,byteorder,offset);
3222             print_tag_address(ENTRY,offset,indent,"@");
3223             if((PRINT_TAGINFO))
3224                 chpr += printf("%s",tagprefix);
3225             offset += 2;
3226             switch(i)
3227             {
3228                 case 1:
3229                     if((PRINT_TAGINFO))
3230                         chpr += printf(".%02d_%-22.22s",i,"Unknown");
3231                     if((PRINT_VALUE))
3232                         chpr += printf(" = %u",value);
3233                     break;
3234                 case 2:
3235                     if((PRINT_TAGINFO))
3236                         chpr += printf(".%02d_%-22.22s",i,"ImageWidth");
3237                     if((PRINT_VALUE))
3238                         chpr += printf(" = %u",value);
3239                     break;
3240                 case 3:
3241                     if((PRINT_TAGINFO))
3242                         chpr += printf(".%02d_%-22.22s",i,"ImageHeight");
3243                     if((PRINT_VALUE))
3244                         chpr += printf(" = %u",value);
3245                     break;
3246                 case 4:
3247                     if((PRINT_TAGINFO))
3248                         chpr += printf(".%02d_%-22.22s",i,"ImageWidthAsShot");
3249                     if((PRINT_VALUE))
3250                         chpr += printf(" = %u",value);
3251                     break;
3252                 case 5:
3253                     if((PRINT_TAGINFO))
3254                         chpr += printf(".%02d_%-22.22s",i,"ImageHeightAsShot");
3255                     if((PRINT_VALUE))
3256                         chpr += printf(" = %u",value);
3257                     break;
3258                 case 22:
3259                     if((PRINT_TAGINFO))
3260                         chpr += printf(".%02d_%-22.22s",i,"AFPointsUsed");
3261                     if((PRINT_VALUE))
3262                         chpr += printf(" = %u",value);
3263                     break;
3264                 default:
3265                     if((PRINT_TAGINFO))
3266                         chpr += printf(".%02d_%-22.22s",i,"Undefined");
3267                     if((PRINT_VALUE))
3268                         chpr += printf(" = %#x%u",value,value);
3269                     break;
3270             }
3271             chpr = newline(chpr);
3272         }
3273     }
3274     setcharsprinted(chpr);
3275     return(end_offset);
3276 }
3277 
3278 /* Currently identified only in CIFF files                            */
3279 
3280 unsigned long
canon_imageinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent,struct image_summary * summary_entry)3281 canon_imageinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
3282                             unsigned long offset,unsigned long dirlength,int indent,
3283                             struct image_summary *summary_entry)
3284 {
3285     unsigned long count,value;
3286     unsigned long end_offset;
3287     float fvalue;
3288     int i;
3289     int chpr = 0;
3290 
3291     if(PRINT_SECTION)
3292     {
3293         chpr += printf(" length %lu",dirlength);
3294         chpr = newline(chpr);
3295     }
3296 
3297     /* NOTE that imageinfo is not treated as a directory; there is no */
3298     /* 2-byte count at the beginning.                                 */
3299 
3300     end_offset = offset + dirlength;
3301     count = (dirlength / sizeof(unsigned long));
3302 
3303     /* Must always do the processing, in order to pick up the image   */
3304     /* width and height for the summary, even if nothing is to be     */
3305     /* printed                                                        */
3306     for(i = 0; i < count; ++i)
3307     {
3308         value = read_ulong(inptr,byteorder,offset);
3309         print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"@");
3310         if((PRINT_ENTRY))
3311         {
3312             if((PRINT_TAGINFO))
3313                 chpr += printf("%s",tagprefix);
3314         }
3315         offset += 4;
3316         switch(i)
3317         {
3318             case 0:
3319                 if((PRINT_TAGINFO))
3320                      chpr += printf(".%02d_%-22.22s",i,"ImageWidth");
3321                 if((PRINT_VALUE))
3322                     chpr += printf(" = %lu",value);
3323                 if(summary_entry)
3324                     summary_entry->pixel_width = value;
3325                 break;
3326             case 1:
3327                 if((PRINT_TAGINFO))
3328                      chpr += printf(".%02d_%-22.22s",i,"ImageHeight");
3329                 if((PRINT_VALUE))
3330                     chpr += printf(" = %lu",value);
3331                 if(summary_entry)
3332                     summary_entry->pixel_height = value;
3333                 break;
3334             case 2:
3335                 fvalue = to_float(value);
3336                 if((PRINT_TAGINFO))
3337                      chpr += printf(".%02d_%-22.22s",i,"PixelAspectRatio");
3338                 if((PRINT_VALUE))
3339                     chpr += printf(" = %lu",value);
3340                 break;
3341             case 3:
3342                 if((PRINT_TAGINFO))
3343                      chpr += printf(".%02d_%-22.22s",i,"Rotation");
3344                 if((PRINT_VALUE))
3345                     chpr += printf(" = %lu",value);
3346                 break;
3347             case 4:
3348                 if((PRINT_TAGINFO))
3349                      chpr += printf(".%02d_%-22.22s",i,"ComponentBitDepth");
3350                 if((PRINT_VALUE))
3351                     chpr += printf(" = %lu",value);
3352                 break;
3353             case 5:
3354                 if((PRINT_TAGINFO))
3355                      chpr += printf(".%02d_%-22.22s",i,"ColorBitDepth");
3356                 if((PRINT_VALUE))
3357                     chpr += printf(" = %lu",value);
3358                 break;
3359             case 6:
3360                 if((PRINT_TAGINFO))
3361                      chpr += printf(".%02d_%-22.22s",i,"ColorBW");
3362                 if((PRINT_VALUE))
3363                 {
3364                     chpr += printf(" = %#lx/%lu",value,value);
3365                     if((value & 0xff) == 1)
3366                          chpr += printf(" = color");
3367                     else
3368                          chpr += printf(" = greyscale");
3369                     if(((value & 0xff00) >> 8) == 1)
3370                          chpr += printf(" = \'pixel ratio postproc reqd\'");
3371                 }
3372                 break;
3373             default:
3374                 if((PRINT_TAGINFO))
3375                      chpr += printf(".%02d_%-22.22s",i,"Undefined");
3376                 if((PRINT_VALUE))
3377                     chpr += printf(" = %#lx/%lu",value,value);
3378                 break;
3379         }
3380         chpr = newline(chpr);
3381     }
3382     setcharsprinted(chpr);
3383     return(end_offset);
3384 }
3385 
3386 /* Currently identified only in CIFF files                            */
3387 
3388 unsigned long
canon_exposureinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent,struct image_summary * summary_entry)3389 canon_exposureinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
3390                             unsigned long offset,unsigned long dirlength,int indent,
3391                             struct image_summary *summary_entry)
3392 {
3393     unsigned long count,value;
3394     unsigned long end_offset;
3395     float fvalue;
3396     int i;
3397     int chpr = 0;
3398 
3399     if(PRINT_SECTION)
3400     {
3401         chpr += printf(" length %lu",dirlength);
3402         chpr = newline(chpr);
3403     }
3404 
3405     /* NOTE that exposureinfo is not treated as a directory; there is */
3406     /* no 2-byte count at the beginning.                              */
3407 
3408     end_offset = offset + dirlength;
3409     count = (dirlength / sizeof(unsigned long));
3410 
3411     for(i = 0; i < count; ++i)
3412     {
3413         value = read_ulong(inptr,byteorder,offset);
3414         print_tag_address(ENTRY,offset,indent,"@");
3415         if((PRINT_ENTRY))
3416         {
3417             if((PRINT_TAGINFO))
3418                 chpr += printf("%s",tagprefix);
3419         }
3420         offset += 4;
3421         switch(i)
3422         {
3423             case 0:
3424                 fvalue = to_float(value);
3425                 if((PRINT_TAGINFO))
3426                     chpr += printf(".%02d_%-22.22s",i,"ExposureCompensation");
3427                 if((PRINT_VALUE))
3428                     chpr += printf(" = %f",fvalue);
3429                 break;
3430             case 1:
3431                 fvalue = to_float(value);
3432                 if((PRINT_TAGINFO))
3433                     chpr += printf(".%02d_%-22.22s",i,"Tv");
3434                 if((PRINT_VALUE))
3435                     chpr += printf(" = %f",fvalue);
3436                 break;
3437             case 2:
3438                 fvalue = to_float(value);
3439                 if((PRINT_TAGINFO))
3440                     chpr += printf(".%02d_%-22.22s",i,"Av");
3441                 if((PRINT_VALUE))
3442                     chpr += printf(" = %f",fvalue);
3443                 break;
3444             default:
3445                 fvalue = to_float(value);
3446                 if((PRINT_TAGINFO))
3447                     chpr += printf(".%02d_%-22.22s",i,"Undefined");
3448                 if((PRINT_VALUE))
3449                     chpr += printf(" = %f",fvalue);
3450                 break;
3451         }
3452         chpr = newline(chpr);
3453     }
3454     setcharsprinted(chpr);
3455     return(end_offset);
3456 }
3457 
3458 
3459 unsigned long
canon_focusinfo(FILE * inptr,unsigned short byteorder,char * tagprefix,unsigned long offset,unsigned long dirlength,int indent)3460 canon_focusinfo(FILE *inptr,unsigned short byteorder,char *tagprefix,
3461                             unsigned long offset,unsigned long dirlength,int indent)
3462 {
3463     unsigned long count;
3464     unsigned long end_offset;
3465     unsigned short value;
3466     int i;
3467     int chpr = 0;
3468 
3469     if(PRINT_SECTION)
3470         chpr += printf(" length %lu",dirlength);
3471     chpr = newline(chpr);
3472 
3473     /* NOTE that focallength is not treated as a directory; there is  */
3474     /* no 2-byte count at the beginning.                              */
3475 
3476     end_offset = offset + dirlength;
3477     count = (dirlength / sizeof(unsigned short));
3478 
3479     for(i = 0; i < count; ++i)
3480     {
3481         value = read_ushort(inptr,byteorder,offset);
3482         print_tag_address(ENTRY,offset,indent,"@");
3483         if((PRINT_ENTRY))
3484         {
3485             if((PRINT_TAGINFO))
3486                 chpr += printf("%s",tagprefix);
3487         }
3488         offset += 2;
3489         switch(i)
3490         {
3491             case 0:
3492                 if((PRINT_TAGINFO))
3493                     chpr += printf(".%02d_%-22.22s",i,"unknown");
3494                 if((PRINT_VALUE))
3495                     chpr += printf(" = %u",value);
3496                 break;
3497             case 1:
3498                 if((PRINT_TAGINFO))
3499                     chpr += printf(".%02d_%-22.22s",i,"FocalLength");
3500                 if((PRINT_VALUE))
3501                     chpr += printf(" = %u",value);
3502                 break;
3503             case 2:
3504                 if((PRINT_TAGINFO))
3505                     chpr += printf(".%02d_%-22.22s",i,"FocalPlaneXSize");
3506                 if((PRINT_VALUE))
3507                     chpr += printf(" = %u",value);
3508                 break;
3509             case 3:
3510                 if((PRINT_TAGINFO))
3511                     chpr += printf(".%02d_%-22.22s",i,"FocalPlaneYSize");
3512                 if((PRINT_VALUE))
3513                     chpr += printf(" = %u",value);
3514                 break;
3515             default:
3516                 if((PRINT_TAGINFO))
3517                     chpr += printf(".%02d_%-22.22s",i,"Undefined");
3518                 if((PRINT_VALUE))
3519                     chpr += printf(" = %#x%u",value,value);
3520                 break;
3521         }
3522         chpr = newline(chpr);
3523     }
3524     setcharsprinted(chpr);
3525     return(end_offset);
3526 }
3527 
3528 /* Some makernotes record offsets as LONG values rather than simply   */
3529 /* using UNDEFINED with a size; the same technique used for           */
3530 /* the ExifIFDPointer itself, or JpegInterchangeFormat, etc.          */
3531 /* This routine hardcodes such tags so that the print_makerentry()    */
3532 /* routine will present them as offsets.                              */
3533 
3534 int
maker_canon_value_is_offset(struct ifd_entry * entry_ptr,int model)3535 maker_canon_value_is_offset(struct ifd_entry *entry_ptr,int model)
3536 {
3537     int is_offset = 0;
3538     int noteversion = 0;
3539 
3540     if(entry_ptr)
3541     {
3542         noteversion = getnoteversion();
3543         switch(noteversion)
3544         {
3545             default:
3546                 switch(entry_ptr->tag)
3547                 {
3548                     case 0x0081: is_offset = 1; break;
3549                     default: break;
3550                 }
3551                 break;
3552         }
3553     }
3554     return(is_offset);
3555 }
3556 
3557 /*
3558 <0xc5d9=50649> = 2 compression=6 CR2 RGB (Ifd 2)
3559 
3560 <0xc5d8=50648> = 0 compression=6  primary? (biggest)        CR2 Ifd 3
3561 <0xc5e0=50656> = 1                                          CR2 Ifd 3
3562 <0xc640-50752> = offset to 3 shorts (EOS 350D)              CR2 Ifd 3
3563 <0xc640-50752> = offset to 3 shorts (EOS-1Ds Mark II)       CR2 Ifd 3  2,1680,1748 (e0=3)
3564 */
3565