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_nikon.c,v 1.30 2005/07/24 22:56:26 alex Exp $";
11 #endif
12 
13 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14 /* Nikon camera maker-specific routines.                              */
15 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
16 /* Much of the information coded here is due to TsuruZoh Tachibanaya  */
17 /* at:                                                                */
18 /* http://www.ba.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html   */
19 
20 /* and Max Lyons (E990 data) at:                                      */
21 /*   http://www.tawbaware.com/                                        */
22 
23 /* Some information is taken from Eugene Crosser's "photopc" program: */
24 /*   http://photopc.sourceforge.net/                                  */
25 /* (as modified by John Bowman: http://www.math.ualberta.ca/imaging/) */
26 
27 /* The presence of JPEG thumbnails in TIFF format makernotes,         */
28 /* extension of (some) E990 tags to the E995 and later models, the    */
29 /* extra TIFF header in D100s, and the PrintIM data in some models,   */
30 /* is due to examination (by earlier versions of this program) of     */
31 /* images from my Nikon 990, and sample images obtained               */
32 /* from:                                                              */
33 /*   http://www.imaging-resource.com/                                 */
34 /* and                                                                */
35 /*   http://www.dpreview.com/                                         */
36 
37 /* April, 2005:                                                       */
38 /* Much of the new information for later model Nikons is taken from   */
39 /* information provided by a Phil Harvey (author of 'exiftool') at:   */
40 /*   http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html */
41 /* and/or  Evan Hunter ("The PHP JPEG Metadata Toolkit"), at:         */
42 /*   http://www.ozhiker.com/electronics/pjmt/jpeg_info/nikon_mn.html  */
43 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
44 
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <math.h>
49 #include "defs.h"
50 #include "datadefs.h"
51 #include "maker_datadefs.h"
52 #include "summary.h"
53 #include "maker.h"
54 #include "misc.h"
55 #include "tags.h"
56 #include "maker_extern.h"
57 #include "extern.h"
58 
59 extern struct camera_id nikon_model_id[];
60 
61 /* Find the identifying number assigned to known Nikon camera models. */
62 /* This number is used to dispatch print and interpret routines       */
63 /* apporopriate to the current image. At the moment, the "software"   */
64 /* string is not used.                                                */
65 
66 int
nikon_model_number(char * model,char * software)67 nikon_model_number(char *model,char *software)
68 {
69     struct camera_id *model_id;
70     int number = NO_MODEL;
71 
72     for(model_id = &nikon_model_id[0]; model_id && model_id->name; ++model_id)
73     {
74         if(strncasecmp(model,model_id->name,model_id->namelen) == 0)
75         {
76             number = model_id->id;
77             setnoteversion(model_id->noteversion);
78             setnotetagset(model_id->notetagset);    /* info only      */
79             break;
80         }
81     }
82     return(number);
83 }
84 
85 /* Determine and set note version from detected scheme.               */
86 /* Notes with ID scheme use tagset 1, offset routine 1, interp 1      */
87 /* Notes with Plain and ID/TIFFhdr use tagset 2, offset 2, interp 2   */
88 
89 /* first tag is also distinctive (v2 has 0x1 (UNDEFINED count 4,      */
90 /* ascii version), v1 has 0x2 (ASCII count 6, "08.00") although TIFF  */
91 /* files will have a thumbnail (0x100) which displaces the first tag  */
92 /* (placed out of numerical sort order).                              */
93 /* For now, it does not seem necessary to check first tag.            */
94 
95 int
set_nikon_noteversion()96 set_nikon_noteversion()
97 {
98     struct maker_scheme *scheme;
99     int noteversion = 0;
100     int tagset = 0;
101 
102     scheme = retrieve_makerscheme();
103     if(scheme->note_version <= 0)
104     {
105         noteversion = -1;
106         tagset = -1;
107         switch(scheme->scheme_type)
108         {
109             case HAS_ID_SCHEME:
110                 tagset = 1;
111                 noteversion = 1;
112                 break;
113             case PLAIN_IFD_SCHEME:
114             case HAS_ID_PLUS_TIFFHDR_SCHEME:
115                 tagset = 2;
116                 noteversion = 2;
117                 break;
118             case UNKNOWN_SCHEME:
119                 break;
120             default:
121                 break;
122         }
123         setnotetagset(tagset);
124         setnoteversion(noteversion);
125     }
126     else
127         noteversion = scheme->note_version;
128     return(noteversion);
129 }
130 
131 void
print_nikon_makervalue(struct ifd_entry * entry_ptr,int make,int model,char * prefix)132 print_nikon_makervalue(struct ifd_entry *entry_ptr,int make, int model,
133                     char *prefix)
134 {
135     int noteversion = 0;
136 
137     noteversion = getnoteversion();
138 
139     if(entry_ptr && (PRINT_VALUE))
140     {
141         switch(noteversion)
142         {
143             case 1:
144                 print_value(entry_ptr,PREFIX);
145                 nikon1_interpret_value(entry_ptr);
146                 break;
147             case 2:
148                 print_value(entry_ptr,PREFIX);
149                 nikon2_interpret_value(entry_ptr);
150                 break;
151             default:
152                 print_value(entry_ptr,PREFIX);
153                 break;
154         }
155     }
156 }
157 
158 void
print_nikon_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)159 print_nikon_offset_makervalue(FILE *inptr,unsigned short byteorder,
160     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
161     struct image_summary *summary_entry,char *parent_name,char*prefix,
162     int indent,int make,int model,int at_offset)
163 {
164     int noteversion = 0;
165     char *nameoftag;
166 
167     noteversion = getnoteversion();
168 
169     if(entry_ptr)
170     {
171         switch(noteversion)
172         {
173             case 1:
174                 nikon1_offset_makervalue(inptr,byteorder,entry_ptr,
175                                             fileoffset_base,summary_entry,
176                                             parent_name,prefix,indent,
177                                             make,model,at_offset);
178                 break;
179             case 2:
180                 nikon2_offset_makervalue(inptr,byteorder,entry_ptr,
181                                             fileoffset_base,summary_entry,
182                                             parent_name,prefix,indent,
183                                             make,model,at_offset);
184                 nameoftag = maker_tagname(entry_ptr->tag,make,model);
185                 nikon2_interpret_offset_makervalue(inptr,byteorder,entry_ptr,
186                                                 fileoffset_base,parent_name,
187                                                 nameoftag,indent);
188                 break;
189             default:
190                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
191                                         fileoffset_base,parent_name,prefix,
192                                         indent,make,model,at_offset);
193                 break;
194         }
195     }
196 }
197 
198 void
nikon1_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)199 nikon1_offset_makervalue(FILE *inptr,unsigned short byteorder,
200     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
201     struct image_summary *summary_entry,char *parent_name,char*prefix,
202     int indent,int make,int model,int at_offset)
203 {
204     unsigned long max_offset = 0;
205     unsigned long value_offset;
206     unsigned long count;
207     unsigned long dumplength;
208     unsigned short marker;
209     int status = 0;
210     int chpr = 0;
211     char *nameoftag;
212     char *fulldirname = NULL;
213 
214     if(entry_ptr)
215     {
216         nameoftag = maker_tagname(entry_ptr->tag,make,model);
217         fulldirname = splice(parent_name,".",nameoftag);
218         value_offset = fileoffset_base + entry_ptr->value;
219         count = entry_ptr->count;
220 
221         switch(entry_ptr->tag)
222         {
223             case 0x0100: /* Jpeg Thumbnail                            */
224                 if(at_offset && (PRINT_SECTION))
225                 {
226                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
227                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
228                     chpr += printf(" length %lu",count);
229                 }
230                 else if(!at_offset && (PRINT_VALUE))
231                 {
232                     if(!(PRINT_OFFSET))
233                         chpr += printf("@%lu:%-9lu",value_offset,count);
234                     else
235                         chpr += printf(":%-9lu", count);
236                     if(!(PRINT_VALUE_AT_OFFSET))
237                         chpr += printf(" # UNDEFINED");
238                 }
239                 if((PRINT_SECTION) || (PRINT_SEGMENT))
240                     chpr = newline(chpr);
241                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
242                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
243                                     count,summary_entry,fulldirname,
244                                     prefix,indent+SMALLINDENT);
245                 if(at_offset)
246                 {
247                     if((PRINT_SECTION))
248                     {
249                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
250                             chpr = newline(chpr);
251                         jpeg_status(status);
252                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
253                                                                         indent,"-");
254                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
255                         chpr += printf(" length %ld",count);
256                         if((PRINT_ENTRY) && !(PRINT_VALUE))
257                             chpr = newline(chpr);
258                     }
259                 }
260                 print_jpeg_status();
261                 if(marker && summary_entry)
262                 {
263                     /* The new one is on the end of the chain         */
264                     if((summary_entry = last_summary_entry(summary_entry)))
265                     {
266                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
267                         summary_entry->datatype = MAKER_IFD;
268                         summary_entry->subfiletype = THUMBNAIL_TYPE;
269                     }
270                 }
271                 /* make certain we're at the end                      */
272                 clearerr(inptr);
273                 fseek(inptr,value_offset + count,0);
274                 break;
275             case 0x0f00: /* Data                                      */
276                 if(at_offset && (PRINT_ENTRY))
277                 {
278                     print_tag_address(ENTRY,value_offset,indent,prefix);
279                     print_makertagid(entry_ptr,25," : ",make,model);
280                     chpr += printf("length %-9lu # UNDEFINED", count);
281                 }
282                 else if(!at_offset && (PRINT_VALUE))
283                 {
284                     if(!(PRINT_OFFSET))
285                         chpr += printf("@%lu:%lu",value_offset,count);
286                     else
287                         chpr += printf(":%lu", count);
288                     if(!(PRINT_VALUE_AT_OFFSET))
289                         chpr += printf(" # UNDEFINED");
290                 }
291                 if(Max_undefined == 0)
292                 {
293                     if(chpr)
294                         printred(" (not dumped, use -U)");
295                 }
296                 else
297                 {
298                     if((Max_undefined == DUMPALL) || (Max_undefined > count))
299                         dumplength = count;
300                     else
301                         dumplength = Max_undefined;
302                     chpr = newline(chpr);
303                     hexdump(inptr,value_offset,count,dumplength,12,
304                                         indent,SUBINDENT);
305                     chpr = newline(1);
306                 }
307                 /* make certain we're at the end                      */
308                 fseek(inptr,value_offset + count,0);
309                 break;
310             default:
311                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
312                                         fileoffset_base,fulldirname,prefix,indent,
313                                         make,model,at_offset);
314                 break;
315         }
316         if(fulldirname)
317             free(fulldirname);
318     }
319     setcharsprinted(chpr);
320 }
321 
322 void
nikon2_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)323 nikon2_offset_makervalue(FILE *inptr,unsigned short byteorder,
324     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
325     struct image_summary *summary_entry,char *parent_name,char*prefix,
326     int indent,int make,int model,int at_offset)
327 {
328     unsigned long max_offset = 0;
329     unsigned long value_offset;
330     unsigned long count;
331     unsigned long dumplength;
332     unsigned long orig_print_options;
333     unsigned short marker;
334     char *nameoftag;
335     char *fulldirname = NULL;
336     int status = 0;
337     int chpr = 0;
338     int ifdnum = -1;
339     int subifdnum = -1;
340 
341     if(entry_ptr)
342     {
343         nameoftag = maker_tagname(entry_ptr->tag,make,model);
344         fulldirname = splice(parent_name,".",nameoftag);
345         value_offset = fileoffset_base + entry_ptr->value;
346         count = entry_ptr->count;
347 
348         switch(entry_ptr->tag)
349         {
350             case 0x0011: /* "NikonPreviewImage"                       */
351                 if(at_offset && (PRINT_SECTION))
352                 {
353                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
354                     chpr += printf("# Start of Nikon Preview Image SubIFD from MakerNote");
355                 }
356                 else if(!at_offset && (PRINT_VALUE))
357                 {
358                     if(!(PRINT_OFFSET))
359                         chpr += printf("@%lu",value_offset);
360                 }
361                 chpr = newline(chpr);
362                 if(summary_entry)
363                 {
364                     ifdnum = summary_entry->ifdnum;
365                     subifdnum = summary_entry->subifdnum;
366                 }
367                 value_offset = process_tiff_ifd(inptr,byteorder,entry_ptr->value,
368                                         fileoffset_base,0,summary_entry,fulldirname,
369                                         MAKER_SUBIFD,ifdnum,subifdnum,
370                                         indent+SMALLINDENT);
371                 if(at_offset && (PRINT_SECTION))
372                 {
373                     chpr = newline(chpr);
374                     if(value_offset == 0)
375                         PUSHCOLOR(RED);
376                     print_tag_address(VALUE_AT_OFFSET,value_offset - 1,
377                                                 indent,"-");
378                     if(value_offset == 0)
379                         POPCOLOR();
380                     chpr += printf("# End of Nikon Preview Image SubIFD from MakerNote");
381                     if(value_offset == 0)
382                         printred(" (INVALID)");
383                 }
384                 if(summary_entry)
385                 {
386                     /* The new one is on the end of the chain         */
387                     if((summary_entry = last_summary_entry(summary_entry)))
388                     {
389                         summary_entry->filesubformat |= FILESUBFMT_MNSUBIFD;
390                         summary_entry->datatype = MAKER_SUBIFD;
391                         summary_entry->subfiletype = REDUCED_RES_TYPE;
392                     }
393                 }
394                 break;
395             case 0x0100: /* Jpeg Thumbnail                            */
396                 if(at_offset && (PRINT_SECTION))
397                 {
398                     print_tag_address(VALUE_AT_OFFSET,value_offset,indent,prefix);
399                     chpr += printf("# Start of JPEG Thumbnail from MakerNote");
400                     chpr += printf(" length %lu",count);
401                 }
402                 else if(!at_offset && (PRINT_VALUE))
403                 {
404                     if(!(PRINT_OFFSET))
405                         chpr += printf("@%lu:%lu",value_offset,count);
406                     else
407                         chpr += printf(":%lu", count);
408                     if(!(PRINT_VALUE_AT_OFFSET))
409                         chpr += printf(" # UNDEFINED");
410                 }
411                 if((PRINT_SECTION) || (PRINT_SEGMENT))
412                     chpr = newline(chpr);
413                 marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset);
414                 max_offset = process_jpeg_segments(inptr,value_offset,marker,
415                                     count,summary_entry,fulldirname,
416                                     prefix,indent+SMALLINDENT);
417 #if 0
418 /* an alternate place to look */
419                 if((status = jpeg_status(status)) == JPEG_NO_SOI)
420                 {
421                     marker = read_ushort(inptr,TIFF_MOTOROLA,value_offset - fileoffset_base);
422                     max_offset = process_jpeg_segments(inptr,value_offset - fileoffset_base,
423                                             marker,count,summary_entry,
424                                             prefix,indent+SMALLINDENT);
425                     if(max_offset)
426                         value_offset -= fileoffset_base;
427                 }
428 #endif
429                 if(at_offset)
430                 {
431                     if((PRINT_SECTION))
432                     {
433                         if((status = jpeg_status(0) == JPEG_EARLY_EOI))
434                             chpr = newline(chpr);
435                         jpeg_status(status);
436                         print_tag_address(VALUE_AT_OFFSET,value_offset + count - 1,
437                                                     indent,"-");
438                         chpr += printf("# End of JPEG Thumbnail from MakerNote");
439                         chpr += printf(" length %lu",count);
440                         if((PRINT_ENTRY) && !(PRINT_VALUE))
441                             chpr = newline(chpr);
442                     }
443                 }
444                 print_jpeg_status();
445                 if(marker && summary_entry)
446                 {
447                     /* The new one is on the end of the chain         */
448                     if((summary_entry = last_summary_entry(summary_entry)))
449                     {
450                         summary_entry->filesubformat |= FILESUBFMT_MNOTE;
451                         summary_entry->datatype = MAKER_IFD;
452                         summary_entry->subfiletype = THUMBNAIL_TYPE;
453                     }
454                 }
455                 /* make certain we're at the end unless 'inptr' bad   */
456                 clearerr(inptr);
457                 fseek(inptr,value_offset + count,0);
458                 break;
459             case 0x0e00: /* PrintIM (Epson Print Image matching)      */
460                 if(!at_offset && (PRINT_VALUE))
461                 {
462                     if(!(PRINT_OFFSET))
463                         chpr += printf("@%lu:%lu",value_offset,count);
464                     if(!(PRINT_VALUE_AT_OFFSET))
465                         chpr += printf("    # UNDEFINED");
466                     chpr = newline(chpr);
467                 }
468                 process_pim(inptr,byteorder,entry_ptr->value,fileoffset_base,
469                     count,nameoftag,parent_name,prefix,indent);
470                 break;
471             case 0x0010: /* Data                                      */
472                 if(at_offset && (PRINT_ENTRY))
473                 {
474                     print_tag_address(ENTRY,value_offset,indent,prefix);
475                     print_makertagid(entry_ptr,25," : ",make,model);
476                     chpr += printf("length %-9lu # UNDEFINED", count);
477                 }
478                 else if(!at_offset && (PRINT_VALUE))
479                 {
480                     if(!(PRINT_OFFSET))
481                         chpr += printf("@%lu:%lu",value_offset,count);
482                     else
483                         chpr += printf(":%lu",count);
484                     if(!(PRINT_VALUE_AT_OFFSET))
485                         chpr += printf("    # UNDEFINED");
486                 }
487                 if(Max_undefined == 0)
488                 {
489                     if(chpr)
490                         printred(" (not dumped, use -U)");
491                 }
492                 else
493                 {
494                     if((Max_undefined == DUMPALL) || (Max_undefined > count))
495                         dumplength = count;
496                     else
497                         dumplength = Max_undefined;
498                     chpr = newline(chpr);
499                     hexdump(inptr,value_offset,count,dumplength,12,
500                                 indent,SUBINDENT);
501                     chpr = newline(1);
502                 }
503                 /* make certain we're at the end                      */
504                 fseek(inptr,value_offset + count,0);
505                 break;
506             case 0x0097:    /* Color Balance ????                     */
507                 /* Most models show this as an UNDEFINED section; the */
508                 /* SQ provides it as ASCII, with the value an "array" */
509                 /* of ascii strings (including newlines). Can these   */
510                 /* both have the same function?                       */
511                 if(entry_ptr->value_type == UNDEFINED)
512                 {
513 #if 1
514                     if(at_offset && (PRINT_ENTRY)) /* PRINT_VALUE?    */
515                     {
516                         print_tag_address(ENTRY,value_offset,indent,prefix);
517                         print_makertagid(entry_ptr,MAKERTAGWIDTH," = ",make,model);
518                     }
519                     if(at_offset && (PRINT_VALUE) && (PRINT_VALUE_AT_OFFSET))
520                         nikon_colorbalance(inptr,entry_ptr,byteorder,fileoffset_base,indent);
521                     else if(!at_offset && (PRINT_VALUE))
522                     {
523                         if(!(PRINT_OFFSET))
524                             chpr += printf("@%lu:%-9lu",value_offset,count);
525                         else
526                             chpr = printf("length %-9lu", entry_ptr->count);
527                         if(!(PRINT_VALUE_AT_OFFSET))
528                             chpr += printf(" # UNDEFINED");
529                     }
530 #else
531                     print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
532                                         fileoffset_base,fulldirname,prefix,
533                                         indent,make,model,at_offset);
534 #endif
535                 }
536                 else
537                 {
538                     /* This is an unpleasant hack to show all of the  */
539                     /* null-separated strings, even in LIST mode,     */
540                     /* where IGNORE_LENGTH is usually on.             */
541                     orig_print_options = Print_options;
542                     Print_options &=~(PRINT_ASCII_IGNORE_LENGTH);
543                     print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
544                                         fileoffset_base,fulldirname,prefix,
545                                         indent,make,model,at_offset);
546                     Print_options = orig_print_options;
547                 }
548                 break;
549             case 0x008c:    /* NEFDecodeTable1                        */
550             case 0x0096:    /* NEFDecodeTable2                        */
551                 if((summary_entry) && (summary_entry->fileformat == FILEFMT_TIFF))
552                     summary_entry->filesubformat |= FILESUBFMT_NEF;
553                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
554                                     fileoffset_base,fulldirname,prefix,
555                                     indent,make,model,at_offset);
556                 break;
557             default:
558                 print_generic_offset_makervalue(inptr,byteorder,entry_ptr,
559                                     fileoffset_base,fulldirname,prefix,
560                                     indent,make,model,at_offset);
561                 break;
562         }
563         if(fulldirname)
564             free(fulldirname);
565     }
566     setcharsprinted(chpr);
567 }
568 
569 /* The tagname routine is the first place in the code path which      */
570 /* requires knowledge of the note version. If the version is not      */
571 /* given in the model table (e.g. the model is unknown), then switch  */
572 /* code in find_maker_scheme() should have set it. This routine       */
573 /* repeats the check for non-zero noteversion and is prepared to set  */
574 /* the noteversion first time through, but should never need to do    */
575 /* so. Noteversion should always be non-zero; it should be set to -1  */
576 /* if generic processing is required.                                 */
577 
578 char *
maker_nikon_tagname(unsigned short tag,int model)579 maker_nikon_tagname(unsigned short tag,int model)
580 {
581     char *tagname = CNULL;
582     int noteversion = 0;
583 
584     if((noteversion = getnoteversion()) == 0)
585         noteversion = set_nikon_noteversion();
586 
587     switch(noteversion)
588     {
589         case 1:
590             tagname = maker_nikon1_tagname(tag,model);
591             break;
592 
593         case 2:
594             tagname = maker_nikon2_tagname(tag,model);
595             break;
596         default:
597             break;
598     }
599     return(tagname);
600 }
601 
602 
603 /* Tags for the older cameras.                                        */
604 
605 char *
maker_nikon1_tagname(unsigned short tag,int model)606 maker_nikon1_tagname(unsigned short tag,int model)
607 {
608     char *tagname = CNULL;
609 
610     switch(tag)
611     {
612         case 0x0003: tagname = "Quality"; break;
613         case 0x0004: tagname = "ColorMode"; break;
614         case 0x0005: tagname = "ImageAdjustment"; break;
615         case 0x0006: tagname = "ISOSetting"; break;
616         case 0x0007: tagname = "WhiteBalance"; break;
617         case 0x0008: tagname = "Focus"; break;
618         case 0x000a: tagname = "DigitalZoom"; break;
619         case 0x000b: tagname = "LensConverter"; break;
620         case 0x0100: tagname = "JpegThumbnail"; break;
621         case 0x0f00: tagname = "Data"; break;
622             default: break;
623     }
624     setnotetagset(1);
625     return(tagname);
626 }
627 
628 
629 char *
maker_nikon2_tagname(unsigned short tag,int model)630 maker_nikon2_tagname(unsigned short tag,int model)
631 {
632     char *tagname = CNULL;
633 
634     switch(tag)
635     {
636         case 0x0001: tagname = "Version"; break;
637         case 0x0002: tagname = "ISO"; break;
638         case 0x0003: tagname = "ColorMode"; break;
639         case 0x0004: tagname = "Quality"; break;
640         case 0x0005: tagname = "WhiteBalance"; break;
641         case 0x0006: tagname = "ImageSharpening"; break;
642         case 0x0007: tagname = "FocusMode"; break;
643         case 0x0008: tagname = "FlashSetting"; break;
644         case 0x0009: tagname = "FlashType"; break; /* Harvey          */
645 #if 0
646         case 0x000a: break; /* WhiteBal Bias ???                      */
647         case 0x000d: break; /* WhiteBal coeff ???                     */
648         case 0x000e: break; /* ISOSel? ???                            */
649 #endif
650         case 0x000b: tagname = "WhiteBalanceBias"; break;
651         case 0x000c: tagname = "WhiteBalance"; break;
652         case 0x000f: tagname = "ISOSelection"; break;
653         case 0x0010: tagname = "Data"; break;
654         case 0x0011: tagname = "NikonPreviewImage"; break;
655         case 0x0012: tagname = "FlashExposureCompensation*"; break;
656         case 0x0013: tagname = "ISOSetting"; break;
657         case 0x0016: tagname = "ImageBoundary"; break;
658         case 0x0018: tagname = "FlashExposureBracketValue*"; break;
659         case 0x0019: tagname = "ExposureBracketValue"; break;
660 
661         case 0x0080: tagname = "ImageAdjustment"; break;
662         case 0x0081: tagname = "ToneCompensation"; break;
663         case 0x0082: tagname = "LensAdapter"; break;
664         case 0x0083: tagname = "LensType"; break;
665         case 0x0084: tagname = "LensInfo"; break;
666         case 0x0085: tagname = "ManualFocusDistance"; break;
667         case 0x0086: tagname = "DigitalZoom"; break;
668         case 0x0087: tagname = "FlashMode*"; break;
669         case 0x0088: tagname = "AutoFocusArea*"; break;
670         case 0x0089: tagname = "ShootingMode"; break;
671         case 0x008c: tagname = "NEFDecodeTable1"; break;
672         case 0x008d: tagname = "ColorMode"; break;
673         case 0x008f: tagname = "SceneMode"; break;
674         case 0x0090: tagname = "Lightsource"; break;
675         case 0x0092: tagname = "HueAdjustment"; break;
676         case 0x0094: tagname = "Saturation"; break;
677         case 0x0095: tagname = "NoiseReduction"; break;
678         case 0x0096: tagname = "NEFDecodeTable2"; break;
679         case 0x0097: tagname = "ColorBalance**"; break;
680         case 0x0099: tagname = "NEFThumbnailSize*"; break;
681         case 0x00a0: tagname = "SerialNumber"; break;
682         case 0x00a7: tagname = "ShutterCount"; break;
683         case 0x00a9: tagname = "ImageOptimization"; break;
684         case 0x00aa: tagname = "Saturation"; break;
685         case 0x00ab: tagname = "VariProgram"; break;
686 
687         case 0x0100: tagname = "JpegThumbnail"; break;
688         case 0x0e00: tagname = "PrintIM"; break;
689         case 0x0e0e: tagname = "NikonCaptureOffsets"; break;
690         default: break;
691     }
692     setnotetagset(2);
693     return(tagname);
694 }
695 
696 void
nikon1_interpret_value(struct ifd_entry * entry_ptr)697 nikon1_interpret_value(struct ifd_entry *entry_ptr)
698 {
699     int chpr = 0;
700 
701     switch(entry_ptr->tag)
702     {
703         case 0x0003:    /* Quality */
704             print_startvalue();
705             switch(entry_ptr->value)
706             {
707                 case 1:
708                     chpr += printf("VGA Basic - 640x480 (1/16)");
709                     break;
710                 case 2:
711                     chpr += printf("VGA Normal - 640x480 (1/8)");
712                     break;
713                 case 3:
714                     chpr += printf("VGA Fine - 640x480 (1/4)");
715                     break;
716                 case 4:
717                     chpr += printf("XGA Basic - 1024x768 (1/16)");
718                     break;
719                 case 5:
720                     chpr += printf("XGA Normal - 1024x768 (1/8)");
721                     break;
722                 case 6:
723                     chpr += printf("XGA Fine - 1024x768 (1/4)");
724                     break;
725                 case 7:
726                     chpr += printf("SXGA Basic*");
727                     break;
728                 case 8:
729                     chpr += printf("SXGA Normal*");
730                     break;
731                 case 9:
732                     chpr += printf("SXGA Fine*");
733                     break;
734                 case 10:
735                     chpr += printf("Basic - 1600x1200 (1/16)");
736                     break;
737                 case 11:
738                     chpr += printf("Normal - 1600x1200 (1/8)");
739                     break;
740                 case 12:
741                     chpr += printf("Fine - 1600x1200 (1/4)");
742                     break;
743                 case 20:
744                     chpr += printf("Hi - 1600x1200");
745                     break;
746                 default:
747                     printred("undefined");
748                     break;
749             }
750             print_endvalue();
751             break;
752         case 0x0004:    /* Color Mode */
753             print_startvalue();
754             if(entry_ptr->value == 1)
755                 chpr += printf("color");
756             else if(entry_ptr->value == 2)
757                 chpr += printf("monochrome");
758             else
759                 printred("undefined");
760             print_endvalue();
761             break;
762         case 0x0005:    /* Image Adjustment */
763             print_startvalue();
764             /* The data from Crosser's "photopc" conflicts with that  */
765             /* from Tachibanaya for contrast and brightness (they're  */
766             /* swapped). These are Tachibanaya's values. Somebody please  */
767             /* tell me which is right.                                */
768             switch(entry_ptr->value)
769             {
770                 case 0:
771                     chpr += printf("Standard");
772                     break;
773                 case 1:
774                     chpr += printf("Brightness+?"); /* ###%%% Contrast?    */
775                     break;
776                 case 2:
777                     chpr += printf("Brightness-?");  /* ###%%% Contrast?   */
778                     break;
779                 case 3:
780                     chpr += printf("Contrast+?"); /* ###%%% Brightness?    */
781                     break;
782                 case 4:
783                     chpr += printf("Contrast-?"); /* ###%%% Brightness?    */
784                     break;
785                 case 5:
786                     /* Is this right?                                 */
787                     chpr += printf("Auto?");
788                     break;
789                 default:
790                     printred("undefined");
791                     break;
792             }
793             print_endvalue();
794             break;
795         case 0x0006:    /* CCD Sensitivity (ISO) */
796             print_startvalue();
797             switch(entry_ptr->value)
798             {
799                 case 0:
800                     chpr += printf("80");
801                     break;
802                 case 2:
803                     chpr += printf("160");
804                     break;
805                 case 4:
806                     chpr += printf("320");
807                     break;
808                 case 5:
809                     chpr += printf("100");
810                     break;
811                 default:
812                     printred("undefined");
813                     break;
814             }
815             print_endvalue();
816             break;
817         case 0x0007:    /* White Balance */
818             print_startvalue();
819             /* These values, taken from "photopc", conflict with      */
820             /* values given by Tachibanaya                            */
821             switch(entry_ptr->value)
822             {
823                 case 0:
824                     chpr += printf("Auto");
825                     break;
826                 case 1:
827                     chpr += printf("Preset");
828                     break;
829                 case 2:
830                     chpr += printf("Daylight");
831                     break;
832                 case 3:
833                     chpr += printf("Incandescent");
834                     break;
835                 case 4:
836                     chpr += printf("Fluorescent");
837                     break;
838                 case 5:
839                     chpr += printf("Cloudy");
840                     break;
841                 case 6:
842                     chpr += printf("Flash");
843                     break;
844                 default:
845                     printred("undefined");
846                     break;
847             }
848             print_endvalue();
849             break;
850         case 0x000b:    /* Lens Converter */
851             print_startvalue();
852             if(entry_ptr->value == 0)
853                 chpr += printf("none");
854             else if(entry_ptr->value == 1)
855                 chpr += printf("fisheye");
856             else
857                 printred("undefined");
858             print_endvalue();
859             break;
860 
861         default:
862             break;
863     }
864     setcharsprinted(chpr);
865 }
866 
867 void
nikon2_interpret_value(struct ifd_entry * entry_ptr)868 nikon2_interpret_value(struct ifd_entry *entry_ptr)
869 {
870     int chpr = 0;
871 
872     switch(entry_ptr->tag)
873     {
874         case 0x0002:    /* CCD Sensitivity (ISO) */
875             print_startvalue();
876             if(entry_ptr->value & 0xffff)
877                 chpr += printf("%u",(unsigned short)(entry_ptr->value & 0xffff));
878             else if((entry_ptr->value >> 16) & 0xffff)
879                 chpr += printf("%u",(unsigned short)((entry_ptr->value >> 16) & 0xffff));
880             else
881                 chpr += printf("Auto");
882             print_endvalue();
883             break;
884         case 0x000b:
885         case 0x000d:
886         case 0x000e:
887         case 0x0011:
888         case 0x008a:
889         case 0x008b:
890         case 0x0092:
891         case 0x0094:
892             /*
893             print_startvalue();
894             printred("unknown");
895             print_endvalue();
896             */
897             break;
898         case 0x0087:    /* Flash Used                                 */
899             print_startvalue();
900             switch(entry_ptr->value)
901             {
902                 case 0: chpr += printf("did not fire"); break;
903                 case 8: chpr += printf("fired, commander mode"); break;
904                 case 9: chpr += printf("fired, TTL mode"); break;
905                 default: printred("undefined"); break;
906             }
907             print_endvalue();
908             break;
909         case 0x0088:    /* Auto Focus Position                    */
910 #if 0
911             print_startvalue();
912             /* updated from PHP Metadata Toolkit & exiftool           */
913             /* ###%%% don't think these are right:                    */
914             /* The two sources conflict.                              */
915             /* AFPosition can be tied to metering, which isn't        */
916             /* mentioned... There are 4 bytes here that might have    */
917             /* significance. Hold off on this. Asterisk the tag.      */
918             switch(entry_ptr->value & 0xff)
919             {
920                 case 0:
921                     chpr += printf("Single area - ");
922                     break;
923                 case 0x1:
924                     chpr += printf("Dynamic area - ");
925                     break;
926                 case 0x2:
927                     chpr += printf("Closest subject - ");
928                     break;
929                 default:
930                     printred("undefined area -");
931                     break;
932             }
933 #endif
934             /* It appears that this byte describes autofocus          */
935             /* position.                                              */
936             /* It is not clear what the other bytes are for.          */
937             /* Possibilities are:                                     */
938             /*     metering lock to the focus area                    */
939             /*     auto vs manual focus area select or "off"          */
940             /*     continuous AF vs single AF                         */
941             /*     auto focus on closest subject                      */
942             /*     actual area used                                   */
943             /* ...what *is* "dynamic area"?                           */
944             print_startvalue();
945             switch((entry_ptr->value >> 8) & 0xff)
946             {
947                 case 0:
948                     chpr += printf("Center");
949                     break;
950                 case 0x1:
951                     chpr += printf("Top");
952                     break;
953                 case 0x2:
954                     chpr += printf("Bottom");
955                     break;
956                 case 0x3:
957                     chpr += printf("Left");
958                     break;
959                 case 0x4:
960                     chpr += printf("Right");
961                     break;
962                 default:
963                     printred("undefined");
964                     break;
965             }
966             print_endvalue();
967             break;
968         case 0x0089:    /* Shooting Mode */
969             print_startvalue();
970             switch(entry_ptr->value & 0x3)
971             {
972                 case 0: chpr += printf("single frame"); break;
973                 case 1: chpr += printf("continuous"); break;
974                 case 2: chpr += printf("timer"); break;
975                 case 3: chpr += printf("remote timer?"); break;
976                 case 4: chpr += printf("remote?"); break;
977                 default: chpr += printf("(undefined)"); break;
978             }
979             if(entry_ptr->value & 0x8)
980                 chpr += printf(", bracketing on");
981             else
982                 chpr += printf(", bracketing off");
983             if(entry_ptr->value & 0x20)
984                 chpr += printf(", WB bracketing on");
985             else
986                 chpr += printf(", WB bracketing off");
987             print_endvalue();
988             break;
989         default:
990             break;
991     }
992     setcharsprinted(chpr);
993 }
994 
995 void
nikon2_interpret_offset_makervalue(FILE * inptr,unsigned short byteorder,struct ifd_entry * entry_ptr,unsigned long fileoffset_base,char * parent_name,char * nameoftag,int indent)996 nikon2_interpret_offset_makervalue(FILE *inptr,unsigned short byteorder,
997                     struct ifd_entry *entry_ptr,unsigned long fileoffset_base,
998                     char *parent_name,char *nameoftag,int indent)
999 {
1000     unsigned long offset;
1001     int chpr = 0;
1002     char *fullnameoftag = CNULL;
1003     int entrywidth;
1004     double minfl,maxfl,minmaxap,maxmaxap;
1005     unsigned long num,denom;
1006 
1007     if(entry_ptr && (PRINT_VALUE))
1008     {
1009         fullnameoftag = splice(parent_name,".",nameoftag);
1010         offset = entry_ptr->value + fileoffset_base;
1011         switch(entry_ptr->tag)
1012         {
1013             case 0x0084:
1014                 /* Assume no read errors here, since it's been    */
1015                 /* read once before; if there are, we'll hear     */
1016                 /* about it (but do nothing).                     */
1017                 num = read_ulong(inptr,byteorder,offset);
1018                 denom = read_ulong(inptr,byteorder,HERE);
1019                 if(num == 0UL)
1020                     minfl = 0.0;
1021                 else
1022                     minfl = (double)((double)num/(double)denom);
1023                 num = read_ulong(inptr,byteorder,HERE);
1024                 denom = read_ulong(inptr,byteorder,HERE);
1025                 if(num == 0UL)
1026                     maxfl = 0.0;
1027                 else
1028                     maxfl = (double)((double)num/(double)denom);
1029                 num = read_ulong(inptr,byteorder,HERE);
1030                 denom = read_ulong(inptr,byteorder,HERE);
1031                 if(num == 0UL)
1032                     minmaxap = 0.0;
1033                 else
1034                     minmaxap = (double)((double)num/(double)denom);
1035                 num = read_ulong(inptr,byteorder,HERE);
1036                 denom = read_ulong(inptr,byteorder,HERE);
1037                 if(num == 0UL)
1038                     maxmaxap = 0.0;
1039                 else
1040                     maxmaxap = (double)((double)num/(double)denom);
1041 
1042                 if((PRINT_SECTION))
1043                 {
1044                     chpr = printf(" = {");
1045                     chpr = newline(chpr);
1046                     indent += MEDIUMINDENT + MAKERTAGWIDTH + 3;
1047                     print_tag_address(ENTRY,offset,indent,"@");
1048                 }
1049                 else
1050                 {
1051                     chpr = newline(chpr);
1052                     print_tag_address(ENTRY,offset,indent,"@");
1053                 }
1054 
1055                 if(PRINT_ENTRY)
1056                 {
1057                     entrywidth = sizeof("MaxApertureAtMinFocalLength");
1058                     if((PRINT_TAGINFO))
1059                     {
1060                         if((PRINT_LONGNAMES))
1061                             chpr += printf("%s.",fullnameoftag);
1062                         chpr += printf("%-*.*s",entrywidth,entrywidth,"MinFocalLength");
1063                     }
1064                     if((PRINT_VALUE))
1065                     {
1066                         print_startvalue();
1067                         printf("%.0f mm",minfl);
1068                         print_endvalue();
1069                         chpr = newline(chpr);
1070                     }
1071                     print_tag_address(ENTRY,offset + 8,indent,"@");
1072                     if((PRINT_TAGINFO))
1073                     {
1074                         if((PRINT_LONGNAMES))
1075                             chpr += printf("%s.",fullnameoftag);
1076                         chpr += printf("%-*.*s",entrywidth,entrywidth,"MaxFocalLength");
1077                     }
1078                     if((PRINT_VALUE))
1079                     {
1080                         print_startvalue();
1081                         chpr += printf("%.0f mm",maxfl);
1082                         print_endvalue();
1083                         chpr = newline(chpr);
1084                     }
1085                     print_tag_address(ENTRY,offset + 16,indent,"@");
1086                     if((PRINT_TAGINFO))
1087                     {
1088                         if((PRINT_LONGNAMES))
1089                             chpr += printf("%s.",fullnameoftag);
1090                         chpr += printf("%-*.*s",entrywidth,entrywidth,
1091                                                 "MaxApertureAtMinFocalLength");
1092                     }
1093                     if((PRINT_VALUE))
1094                     {
1095                         /* ###%%% APEX? */
1096                         chpr += printf(" = %3.2f APEX",minmaxap);
1097                         minmaxap = pow(2.0,minmaxap/2.0);
1098                         print_startvalue();
1099                         chpr += printf("f%.1f",minmaxap);
1100                         print_endvalue();
1101                         chpr = newline(chpr);
1102                     }
1103                     print_tag_address(ENTRY,offset + 24,indent,"@");
1104                     if((PRINT_TAGINFO))
1105                     {
1106                         if((PRINT_LONGNAMES))
1107                             chpr += printf("%s.",fullnameoftag);
1108                         chpr += printf("%-*.*s",entrywidth,entrywidth,
1109                                                 "MaxApertureAtMaxFocalLength");
1110                     }
1111                     if((PRINT_VALUE))
1112                     {
1113                         /* ###%%% APEX? */
1114                         chpr += printf(" = %3.2f APEX",maxmaxap);
1115                         maxmaxap = pow(2.0,maxmaxap/2.0);
1116                         print_startvalue();
1117                         chpr += printf("f%.1f",maxmaxap);
1118                         print_endvalue();
1119                         if(PRINT_SECTION)
1120                         {
1121                             chpr = newline(chpr);
1122                             print_tag_address(ENTRY,offset + 31,0,"@");
1123                             putindent(indent - MEDIUMINDENT);
1124                             chpr = printf("}");
1125                         }
1126                     }
1127                 }
1128                 break;
1129             default:
1130                 break;
1131         }
1132     }
1133     setcharsprinted(chpr);
1134 }
1135 
1136 /* ###%%% Phil Harvey's ExifTool pages seem to indicate that these are tables of
1137 'rational16' values after an initial 4 character identifier, except that the values
1138 for identifier 0100 are 'int16'.  I dunno; the values I see do not look reasonable
1139 for color balance values (i.e. 'Infinity', '17.2143', ...).  There must be more
1140 than he's saying.
1141 
1142 Exiftool picks out two values at model-dependent offsets for red and blue balance,
1143 but doesn't address the rest of the section.  Print those values here, then call
1144 dumpsection so that users can look at the rest.
1145 */
1146 
1147 void
nikon_colorbalance(FILE * inptr,struct ifd_entry * entry_ptr,unsigned short byteorder,unsigned long fileoffset_base,int indent)1148 nikon_colorbalance(FILE *inptr,struct ifd_entry *entry_ptr,unsigned short byteorder,
1149                                             unsigned long fileoffset_base,int indent)
1150 {
1151     unsigned long offset;
1152     unsigned short numerator,denominator;
1153     double value;
1154     int chpr = 0;
1155     int unknown = 0;
1156     char *id;
1157 
1158     if(entry_ptr && (PRINT_VALUE))
1159     {
1160         offset = entry_ptr->value + fileoffset_base;
1161 #if 1
1162         id = read_string(inptr,offset,4);
1163         chpr += printf("'ID:");
1164         show_string(id,4,1);
1165         if(strncmp(id,"0100",4) == 0)
1166             offset += 72;
1167         else if(strncmp(id,"0102",4) == 0)
1168             offset += 10;
1169         else if(strncmp(id,"0103",4) == 0)
1170             offset += 20;
1171         else
1172             ++unknown;
1173         if(!unknown)
1174         {
1175             if((PRINT_SECTION))
1176             {
1177                 indent += MAKERTAGWIDTH + 3;
1178                 chpr += printf("' = {");
1179                 chpr = newline(chpr);
1180                 print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"?");
1181                 chpr += printf("RedBalance**  = ");
1182                 numerator = read_ushort(inptr,byteorder,offset);
1183                 offset += 2;
1184                 if(strncmp(id,"0100",4))
1185                 {
1186                     denominator = read_ushort(inptr,byteorder,offset);
1187                     offset += 2;
1188                 }
1189                 else
1190                     denominator = 256;
1191                 value = (double)numerator / (double)denominator;
1192                 chpr += printf("%.6f (%u/%u)",value,numerator,denominator);
1193                 chpr = newline(chpr);
1194 
1195                 print_tag_address(ENTRY,offset,indent + MEDIUMINDENT,"?");
1196                 chpr += printf("BlueBalance** = ");
1197                 numerator = read_ushort(inptr,byteorder,offset);
1198                 offset += 2;
1199                 if(strncmp(id,"0100",4))
1200                 {
1201                     denominator = read_ushort(inptr,byteorder,offset);
1202                     offset += 2;
1203                 }
1204                 else
1205                     denominator = 256;
1206                 value = (double)numerator / (double)denominator;
1207                 chpr += printf("%.6f (%u/%u)",value,numerator,denominator);
1208                 chpr = newline(chpr);
1209                 print_tag_address(ENTRY,offset + entry_ptr->count - 1,indent,"?");
1210                 chpr += printf("} = {");
1211                 indent -= MAKERTAGWIDTH + 3;
1212             }
1213             chpr = newline(chpr);
1214         }
1215         else
1216         {
1217             chpr += printf(" = unknown = {");
1218             chpr = newline(chpr);
1219         }
1220         offset = entry_ptr->value + fileoffset_base;
1221         PUSHCOLOR(RED);
1222         dumpsection(inptr,offset,entry_ptr->count,indent);
1223         POPCOLOR();
1224         print_tag_address(ENTRY,offset + entry_ptr->count - 1,indent,"?");
1225         chpr += printf("}");
1226     }
1227 #else
1228 /* This just prints everything after the idstring as short rationals, */
1229 /* in the same fashion as print_ushort();                             */
1230         count = entry_ptr->count / 4;   /* two unsigned shorts        */
1231         print_ascii(inptr,4,offset);
1232         count--;
1233         offset += 4;
1234         chpr = newline(chpr);
1235         for(i = 0; i < count; ++i)
1236         {
1237             int rowlength;
1238             if((count -i) >= 4)
1239                 rowlength = 4;
1240             else
1241                 rowlength = count - i;
1242             print_tag_address(ENTRY,offset,indent,"?");
1243             for(j = 0; j < rowlength; ++j,++i)
1244             {
1245                 numerator = read_ushort(inptr,byteorder,offset);
1246                 denominator = read_ushort(inptr,byteorder,HERE);
1247                 offset += 4;
1248                 if(j)
1249                     chpr += printf(", ");
1250                 if(j == 2)
1251                     chpr += printf("    ");
1252                 if(numerator == 0)
1253                     chpr += printf("0     ");
1254                 else if(denominator == 0)
1255                     chpr += printf("Inf   ");
1256                 else
1257                 {
1258                     value = (double)numerator / (double)denominator;
1259                     chpr += printf("%.4f",value);
1260                 }
1261             }
1262             chpr = newline(chpr);
1263         }
1264     }
1265     if(Max_undefined > 0)
1266     {
1267         unsigned long dumplength;
1268 
1269         offset = entry_ptr->value + fileoffset_base;
1270         if((Max_undefined == DUMPALL) || (Max_undefined > entry_ptr->count))
1271             dumplength = entry_ptr->count;
1272         else
1273             dumplength = Max_undefined;
1274         chpr = newline(chpr);
1275         hexdump(inptr,offset,entry_ptr->count,dumplength,16,
1276                     4,SUBINDENT);
1277         chpr = newline(1);
1278     }
1279 #endif
1280     setcharsprinted(chpr);
1281 }
1282 
1283 /* Mark items (usually LONG) which should be treated as offsets.      */
1284 
1285 int
maker_nikon_value_is_offset(struct ifd_entry * entry_ptr,int model)1286 maker_nikon_value_is_offset(struct ifd_entry *entry_ptr,int model)
1287 {
1288     int is_offset = 0;
1289 
1290     /* There is currently no need for a switch on noteversion         */
1291     if(entry_ptr)
1292     {
1293         switch(entry_ptr->tag)
1294         {
1295             case 0x0011: is_offset = 1; break;
1296             case 0x0097: is_offset = 1; break;
1297             case 0x0100: is_offset = 1; break;
1298             default: break;
1299         }
1300     }
1301     return(is_offset);
1302 }
1303