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