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_minolta.c,v 1.28 2005/07/24 21:57:28 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* minolta camera maker-specific routines                             */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* Most of the information used here is due to Dalibor Jelinek at:    */
17 /*     http://www.dalibor.cz/minolta/makernote.htm                    */
18 /*                                                                    */
19 /* The F100 and "X" models *appear* to use the same MakerNote tagset  */
20 /* as used for Sanyo models, as decoded by John Hawkins               */
21 /*     http://www.exif.org/makernotes/SanyoMakerNote.html             */
22 /*                                                                    */
23 /* NOTE that this is guesswork. Test images I have found for these    */
24 /* models appear to decode properly using the tag numbers from        */
25 /* Hawkinn's Sanyo data.  Send mail if you can confirm or deny.       */
26 /*                                                                    */
27 /* The EX model MakerNote format is indecipherable.                   */
28 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include "defs.h"
34 #include "datadefs.h"
35 #include "maker_datadefs.h"
36 #include "summary.h"
37 #include "maker.h"
38 #include "misc.h"
39 #include "tags.h"
40 #include "maker_extern.h"
41 #include "extern.h"
42 
43 extern struct camera_id minolta_model_id[];
44 
45 /* Find the identifying number assigned to known Minolta camera       */
46 /* models, and record the noteversion and tagset assigned to that     */
47 /* model. The noteversion is used to dispatch print and interpret     */
48 /* routines approopriate to the current image.                        */
49 
50 int
minolta_model_number(char * model,char * software)51 minolta_model_number(char *model,char *software)
52 {
53     struct camera_id *model_id;
54     int number = NO_MODEL;
55 
56     for(model_id = &minolta_model_id[0]; model_id && model_id->name; ++model_id)
57     {
58         if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
59         {
60             number = model_id->id;
61             setnoteversion(model_id->noteversion);
62             setnotetagset(model_id->notetagset);    /* info only      */
63             break;
64         }
65     }
66     return(number);
67 }
68 
69 
70 /* Dispatch a print routine based upon the noteversion which has been */
71 /* assigned.                                                          */
72 
73 void
print_minolta_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)74 print_minolta_makervalue(struct ifd_entry *entry_ptr,int make, int model,
75                                                             char *prefix)
76 {
77     int noteversion = 0;
78 
79     noteversion = getnoteversion();
80 
81     if(entry_ptr && (PRINT_VALUE))
82     {
83         switch(noteversion)
84         {
85             case 1:
86                 print_minolta1_makervalue(entry_ptr,make,model,prefix);
87                 minolta1_interpret_value(entry_ptr,model);
88                 break;
89             default:
90                 print_value(entry_ptr,PREFIX);
91                 break;
92         }
93     }
94 }
95 
96 /* Maker-specific print routine for minolta cameras. This routine is  */
97 /* responsible for picking off any direct entry tags which are        */
98 /* peculiar and might 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_minolta1_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)104 print_minolta1_makervalue(struct ifd_entry *entry_ptr,int make, int model,
105                                                             char *prefix)
106 {
107     int chpr = 0;
108     if(entry_ptr && (PRINT_VALUE))
109     {
110         switch(entry_ptr->tag)
111         {
112                 case 0x0040:    /* ImageByteSize                      */
113                     chpr += printf("%lu ",entry_ptr->value);
114                     if(entry_ptr->count > 1)
115                     {
116                         printred("# BAD COUNT");
117                         setcharsprinted(chpr);
118                     }
119                     break;
120                 default:
121                     print_value(entry_ptr,PREFIX);
122                 break;
123         }
124     }
125 }
126 
127 /* Dispatch a routine to decode and print offset values for minolta   */
128 /* cameras.                                                           */
129 
130 void
print_minolta_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)131 print_minolta_offset_makervalue(FILE *inptr,unsigned short byteorder,
132     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
133     struct image_summary *summary_entry,char *parent_name,char*prefix,
134     int indent,int make,int model,int at_offset)
135 {
136     int noteversion = 0;
137 
138 
139     if(entry_ptr)
140     {
141         noteversion = getnoteversion();
142         switch(noteversion)
143         {
144             case 1:
145                 minolta1_offset_makervalue(inptr,byteorder,entry_ptr,
146                                             fileoffset_base,summary_entry,
147                                             parent_name,prefix,indent,
148                                             make,model,at_offset);
149                 minolta1_interpret_offset_makervalue(inptr,byteorder,entry_ptr,
150                                             fileoffset_base);
151                 break;
152             default:
153                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
154                                         fileoffset_base,parent_name,prefix,indent,
155                                         make,model,at_offset);
156                 break;
157         }
158     }
159 }
160 
161 /* Maker-specific routine to print UNDEFINED values found at offsets  */
162 /* in minolta makernotes. One of these may be supplied for each model */
163 /* with unique UNDEFINED tags.                                        */
164 
165 void
minolta1_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)166 minolta1_offset_makervalue(FILE *inptr,unsigned short byteorder,
167     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
168     struct image_summary *summary_entry,char *parent_name,char*prefix,
169     int indent,int make,int model,int at_offset)
170 {
171     static unsigned long jpegthumbnailoffset = 0UL;
172     unsigned long value_offset;
173     unsigned long dumplength;
174     unsigned long count;
175     unsigned long max_offset = 0;
176     unsigned short marker;
177     char *nameoftag,*tagprefix;
178     char *fulldirname = NULL;
179     int status = 0;
180     int chpr = 0;
181 
182     if(entry_ptr)
183     {
184         nameoftag = maker_tagname(entry_ptr->tag,make,model);
185         fulldirname = splice(parent_name,".",nameoftag);
186         value_offset = fileoffset_base + entry_ptr->value;
187         count = entry_ptr->count;
188         switch(entry_ptr->tag)
189         {
190             case 0x0001:    /* Camera Settings, old                   */
191             case 0x0003:    /* Camera Settings, new                   */
192                 if(at_offset)
193                 {
194                     if((PRINT_SECTION))
195                     {
196                         print_tag_address(SECTION,value_offset,indent,prefix);
197                         chpr += printf("<%s> ",nameoftag);
198                         chpr += printf("%lu entries",count / 4);
199                     }
200                 }
201                 else if(!at_offset && (PRINT_VALUE))
202                 {
203                     if(!(PRINT_OFFSET))
204                         chpr += printf("@%lu",value_offset);
205                 }
206                 if((PRINT_LONGNAMES))
207                     tagprefix = fulldirname;
208                 else
209                     tagprefix = nameoftag;
210                 max_offset = minolta_camerasetting(inptr,byteorder,model,tagprefix,
211                                     entry_ptr,value_offset,indent + MEDIUMINDENT);
212                 if(PRINT_SECTION)
213                 {
214                     chpr = newline(0);
215                     print_tag_address(SECTION,max_offset - 1,indent,prefix);
216                     chpr += printf("</%s> ",nameoftag);
217                 }
218                 setcharsprinted(chpr);
219                 break;
220             case 0x0040:    /* ImageByteSize                      */
221                 break;      /* should have a count of 1               */
222             case 0x0088:    /* JpegThumbnailOffset                    */
223                 /* It's not magic, there's a trick to it. The offset  */
224                 /* length will normally be the next entry tag in the  */
225                 /* IFD, and this will work iff it is. Remember the    */
226                 /* offset and handle it when the length tag is seen.  */
227                 /* This is necessary because we do not save entries.  */
228                 jpegthumbnailoffset = value_offset;
229                 if(!at_offset && (PRINT_VALUE))
230                 {
231                     if(!(PRINT_OFFSET))
232                         chpr += printf("@%lu",jpegthumbnailoffset);
233                 }
234                 break;
235             case 0x0089:    /* JpegThumbnailLength                    */
236                 if(jpegthumbnailoffset == 0UL)
237                 {
238                     printred("# WARNING: JpegThumbnailLength encountered with 0 offset");
239                     break;  /* must have the offset.                  */
240                 }
241                 value_offset = jpegthumbnailoffset;
242                 count = entry_ptr->value;
243                 jpegthumbnailoffset = 0L;
244                 /* fall through                                       */
245             case 0x0081:    /* Jpeg Thumbnail                         */
246                 /* Minolta seems to use EITHER 0x0088/0x0089 OR       */
247                 /* 0x0081, not both.                                  */
248                 if(at_offset && (PRINT_SECTION))
249                 {
250                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,
251                                                         prefix);
252                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
253                     chpr += printf(" length %lu",count);
254                 }
255                 else if(!at_offset && (PRINT_VALUE) && (entry_ptr->tag == 0x0081))
256                 {
257                     if(!(PRINT_OFFSET))
258                         chpr += printf("@%lu:%lu",value_offset,count);
259                     else
260                         chpr = printf(":%lu",count);
261                     if(!(PRINT_VALUE_AT_OFFSET))
262                         chpr += printf(" # UNDEFINED");
263                 }
264                 if((PRINT_SECTION) || (PRINT_SEGMENT))
265                     chpr = newline(chpr);
266                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
267                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
268                                             count,summary_entry,fulldirname,
269                                             prefix,indent+SMALLINDENT);
270                 if(at_offset)
271                 {
272                     if((PRINT_SECTION))
273                     {
274                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
275                             chpr = newline(chpr);
276                         jpeg_status(status);
277                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
278                                                             indent,"-");
279                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
280                         if((PRINT_ENTRY) && !(PRINT_VALUE))
281                             chpr = newline(chpr);
282                     }
283                 }
284                 print_jpeg_status();
285                 if(marker && summary_entry)
286                 {
287                     /* The new one is on the end of the chain         */
288                     if((summary_entry = last_summary_entry(summary_entry)))
289                     {
290                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
291                         summary_entry->datatype = MAKER_IFD;
292                         summary_entry->subfiletype = THUMBNAIL_TYPE;
293                     }
294                 }
295                 /* make certain we're at the end                      */
296                 clearerr(inptr);
297                 fseek(inptr,value_offset + count,0);
298                 break;
299             case 0x0e00: /* PrintIM                                   */
300                 if(!at_offset && (PRINT_VALUE))
301                 {
302                     if(!(PRINT_OFFSET))
303                     {
304                         chpr += printf("@%lu:%lu",value_offset,count);
305                         chpr = newline(chpr);
306                     }
307                 }
308                 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
309                     count,nameoftag,parent_name,prefix,indent);
310                 break;
311             case 0x0f00: /* Data                                      */
312                 if(at_offset && (PRINT_ENTRY))
313                 {
314                     print_tag_address(ENTRY,value_offset,indent,prefix);
315                     print_makertagid(entry_ptr,23," : ",make,model);
316                     chpr += printf(" length %-9lu", count);
317                     if(Max_undefined == 0)
318                     {
319                         if(chpr)
320                             printred(" (not dumped, use -U)");
321                     }
322                     else
323                     {
324                         if((Max_undefined == DUMPALL) || (Max_undefined > count))
325                             dumplength = count;
326                         else
327                             dumplength = Max_undefined;
328                         chpr = newline(chpr);
329                         hexdump(inptr,value_offset,count,dumplength,12,
330                                     indent,SUBINDENT);
331                         chpr = newline(1);
332                     }
333                 }
334                 else if(!at_offset && (PRINT_VALUE))
335                 {
336                     if(!(PRINT_OFFSET))
337                         chpr += printf("@%lu:%lu",value_offset,count);
338                     else
339                         chpr += printf(":%lu", count);
340                     if(!(PRINT_VALUE_AT_OFFSET))
341                         chpr += printf(" # UNDEFINED");
342                 }
343                 /* make certain we're at the end                      */
344                 fseek(inptr,value_offset + count,0);
345                 break;
346             default:
347                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
348                                         fileoffset_base,fulldirname,prefix,indent,
349                                         make,model,at_offset);
350                 break;
351         }
352         if(fulldirname)
353             free(fulldirname);
354     }
355     setcharsprinted(chpr);
356 }
357 
358 /* Minolta-specific tagnames for makernotes.                          */
359 /* Minolta models sport at least 9 different MakerNote tagsets that I */
360 /* have seen. However, the various tagsets do not overlap (if a given */
361 /* tag number is used in more than 1 model, it is assigned the same   */
362 /* meaning everywhere). This makes it possible to use a single        */
363 /* routine for tagnames, values, interpretations, etc.                */
364 
365 char *
maker_minolta_tagname(unsigned short tag,int model)366 maker_minolta_tagname(unsigned short tag,int model)
367 {
368     char *tagname = (char *)0;
369     int noteversion = 0;
370 
371     /* Should have to do this only once, and only for unrecognized    */
372     /* models. If the model is recognized (or the user has forced a   */
373     /* noteversion) noteversion will already be set.                  */
374     if((noteversion = getnoteversion()) == 0)
375     {
376         noteversion = 1;
377         setnoteversion(1);
378     }
379 
380     switch(noteversion)
381     {
382         case 1:
383             tagname = maker_minolta1_tagname(tag,model);
384             break;
385         default:
386             break;
387     }
388 
389     /* If no model-specific tag is found, check "generic" tags        */
390     if(tagname == NULL)
391     {
392         switch(tag)
393         {
394             case 0x0e00: tagname = "PrintIM"; break;
395             default: break;
396         }
397     }
398     return(tagname);
399 }
400 
401 /* Although several versions of Minolta MakerNotes have been seen in  */
402 /* the wild, there appears to be no duplication of tag numbers (i.e.  */
403 /* no tag number is used for different purposes in one note version   */
404 /* than in another vesion. This makes it possible to treat the notes  */
405 /* as a single version.                                               */
406 
407 /* For now...                                                         */
408 
409 char *
maker_minolta1_tagname(unsigned short tag,int model)410 maker_minolta1_tagname(unsigned short tag,int model)
411 {
412     char *tagname = CNULL;
413 
414     /* The Minolta MakerNote of TIFF format images have a JPEG        */
415     /* thumbnail with a defective SOI marker (0x00f8). In fact,       */
416     /* Minolta JPEG_SOI is often missing the high "0xff".             */
417 
418     if(tagname == NULL)
419     {
420         switch(tag)
421         {
422             case 0x0000: tagname = "Version"; break;
423             case 0x0001: tagname = "CameraSettings"; break;
424             case 0x0003: tagname = "CameraSettings"; break;
425             case 0x0040: tagname = "ImageByteSize"; break;
426             case 0x0081: tagname = "JpegThumbnail"; break;
427             case 0x0088: tagname = "JpegThumbnailOffset"; break;
428             case 0x0089: tagname = "JpegThumbnailLength"; break;
429             case 0x0101: tagname = "ColorMode"; break;
430             case 0x0102: tagname = "ImageQuality"; break;
431             case 0x0103: if(model == MINOLTA_DIMAGE7Hi)
432                               tagname = "ImageQuality";
433                          else
434                               tagname = "ImageSize";
435                          break;
436             /* The following tagname appears valid for at least the   */
437             /* F200, thanks to Harald Puhl (h.puhl@ki-ag.com)         */
438             case 0x0104: tagname = "FlashCompensation"; break;
439             case 0x0200: tagname = "SpecialMode"; break;
440 
441     /* The following tag names appear valid for the F100 and "X" but  */
442     /* do not appear to be used for any other Minolta model. They are */
443     /* essentially the Sanyo tag set, used here based upon guesswork; */
444     /* some Minolta and Sanyo cameras are said to use the same chip,  */
445     /* and some F100 and "X" images I've seen contain almost exactly  */
446     /* this set of tags (as described by John Hawkins for Sanyo       */
447     /* DSC-MZ2 notes). The Quality, Macro, SpecialMode and PrintIM    */
448     /* tags are reasonably certain to be correct (they "decode"       */
449     /* properly). The remaining names are less certain, and no        */
450     /* attempt is made to decode them in minolta1_interpret_value()/  */
451 
452             case 0x0201: tagname = "Quality"; break;
453             case 0x0202: tagname = "Macro"; break;
454             case 0x0204: tagname = "DigiZoom"; break;
455             case 0x0207: tagname = "SoftwareRelease"; break;
456             case 0x0208: tagname = "PictInfo"; break;
457             case 0x0209: tagname = "CameraID"; break;
458             case 0x020e: tagname = "SeqShotMethod"; break;
459             case 0x020f: tagname = "WideRange"; break;
460             case 0x0210: tagname = "ColorAdjMode"; break;
461             case 0x0213: tagname = "QuickShot"; break;
462             case 0x0214: tagname = "SelfTimer"; break;
463             case 0x0216: tagname = "VoiceMemo"; break;
464             case 0x0217: tagname = "RecordShutterRel"; break;
465             case 0x0218: tagname = "FlickerReduce"; break;
466             case 0x0219: tagname = "OpticalZoom"; break;
467             case 0x021b: tagname = "DigitalZoom"; break;
468             case 0x021d: tagname = "LightSourceSpecial"; break;
469             case 0x021e: tagname = "Resaved"; break;
470             case 0x021f: tagname = "SceneSelect"; break;
471             case 0x0223: tagname = "ManualFocusDist"; break; /* ###%%% not seen */
472             case 0x0224: tagname = "SeqShotIntvl"; break; /* ###%%% not seen */
473             case 0x0225: tagname = "FlashMode"; break; /* ###%%% not seen */
474             case 0x0e00: tagname = "PrintIM"; break;
475             case 0x0f00: tagname = "Data"; break;
476             default: break;
477         }
478     }
479     setnotetagset(1);
480     return(tagname);
481 }
482 
483 
484 void
minolta1_interpret_value(struct ifd_entry * entry_ptr,int model)485 minolta1_interpret_value(struct ifd_entry *entry_ptr,int model)
486 {
487     int chpr = 0;
488 
489     if(entry_ptr && (PRINT_VALUE))
490     {
491         switch(entry_ptr->tag)
492         {
493             case 0x0101:    /* ColorMode                                  */
494                 print_startvalue();
495                 switch(entry_ptr->value)
496                 {
497                     case 0: chpr += printf("Natural"); break;
498                     case 1: chpr += printf("Black/White*"); break;
499                     case 2: chpr += printf("Vivid"); break;
500                     case 3: chpr += printf("Solarize"); break;
501                     case 4: chpr += printf("Adobe RGB"); break;
502                     case 9: chpr += printf("unknown"); break;
503                     case 132: chpr += printf("Adobe RGB Embedded Profile"); break;
504                     default: printred("undefined"); break;
505                 }
506                 print_endvalue();
507                 break;
508             case 0x0102:    /* CameraSettings ImageQuality, 7, 7Hi, F300  */
509 minolta_7Hi_botch:
510                 print_startvalue();
511                 switch(entry_ptr->value)
512                 {
513                     /* ###%%% jpeg quality/compression? check this        */
514                     case 0: chpr += printf("Raw"); break;
515                     case 1: chpr += printf("Uncompressed"); break; /* superfine, raw? tiff? */
516                     case 2: chpr += printf("Fine(1/2)"); break;
517                     case 3: chpr += printf("Normal(1/3)"); break;   /* ###%%% */
518                     case 4: chpr += printf("Economy(1/4)"); break;  /* ###%%% */
519                     case 5: chpr += printf("ExtraFine(1/1)"); break;
520                     default: printred("undefined"); break;
521                 }
522                 print_endvalue();
523                 break;
524             case 0x0103:    /* CameraSettings ImageSize*, 7Hi, F300       */
525                 /* The 7Hi appears to get this wrong, printing the same   */
526                 /* value for this as for 0x0102; the F300 seems to do it  */
527                 /* right. The ImageSize entry in "Camera Settings"        */
528                 /* appears correct in both cases. For the 7Hi, it would   */
529                 /* be wrong to report this as image size, so just don't   */
530                 /* do it.                                                 */
531                 if(model == MINOLTA_DIMAGE7Hi)
532                     goto minolta_7Hi_botch;
533 
534                 print_startvalue();
535                 switch(entry_ptr->value)
536                 {
537                     case 1: chpr += printf("1600x1200"); break;
538                     case 2: chpr += printf("unknown"); break;   /* 1280x960? */
539                     case 3: chpr += printf("640x480"); break;
540                     case 4: chpr += printf("unknown"); break;
541                     case 5: chpr += printf("2560x1920"); break;
542                     case 6: chpr += printf("2272x1704"); break;
543                     case 7: chpr += printf("2048x1536"); break;
544                     case 13: chpr += printf("3264x2448"); break;
545                     default: printred("undefined"); break;
546                 }
547                 print_endvalue();
548                 break;
549             case 0x0201:    /* Quality, X, F100                           */
550                 print_startvalue();
551                     /* ###%%% jpeg quality/compression? check this, same as 0x0102?       */
552                 switch(entry_ptr->value)
553                 {
554                     case 0: chpr += printf("Raw*"); break;
555                     case 1: chpr += printf("Economy(1/8)"); break;
556                     case 2: chpr += printf("Normal(1/4)"); break;
557                     case 3: chpr += printf("Fine(1/2)"); break;
558                     case 4: chpr += printf("Uncompressed"); break;
559                     default: printred("undefined"); break;
560                 }
561                 print_endvalue();
562                 break;
563             case 0x0202:    /* Macro */
564                 print_startvalue();
565                 switch(entry_ptr->value)
566                 {
567                     case 0: chpr += printf("Normal"); break;
568                     case 1: chpr += printf("Macro"); break;
569                     case 2: chpr += printf("View"); break;
570                     default: printred("undefined"); break;
571                 }
572                 print_endvalue();
573                 break;
574             default:
575                 break;
576         }
577     }
578     setcharsprinted(chpr);
579 }
580 
581 void
minolta1_interpret_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base)582 minolta1_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder,
583                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base)
584 {
585     unsigned long offset,value;
586     int chpr = 0;
587 
588     if(entry_ptr && (PRINT_VALUE))
589     {
590         offset = entry_ptr->value + fileoffset_base;
591         switch(entry_ptr->tag)
592         {
593             case 0x0200:    /* SpecialMode                               */
594                 value = read_ulong(inptr,byteorder,offset);
595                 print_startvalue();
596                 switch(value)
597                 {
598                     case 0: chpr += printf("Normal"); break;
599                     case 1: chpr += printf("Unkown"); break;
600                     case 2: chpr += printf("Fast"); break;
601                     case 3: chpr += printf("Panorama,");
602                             value = read_ulong(inptr,byteorder,HERE);
603                             chpr += printf("#%lu,",value);
604                             value = read_ulong(inptr,byteorder,HERE);
605                             switch(value)
606                             {
607                                 case 1: chpr += printf(" Left to Right"); break;
608                                 case 2: chpr += printf(" Right to Left"); break;
609                                 case 3: chpr += printf(" Bottom to Top"); break;
610                                 case 4: chpr += printf(" Top to Bottom"); break;
611                                 default: printred(" undefined"); break;
612                             }
613                             break;
614                     default: printred("undefined"); break;
615                 }
616                 print_endvalue();
617                 break;
618             default:
619                 break;
620         }
621     }
622     setcharsprinted(chpr);
623 }
624 
625 /* Interpret the "Camera Settings" tag data from Minolta MakerNotes.  */
626 
627 #include <math.h>
628 
629 unsigned long
minolta_camerasetting(FILE * inptr,unsigned short byteorder,int model,char * tagprefix,struct ifd_entry * entry_ptr,unsigned long offset,int indent)630 minolta_camerasetting(FILE *inptr,unsigned short byteorder,int model,
631     char *tagprefix,struct ifd_entry *entry_ptr,unsigned long offset,int indent)
632 {
633     unsigned long value,end_offset;
634     double fvalue;
635     int i,corr_i,entries;
636     signed char wcorr;
637     int chpr = 0;
638 
639     end_offset = offset + entry_ptr->count;
640     if((PRINT_SECTION))
641         chpr += printf(" length %lu",entry_ptr->count);
642     if((PRINT_ENTRY))
643     {
644         entries = entry_ptr->count / 4;
645         for(i = 0; i < entries; ++i)
646         {
647             chpr = newline(chpr);
648             value = read_ulong(inptr,TIFF_MOTOROLA,offset);
649             print_tag_address(ENTRY,offset,indent,"@");
650             if((PRINT_TAGINFO))
651                 chpr += printf("%s.",tagprefix);
652             offset += 4;
653 
654             /* Very oddly new values are inserted after value 51. */
655             corr_i=i;
656             if((model != MINOLTA_DIMAGE7Hi) && (model != MINOLTA_DIMAGEA1))
657             {
658                 if (i > 50)
659                     corr_i++;
660             }
661             if((model != MINOLTA_DIMAGEA1) && (model != MINOLTA_DIMAGEA2) && (model != MINOLTA_DIMAGEA200))
662             {
663                 if (i > 51)
664                     corr_i++;
665             }
666 
667             switch(corr_i)
668             {
669                 case 0:
670                     if((PRINT_TAGINFO))
671                         chpr += printf("%02d:%-21.21s",i,"Unknown");
672                     if((PRINT_VALUE))
673                         chpr += printf(" = %lu",value);
674                     break;
675                 case 1:
676                     if((PRINT_TAGINFO))
677                         chpr += printf("%02d:%-21.21s",i,"ExposureMode");
678                     if((PRINT_VALUE))
679                     {
680                         chpr += printf(" = %lu",value);
681                         print_startvalue();
682                         switch(value)
683                         {
684                             case 0: chpr += printf("Programmed Auto"); break;
685                             case 1: chpr += printf("Aperture Priority Auto"); break;
686                             case 2: chpr += printf("Shuttter Priority Auto"); break;
687                             case 3: chpr += printf("Manual"); break;
688                             default: printred("undefined"); break;
689                         }
690                         print_endvalue();
691                     }
692                     break;
693                 case 2:
694                     if((PRINT_TAGINFO))
695                         chpr += printf("%02d:%-21.21s",i,"FlashMode");
696                     if((PRINT_VALUE))
697                     {
698                         chpr += printf(" = %lu",value);
699                         print_startvalue();
700                         switch(value)
701                         {
702                             case 0: chpr += printf("Fill-Flash"); break;
703                             case 1: chpr += printf("Red Eye Reduction"); break;
704                             case 2: chpr += printf("Rear Flash Sync"); break;
705                             case 3: chpr += printf("Wireless"); break;
706                             default: printred("undefined"); break;
707                         }
708                         print_endvalue();
709                     }
710                     break;
711                 case 3:
712                     if((PRINT_TAGINFO))
713                         chpr += printf("%02d:%-21.21s",i,"WhiteBalance");
714                     if((PRINT_VALUE))
715                     {
716                         chpr += printf(" = %#lx",value);
717                         print_startvalue();
718                         if (value & 0x00ff0000)
719                         {
720                             /* New style white balance values */
721                             switch(value >> 24)
722                             {
723                                 case 0: printf("Auto"); break;
724                                 case 1: printf("Daylight"); break;
725                                 case 2: printf("Cloudy"); break;
726                                 case 3: printf("Incandescent"); break;
727                                 case 5: printf("Fluorescent"); break;
728                                 case 6: printf("Shadow"); break;
729                                 case 7: printf("Memory1"); break;
730                                 case 8: printf("Memory2"); break;
731                                 case 9: printf("Memory3"); break;
732                                 default: printred("unknown"); break;
733                             }
734                             wcorr = ((value & 0x00ffffff) >> 16) - 0x80;
735                             switch(wcorr)
736                             {
737                                 case 0: break;
738                                 default: printf(" %+hd", wcorr); break;
739                             }
740                         }
741                         else
742                         {
743                             /* Old style white balance values */
744                             switch(value)
745                             {
746                                 case 0: chpr += printf("Auto"); break;
747                                 case 1: chpr += printf("Daylight"); break;
748                                 case 2: chpr += printf("Cloudy"); break;
749                                 case 3: chpr += printf("Incandescent"); break;
750                                 case 5: chpr += printf("Custom"); break;
751                                 case 7: chpr += printf("Fluorescent"); break;
752                                 case 8: chpr += printf("Fluorescent2"); break;
753                                 case 11: chpr += printf("Custom2"); break;
754                                 case 12: chpr += printf("Custom3"); break;
755                                 default: printred("unknown"); break;
756                             }
757                         }
758                         print_endvalue();
759                     }
760                     break;
761                 case 4:
762                     if((PRINT_TAGINFO))
763                         chpr += printf("%02d:%-21.21s",i,"ImageSize");
764                     if((PRINT_VALUE))
765                     {
766                         chpr += printf(" = %lu",value);
767                         print_startvalue();
768                         switch(value)
769                         {
770                             /* ###%%% There should also be a          */
771                             /* 2080x1560 size, at least for the A1    */
772                             case 0: switch(model)
773                                     {
774                                         case MINOLTA_DIMAGEA2:
775                                             chpr += printf("3264x2448");
776                                             break;
777                                         case MINOLTA_DIMAGES404:
778                                         case MINOLTA_DIMAGES414:
779                                             chpr += printf("2272x1704");
780                                             break;
781                                         case MINOLTA_DIMAGE5:
782                                             chpr += printf("2048x1536");
783                                             break;
784                                         case MINOLTA_DIMAGEA1:
785                                         case MINOLTA_DIMAGE7Hi:
786                                         case MINOLTA_DIMAGE7i:
787                                         default:
788                                             chpr += printf("2560x1920");
789                                             break;
790                                     }
791                                     break;
792                             case 1: chpr += printf("1600x1200"); break;
793                             case 2: chpr += printf("1280x960"); break;
794                             case 3: chpr += printf("640x480"); break;
795                             default: printred("undefined"); break;
796                         }
797                         print_endvalue();
798                     }
799                     break;
800                 case 5:
801                     if((PRINT_TAGINFO))
802                         chpr += printf("%02d:%-21.21s",i,"ImageQuality");
803                     if((PRINT_VALUE))
804                     {
805                         chpr += printf(" = %lu",value);
806                         print_startvalue();
807                         switch(value)
808                         {
809                             case 0: chpr += printf("RAW"); break;
810                             case 1: chpr += printf("Super Fine"); break;
811                             case 2: chpr += printf("Fine"); break;
812                             case 3: chpr += printf("Standard"); break;
813                             case 4: chpr += printf("Economy"); break;
814                             case 5: chpr += printf("Extra Fine"); break;
815                             default: printred("undefined"); break;
816                         }
817                         print_endvalue();
818                     }
819                     break;
820                 case 6:
821                     if((PRINT_TAGINFO))
822                         chpr += printf("%02d:%-21.21s",i,"DriveMode");
823                     if((PRINT_VALUE))
824                     {
825                         chpr += printf(" = %lu",value);
826                         print_startvalue();
827                         switch(value)
828                         {
829                             case 0: chpr += printf("Single"); break;
830                             case 1: chpr += printf("Continuous"); break;
831                             case 2: chpr += printf("Self Timer"); break;
832                             case 4: chpr += printf("Bracketing"); break;
833                             case 5: chpr += printf("Interval"); break;
834                             case 6: chpr += printf("UHS Continuous"); break;
835                             case 7: chpr += printf("HS Continuous"); break;
836                             default: printred("undefined"); break;
837                         }
838                         print_endvalue();
839                     }
840                     break;
841                 case 7:
842                     if((PRINT_TAGINFO))
843                         chpr += printf("%02d:%-21.21s",i,"MeteringMode");
844                     if((PRINT_VALUE))
845                     {
846                         chpr += printf(" = %lu",value);
847                         print_startvalue();
848                         switch(value)
849                         {
850                             case 0: chpr += printf("Multi-Segment"); break;
851                             case 1: chpr += printf("Center Weighted"); break;
852                             case 2: chpr += printf("Spot"); break;
853                             default: printred("undefined"); break;
854                         }
855                         print_endvalue();
856                     }
857                     break;
858                 case 8:
859                     if((PRINT_TAGINFO))
860                         chpr += printf("%02d:%-21.21s",i,"CCDSentitivity");
861                     if((PRINT_VALUE))
862                     {
863                         if(PRINT_RAW_VALUES)
864                             chpr += printf(" = %lu",value);
865                         fvalue = ((double)value/8.0) - 1.0;
866                         chpr += printf(" = %.3g APEX",fvalue);
867                         fvalue = pow(2.0,fvalue) * 3.125;
868                         print_startvalue();
869                         chpr += printf("%.3g ISO",fvalue);
870                         print_endvalue();
871                     }
872                     break;
873                 case 9:
874                     if((PRINT_TAGINFO))
875                         chpr += printf("%02d_%-21.21s",i,"ShutterSpeed");
876                     if((PRINT_VALUE))
877                     {
878                         if(PRINT_RAW_VALUES)
879                             chpr += printf(" = %lu",value);
880                         if (value == 8)
881                             fvalue = 30.0; /* Due to rounding error x=8 should be displayed as 30 sec. */
882                         else
883                         {
884                             fvalue = ((double)value / 8.0) - 6.0;
885                             chpr += printf(" = %.3g APEX",fvalue);
886                             fvalue = pow(2.0,-fvalue);
887                         }
888                         print_startvalue();
889                         chpr += printf("%.3g sec",fvalue);
890                         print_endvalue();
891                     }
892                     break;
893                 case 10:
894                     if((PRINT_TAGINFO))
895                         chpr += printf("%02d_%-21.21s",i,"Aperture");
896                     if((PRINT_VALUE))
897                     {
898                         if(PRINT_RAW_VALUES)
899                             chpr += printf(" = %lu",value);
900                         fvalue = (double)value/8.0 - 1.0;
901                         chpr += printf(" = %.3g APEX",fvalue);
902                         fvalue = pow(2.0,fvalue/2.0);
903                         print_startvalue();
904                         chpr += printf("f%.2g",fvalue);
905                         print_endvalue();
906                     }
907                     break;
908                 case 11:
909                     if((PRINT_TAGINFO))
910                         chpr += printf("%02d_%-21.21s",i,"MacroMode");
911                     if((PRINT_VALUE))
912                     {
913                         chpr += printf(" = %lu",value);
914                         print_startvalue();
915                         switch(value)
916                         {
917                             case 0: chpr += printf("On"); break;
918                             case 1: chpr += printf("Off"); break;
919                             default: printred("undefined"); break;
920                         }
921                         print_endvalue();
922                     }
923                     break;
924                 case 12:
925                     if((PRINT_TAGINFO))
926                         chpr += printf("%02d_%-21.21s",i,"DigitalZoom");
927                     if((PRINT_VALUE))
928                     {
929                         chpr += printf(" = %lu",value);
930                         print_startvalue();
931                         switch(value)
932                         {
933                             case 0: chpr += printf("Off"); break;
934                             case 1: chpr += printf("Electronic"); break;
935                             case 2: chpr += printf("2x"); break;
936                             /* FIXME: http://www.dalibor.cz/minolta/makernote.htm says 2 */
937                             case 0xffff: chpr += printf("2x"); break;
938                             default: printred("Undefined"); break;
939                         }
940                         print_endvalue();
941                     }
942                     break;
943                 case 13:
944                     if((PRINT_TAGINFO))
945                         chpr += printf("%02d_%-21.21s",i,"ExposureCompensation");
946                     if((PRINT_VALUE))
947                     {
948                         chpr += printf(" = %lu",value);
949                         print_startvalue();
950                         chpr += printf("%g EV",(double)value/3.0 - 2);
951                         print_endvalue();
952                     }
953                     break;
954                 case 14:
955                     if((PRINT_TAGINFO))
956                         chpr += printf("%02d:%-21.21s",i,"BracketStep");
957                     if((PRINT_VALUE))
958                     {
959                         chpr += printf(" = %lu",value);
960                         print_startvalue();
961                         switch(value)
962                         {
963                             case 0: chpr += printf("1/3"); break;
964                             case 1: chpr += printf("2/3"); break;
965                             case 2: chpr += printf("1"); break;
966                             default: printred("undefined"); break;
967                         }
968                         print_endvalue();
969                     }
970                     break;
971                 case 15:
972                     if((PRINT_TAGINFO))
973                         chpr += printf("%02d:%-21.21s",i,"Unknown");
974                     if((PRINT_VALUE))
975                         chpr += printf(" = %lu",value);
976                     break;
977                 case 16:
978                     if((PRINT_TAGINFO))
979                         /* FIXME: Values don't fit on A1 */
980                         chpr += printf("%02d_%-21.21s",i,"IntervalLength");
981                     if((PRINT_VALUE))
982                     {
983                         chpr += printf(" = %lu",value + 1);
984                         chpr += printf(" minutes");
985                     }
986                     break;
987                 case 17:
988                     if((PRINT_TAGINFO))
989                         chpr += printf("%02d:%-21.21s",i,"IntervalNumber");
990                     if((PRINT_VALUE))
991                         chpr += printf(" = %lu",value);
992                     break;
993                 case 18:
994                     if((PRINT_TAGINFO))
995                         chpr += printf("%02d:%-21.21s",i,"FocalLength");
996                     if((PRINT_VALUE))
997                     {
998                         /* This value is not equal to FocalLength in public
999                            EXIF as the public one is tweaked to get 7x zoom to
1000                            comply with marketing specification. The real zoom
1001                            is 6.51x. * 3.9333 is 35mm equivalent */
1002                         chpr += printf(" = %lu",value);
1003                         fvalue = (double)value/256.0;
1004                         print_startvalue();
1005                         chpr += printf("%g mm",fvalue);
1006                         print_endvalue();
1007                     }
1008                     break;
1009                 case 19:
1010                     if((PRINT_TAGINFO))
1011                         chpr += printf("%02d:%-21.21s",i,"FocalDistance");
1012                     if((PRINT_VALUE))
1013                     {
1014                         if (value == 0)
1015                         {
1016                             chpr += printf(" = infinity");
1017                         }
1018                         else
1019                         {
1020                             chpr += printf(" = %lu",value);
1021                             chpr += printf(" mm");
1022                         }
1023                     }
1024                     break;
1025                 case 20:
1026                     if((PRINT_TAGINFO))
1027                         chpr += printf("%02d:%-21.21s",i,"FlashFired");
1028                     if((PRINT_VALUE))
1029                     {
1030                         chpr += printf(" = %lu",value);
1031                         print_startvalue();
1032                         if(value == 0UL)
1033                             chpr += printf("No");
1034                         else
1035                             chpr += printf("Yes");
1036                         print_endvalue();
1037                     }
1038                     break;
1039                 case 21:
1040                     if((PRINT_TAGINFO))
1041                         chpr += printf("%02d:%-21.21s",i,"Date");
1042                     if((PRINT_VALUE))
1043                     {
1044                         chpr += printf(" = %#010lx",value);
1045                         print_startvalue();
1046                         chpr += printf("%02ld:%02ld:%02ld",(value & 0xffff0000) >> 16,
1047                                 (value & 0xff00) >> 8,value & 0xff);
1048                         print_endvalue();
1049                     }
1050                     break;
1051                 case 22:
1052                     if((PRINT_TAGINFO))
1053                         chpr += printf("%02d:%-21.21s",i,"Time");
1054                     if((PRINT_VALUE))
1055                     {
1056                         chpr += printf(" = %#010lx",value);
1057                         print_startvalue();
1058                         chpr += printf("%02ld:%02ld:%02ld",(value & 0xffff0000) >> 16,
1059                                 (value & 0xff00) >> 8,value & 0xff);
1060                         print_endvalue();
1061                     }
1062                     break;
1063                 case 23:
1064                     if((PRINT_TAGINFO))
1065                         chpr += printf("%02d_%-21.21s",i,"MaxAperture");
1066                     if((PRINT_VALUE))
1067                     {
1068                         if(PRINT_RAW_VALUES)
1069                             chpr += printf(" = %lu",value);
1070                         fvalue = (double)value/8.0 - 1.0;
1071                         chpr += printf(" = %.3g APEX",fvalue);
1072                         fvalue = pow(2.0,fvalue/2.0);
1073                         print_startvalue();
1074                         chpr += printf("f%.2g",fvalue);
1075                         print_endvalue();
1076                     }
1077                     break;
1078                 case 24:
1079                     if((PRINT_TAGINFO))
1080                         chpr += printf("%02d:%-21.21s",i,"Unknown");
1081                     if((PRINT_VALUE))
1082                         chpr += printf(" = %lu",value);
1083                     break;
1084                 case 25:
1085                     if((PRINT_TAGINFO))
1086                         chpr += printf("%02d:%-21.21s",i,"Unknown");
1087                     if((PRINT_VALUE))
1088                         chpr += printf(" = %lu",value);
1089                     break;
1090                 case 26:
1091                     if((PRINT_TAGINFO))
1092                         chpr += printf("%02d:%-21.21s",i,"FileNumberMemory");
1093                     if((PRINT_VALUE))
1094                     {
1095                         chpr += printf(" = %lu",value);
1096                         print_startvalue();
1097                         if(value == 0UL)
1098                             chpr += printf("Off");
1099                         else
1100                             chpr += printf("On");
1101                         print_endvalue();
1102                     }
1103                     break;
1104                 case 27:
1105                     if((PRINT_TAGINFO))
1106                         chpr += printf("%02d:%-21.21s",i,"LastFileNumber");
1107                     if((PRINT_VALUE))
1108                     {
1109                         chpr += printf(" = %lu",value);
1110                         /* 0 if FileNumberMemory is off */
1111                         if(value == 0)
1112                         {
1113                             print_startvalue();
1114                             chpr += printf("(FileNumberMemory Off)");
1115                             print_endvalue();
1116                         }
1117                     }
1118                     break;
1119                 case 28:
1120                     if((PRINT_TAGINFO))
1121                         chpr += printf("%02d_%-21.21s",i,"WhiteBalanceRed");
1122                     if((PRINT_VALUE))
1123                     {
1124                         chpr += printf(" = %lu",value);
1125                         print_startvalue();
1126                         chpr += printf("%.3f",value/256.0);
1127                         print_endvalue();
1128                     }
1129                     break;
1130                 case 29:
1131                     /* Warning! Green white balance coefficient in    */
1132                     /* raw file may not be equal to one and in this   */
1133                     /* case WB coefficients stored in raw file will   */
1134                     /* not match those stored here.                   */
1135                     if((PRINT_TAGINFO))
1136                         chpr += printf("%02d:%-21.21s",i,"WhiteBalanceGreen");
1137                     if((PRINT_VALUE))
1138                     {
1139                         chpr += printf(" = %lu",value);
1140                         print_startvalue();
1141                         chpr += printf("%.3f",value/256.0);
1142                         print_endvalue();
1143                     }
1144                     break;
1145                 case 30:
1146                     if((PRINT_TAGINFO))
1147                         chpr += printf("%02d:%-21.21s",i,"WhiteBalanceBlue");
1148                     if((PRINT_VALUE))
1149                     {
1150                         chpr += printf(" = %lu",value);
1151                         print_startvalue();
1152                         chpr += printf("%.3f",value/256.0);
1153                         print_endvalue();
1154                     }
1155                     break;
1156                 case 31:
1157                     if((PRINT_TAGINFO))
1158                         chpr += printf("%02d:%-21.21s",i,"Saturation");
1159                     if((PRINT_VALUE))
1160                     {
1161                         chpr += printf(" = %lu",value);
1162                         print_startvalue();
1163                         if ((model == MINOLTA_DIMAGEA1) || (model == MINOLTA_DIMAGEA2) || (model == MINOLTA_DIMAGEA200))
1164                             chpr += printf("%+ld",value-5);
1165                         else
1166                             chpr += printf("%+ld",value-3);
1167 
1168                         print_endvalue();
1169                     }
1170                     break;
1171                 case 32:
1172                     if((PRINT_TAGINFO))
1173                         chpr += printf("%02d:%-21.21s",i,"Contrast");
1174                     if((PRINT_VALUE))
1175                     {
1176                         chpr += printf(" = %lu",value);
1177                         print_startvalue();
1178                         if ((model == MINOLTA_DIMAGEA1) || (model == MINOLTA_DIMAGEA2) || (model == MINOLTA_DIMAGEA200))
1179                             chpr += printf("%+ld",value-5);
1180                         else
1181                             chpr += printf("%+ld",value-3);
1182 
1183                         print_endvalue();
1184                     }
1185                     break;
1186                 case 33:
1187                     if((PRINT_TAGINFO))
1188                         chpr += printf("%02d:%-21.21s",i,"Sharpness");
1189                     if((PRINT_VALUE))
1190                     {
1191                         chpr += printf(" = %lu",value);
1192                         print_startvalue();
1193                         switch(value)
1194                         {
1195                             case 0: chpr += printf("Hard"); break;
1196                             case 1: chpr += printf("Normal"); break;
1197                             case 2: chpr += printf("Soft"); break;
1198                             case 3: chpr += printf("None"); break;
1199                             default: printred("undefined"); break;
1200                         }
1201                         print_endvalue();
1202                     }
1203                     break;
1204                 case 34:
1205                     if((PRINT_TAGINFO))
1206                         chpr += printf("%02d:%-21.21s",i,"Subject Program");
1207                     if((PRINT_VALUE))
1208                     {
1209                         chpr += printf(" = %lu",value);
1210                         print_startvalue();
1211                         switch(value)
1212                         {
1213                             case 0: chpr += printf("None"); break;
1214                             case 1: chpr += printf("Portrait"); break;
1215                             case 2: chpr += printf("Text"); break;
1216                             case 3: chpr += printf("Night Portrait"); break;
1217                             case 4: chpr += printf("Sunset"); break;
1218                             case 5: chpr += printf("Sports Action"); break;
1219                             default: printred("undefined"); break;
1220                         }
1221                         print_endvalue();
1222                     }
1223                     break;
1224                 case 35:
1225                     if((PRINT_TAGINFO))
1226                         chpr += printf("%02d:%-21.21s",i,"FlashCompensation");
1227                     if((PRINT_VALUE))
1228                     {
1229                         chpr += printf(" = %lu",value);
1230                         fvalue = ((double)value - 6.0) / 3.0;
1231                         print_startvalue();
1232                         chpr += printf("%g EV",fvalue);
1233                         print_endvalue();
1234                     }
1235                     break;
1236                 case 36:
1237                     if((PRINT_TAGINFO))
1238                         chpr += printf("%02d:%-21.21s",i,"ISO Setting");
1239                     if((PRINT_VALUE))
1240                     {
1241                         chpr += printf(" = %lu",value);
1242                         print_startvalue();
1243                         switch(value)
1244                         {
1245                             case 0: chpr += printf("100"); break;
1246                             case 1: chpr += printf("200"); break;
1247                             case 2: chpr += printf("200"); break;
1248                             case 3: chpr += printf("800"); break;
1249                             case 4: chpr += printf("Auto"); break;
1250                             case 5: chpr += printf("64"); break;
1251                             default: printred("undefined"); break;
1252                         }
1253                         print_endvalue();
1254                     }
1255                     break;
1256                 case 37:
1257                     if((PRINT_TAGINFO))
1258                         chpr += printf("%02d:%-21.21s",i,"CameraModel");
1259                     if((PRINT_VALUE))
1260                     {
1261                         chpr += printf(" = %lu",value);
1262                         print_startvalue();
1263                         switch(value)
1264                         {
1265                             case 0: chpr += printf("DiMAGE 7"); break;
1266                             case 1: chpr += printf("DiMAGE 5"); break;
1267                             case 2: chpr += printf("DiMAGE S304"); break;
1268                             case 3: chpr += printf("DiMAGE S404"); break;
1269                             case 4: chpr += printf("DiMAGE 7i"); break;
1270                             case 5: chpr += printf("DiMAGE 7Hi"); break;
1271                             case 6: chpr += printf("DiMAGE A1"); break;
1272                             case 7: chpr += printf("DiMAGE (A2 or S414)"); break;
1273                             /* A200 doesn't appear to have            */
1274                             /* CameraSettings                         */
1275                             default: printred("unknown"); break;
1276                         }
1277                         print_endvalue();
1278                     }
1279                     break;
1280                 case 38:
1281                     if((PRINT_TAGINFO))
1282                         chpr += printf("%02d:%-21.21s",i,"IntervalMode*");
1283                     if((PRINT_VALUE))
1284                     {
1285                         chpr += printf(" = %lu",value);
1286                         print_startvalue();
1287                         switch(value)
1288                         /* FIXME: verify it */
1289                         {
1290                             case 0: chpr += printf("Still Image"); break;
1291                             case 1: chpr += printf("Time Lapse"); break;
1292                             default: printred("undefined"); break;
1293                         }
1294                         print_endvalue();
1295                     }
1296                     break;
1297                 case 39:
1298                     if((PRINT_TAGINFO))
1299                         chpr += printf("%02d:%-21.21s",i,"FolderName");
1300                     if((PRINT_VALUE))
1301                     {
1302                         chpr += printf(" = %lu",value);
1303                         print_startvalue();
1304                         switch(value)
1305                         {
1306                             case 0: chpr += printf("Standard Form"); break;
1307                             case 1: chpr += printf("Data Form"); break;
1308                             default: printred("undefined"); break;
1309                         }
1310                         print_endvalue();
1311                     }
1312                     break;
1313                 case 40:
1314                     if((PRINT_TAGINFO))
1315                         chpr += printf("%02d:%-21.21s",i,"ColorMode");
1316                     if((PRINT_VALUE))
1317                     {
1318                         chpr += printf(" = %lu",value);
1319                         print_startvalue();
1320                         switch(value)
1321                         {
1322                             case 0: chpr += printf("Natural Color"); break;
1323                             case 1: chpr += printf("Black and White"); break;
1324                             case 2: chpr += printf("Vivid Color"); break;
1325                             case 3: chpr += printf("Solarization"); break;
1326                             case 4: chpr += printf("Adobe RGB"); break;
1327                             case 9: chpr += printf("unknown"); break;
1328                             case 132: chpr += printf("Adobe RGB Embedded Profile"); break;
1329                             default: printred("undefined"); break;
1330                         }
1331                         print_endvalue();
1332                     }
1333                     break;
1334                 case 41:
1335                     /* FIXME: assign values */
1336                     if((PRINT_TAGINFO))
1337                         chpr += printf("%02d:%-21.21s",i,"ColorFilter");
1338                     if((PRINT_VALUE))
1339                     {
1340                         chpr += printf(" = %lu",value);
1341                         switch(model)
1342                         {
1343                             case MINOLTA_DIMAGEA2:
1344                             case MINOLTA_DIMAGEA1:
1345                                 print_startvalue();
1346                                 switch(value)
1347                                 {
1348                                     case 0: chpr += printf("cool 100%%"); break;
1349                                     case 1: chpr += printf("cool 80%%"); break;
1350                                     case 2: chpr += printf("cool 60%%"); break;
1351                                     case 3: chpr += printf("cool 40%%"); break;
1352                                     case 4: chpr += printf("cool 20%%"); break;
1353                                     case 5: chpr += printf("no cool/warm adjustment"); break;
1354                                     case 6: chpr += printf("warm 20%%"); break;
1355                                     case 7: chpr += printf("warm 40%%"); break;
1356                                     case 8: chpr += printf("warm 60%%"); break;
1357                                     case 9: chpr += printf("warm 80%%"); break;
1358                                     case 10: chpr += printf("warm 100%%"); break;
1359                                     default: chpr += printf("undefined"); break;
1360                                 }
1361                                 print_endvalue();
1362                                 break;
1363                             case MINOLTA_DIMAGE7Hi:
1364                             case MINOLTA_DIMAGE7i:
1365                                 print_startvalue();
1366                                 switch(value)
1367                                 {
1368                                     case 0: chpr += printf("cool 100%%"); break;
1369                                     case 1: chpr += printf("cool 67%%"); break;
1370                                     case 2: chpr += printf("cool 33%%"); break;
1371                                     case 3: chpr += printf("no cool/warm adjustment"); break;
1372                                     case 4: chpr += printf("warm 33%%"); break;
1373                                     case 5: chpr += printf("warm 67%%"); break;
1374                                     case 6: chpr += printf("warm 100%%"); break;
1375                                     default: chpr += printf("undefined"); break;
1376                                 }
1377                                 print_endvalue();
1378                                 break;
1379                             default:
1380                                 /* Print nothing unless the model is  */
1381                                 /* known                              */
1382                                 break;
1383                         }
1384                     }
1385                     break;
1386                 case 42:
1387                     /* FIXME: assign values */
1388                     if((PRINT_TAGINFO))
1389                         chpr += printf("%02d:%-21.21s",i,"BWFilter");
1390                     if((PRINT_VALUE))
1391                         chpr += printf(" = %lu",value);
1392                     break;
1393                 case 43:
1394                     if((PRINT_TAGINFO))
1395                         chpr += printf("%02d:%-21.21s",i,"InternalFlashFired");
1396                     if((PRINT_VALUE))
1397                     {
1398                         chpr += printf(" = %lu",value);
1399                         print_startvalue();
1400                         switch(value)
1401                         {
1402                             case 0: chpr += printf("No"); break;
1403                             case 1: chpr += printf("Yes"); break;
1404                             default: printred("undefined"); break;
1405                         }
1406                         print_endvalue();
1407                     }
1408                     break;
1409                 case 44:
1410                     if((PRINT_TAGINFO))
1411                         chpr += printf("%02d_%-21.21s",i,"BrightnessValue");
1412                     if((PRINT_VALUE))
1413                     {
1414                         if(PRINT_RAW_VALUES)
1415                             chpr += printf(" = %lu",value);
1416                         fvalue = ((double)value/ 8.0) - 6.0;
1417                         chpr += printf(" = %g APEX",fvalue);
1418                         fvalue = pow(2.0,fvalue);
1419                         print_startvalue();
1420                         chpr += printf("%.3f foot lambert",fvalue);
1421                         print_endvalue();
1422                     }
1423                     break;
1424                 case 45:
1425                     if((PRINT_TAGINFO))
1426                         chpr += printf("%02d:%-21.21s",i,"SpotFocusPointX");
1427                     if((PRINT_VALUE))
1428                         chpr += printf(" = %lu",value);
1429                     break;
1430                 case 46:
1431                     if((PRINT_TAGINFO))
1432                         chpr += printf("%02d:%-21.21s",i,"SpotFocusPointY");
1433                     if((PRINT_VALUE))
1434                         chpr += printf(" = %lu",value);
1435                     break;
1436                 case 47:
1437                     if((PRINT_TAGINFO))
1438                         chpr += printf("%02d:%-21.21s",i,"WideFocusZone");
1439                     if((PRINT_VALUE))
1440                     {
1441                         chpr += printf(" = %lu",value);
1442                         print_startvalue();
1443                         /* FIXME: Different for A1 */
1444                         if(model == MINOLTA_DIMAGEA1)
1445                             chpr += printf("Unknown");
1446                         else
1447                         {
1448                             switch(value)
1449                             {
1450                                 case 0: chpr += printf("no zone"); break;
1451                                 case 1: chpr += printf("center zone (horizontal)"); break;
1452                                 case 2: chpr += printf("center zone (vertical)"); break;
1453                                 case 3: chpr += printf("left zone"); break;
1454                                 case 4: chpr += printf("right zone"); break;
1455                                 default: printred("undefined"); break;
1456                             }
1457                         }
1458                         print_endvalue();
1459                     }
1460                     break;
1461                 case 48:
1462                     if((PRINT_TAGINFO))
1463                         chpr += printf("%02d:%-21.21s",i,"FocusMode");
1464                     if((PRINT_VALUE))
1465                     {
1466                         chpr += printf(" = %lu",value);
1467                         print_startvalue();
1468                         switch(value)
1469                         {
1470                             case 0: chpr += printf("Auto"); break;
1471                             case 1: chpr += printf("Manual"); break;
1472                             default: printred("undefined"); break;
1473                         }
1474                         print_endvalue();
1475                     }
1476                     break;
1477                 case 49:
1478                     if((PRINT_TAGINFO))
1479                         chpr += printf("%02d:%-21.21s",i,"FocusArea");
1480                     if((PRINT_VALUE))
1481                     {
1482                         chpr += printf(" = %lu",value);
1483                         print_startvalue();
1484                         switch(value)
1485                         {
1486                             case 0: chpr += printf("Wide"); break;
1487                             case 1: chpr += printf("Spot"); break;
1488                             default: printred("undefined"); break;
1489                         }
1490                         print_endvalue();
1491                     }
1492                     break;
1493                 case 50:
1494                     if((PRINT_TAGINFO))
1495                         chpr += printf("%02d:%-21.21s",i,"DECPosition");
1496                     if((PRINT_VALUE))
1497                     {
1498                         chpr += printf(" = %lu",value);
1499                         print_startvalue();
1500                         switch(value)
1501                         {
1502                             case 0: chpr += printf("Exposure"); break;
1503                             case 1: chpr += printf("Contrast"); break;
1504                             case 2: chpr += printf("Saturation"); break;
1505                             case 3: chpr += printf("Filter"); break;
1506                             default: printred("undefined"); break;
1507                         }
1508                         print_endvalue();
1509                     }
1510                     break;
1511                 case 51:
1512                     if((PRINT_TAGINFO))
1513                         chpr += printf("%02d:%-21.21s",i,"ColorProfileEmbedded");
1514                     if((PRINT_VALUE))
1515                     {
1516                             chpr += printf(" = %lu",value);
1517                             print_startvalue();
1518                             switch(value)
1519                             {
1520                                 case 0: chpr += printf("No"); break;
1521                                 case 1: chpr += printf("Yes"); break;
1522                                 default: printred("undefined"); break;
1523                             }
1524                             print_endvalue();
1525                     }
1526                     break;
1527                 case 52:
1528                     if((PRINT_TAGINFO))
1529                         chpr += printf("%02d:%-21.21s",i,"AntiShake");
1530                     if((PRINT_VALUE))
1531                     {
1532                             chpr += printf(" = %lu",value);
1533                             print_startvalue();
1534                             switch(value)
1535                             {
1536                                 case 0: chpr += printf("Off"); break;
1537                                 case 1: chpr += printf("On"); break;
1538                                 default: printred("undefined"); break;
1539                             }
1540                             print_endvalue();
1541                     }
1542                     break;
1543                 case 53:
1544                     if((PRINT_TAGINFO))
1545                         chpr += printf("%02d:%-21.21s",i,"DataImprint");
1546                     if((PRINT_VALUE))
1547                     {
1548                             chpr += printf(" = %lu",value);
1549                             print_startvalue();
1550                             switch(value)
1551                             {
1552                                 case 0: chpr += printf("None"); break;
1553                                 case 1: chpr += printf("YYYY/MM/DD"); break;
1554                                 case 2: chpr += printf("MM/DD/HR.MIN"); break;
1555                                 case 3: chpr += printf("Text"); break;
1556                                 case 4: chpr += printf("Text + Id#"); break;
1557                                 default: printred("undefined"); break;
1558                             }
1559                             print_endvalue();
1560                     }
1561                     break;
1562                 default:
1563                     if((PRINT_TAGINFO))
1564                         chpr += printf("%02d:%-21.21s",i,"Unknown");
1565                     if((PRINT_VALUE))
1566                         chpr += printf(" = %#lx/%lu",value,value);
1567                     break;
1568             }
1569         }
1570     }
1571     setcharsprinted(chpr);
1572     return(end_offset);
1573 }
1574 
1575 int
maker_minolta_value_is_offset(struct ifd_entry * entry_ptr,int model)1576 maker_minolta_value_is_offset(struct ifd_entry *entry_ptr,int model)
1577 {
1578     int is_offset = 0;
1579 
1580     if(entry_ptr)
1581     {
1582         switch(entry_ptr->tag)
1583         {
1584             case 0x0040: is_offset = -1; break; /* cancel */
1585             case 0x0088: is_offset = 1; break;
1586             case 0x0089: is_offset = -1; break;
1587             default: break;
1588         }
1589     }
1590     return(is_offset);
1591 }
1592 
1593 /* I have seen at least 9 Minolta versions, as shown below.           */
1594 /* Fortunately, some of the variations are minor, and the tagsets do  */
1595 /* not overlap, so it is possible to service all of them with just    */
1596 /* one tagset and one set of processing routines. The version strings */
1597 /* in the notes have no apparent meaning.                             */
1598 
1599 /* tagsets: HEX
1600 0,1,10,20,40,81,e00  MLT0
1601 0,1,10,20,40,E00  mlt0
1602 0,3,10,20,40,88,89,E00 MLT0
1603 0,3,10,20,40,88,89,100-103 MLT0
1604 0,4,10,18,20,40,88,89,100-107,10A-10D (MRW) MLT0
1605 0,88,89,100-103,F00 MLY0
1606 0,88,89,100-103,F00,18 (MRW) MLY0
1607 0,200-21F,E00,F00   MLT0
1608 0,81,200-21F,E00,F00 MLT0
1609 */
1610