1 /* exif_nikon.c
2 
3 Copyright (C) 2012      Dennis Real.
4 
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to
7 deal in the Software without restriction, including without limitation the
8 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 sell copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11 
12 The above copyright notice and this permission notice shall be included in
13 all copies of the Software and its documentation and acknowledgment shall be
14 given in the documentation and software packages that this Software was
15 used.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 */
25 
26 #ifdef HAVE_LIBEXIF
27 
28 #include <stdio.h>
29 #include <libexif/exif-data.h>
30 
31 #include "feh.h"
32 #include "debug.h"
33 #include "exif.h"
34 #include "exif_nikon.h"
35 
36 
37 /* Flash control mode */
38 /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
39 #define EXN_FLASH_CONTROL_MODES_MAX 9
40 char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off",
41                                        "iTTL-BL", "iTTL", "Auto Aperture",
42                                        "Automatic", "GN (distance priority)",
43                                        "Manual", "Repeating Flash",
44                                        "N/A" /* "N/A" is not a nikon setting */
45                                        };
46 
47 #define EXN_FLASH_CONTROL_MODE_MASK 0x7F
48 
49 
50 /* AFInfo2 */
51 /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#AFInfo2 */
52 #define EXN_CONTRAST_DETECT_AF_MAX 2
53 char *EXN_NikonContrastDetectAF[EXN_CONTRAST_DETECT_AF_MAX] = {"Off", "On"};
54 
55 /* AFArea Mode for ContrastDetectAF Off */
56 #define EXN_AF_AREA_MODE_P_MAX 13
57 char *EXN_NikonAFAreaModePhase[EXN_AF_AREA_MODE_P_MAX] = {
58   "Single Area", "Dynamic Area", "Dynamic Area (closest subject)",
59   "Group Dynamic ", "Dynamic Area (9 points) ", "Dynamic Area (21 points)",
60   "Dynamic Area (51 points) ", "Dynamic Area (51 points, 3D-tracking)",
61   "Auto-area", "Dynamic Area (3D-tracking)", "Single Area (wide)",
62   "Dynamic Area (wide)", "Dynamic Area (wide, 3D-tracking)"};
63 
64 /* AFArea Mode for ContrastDetectAF On */
65 #define EXN_AF_AREA_MODE_C_MAX 5
66 char *EXN_NikonAFAreaModeContr[EXN_AF_AREA_MODE_C_MAX] = {
67   "Contrast-detect",
68   "Contrast-detect (normal area)",
69   "Contrast-detect (wide area)",
70   "Contrast-detect (face priority)",
71   "Contrast-detect (subject tracking)"};
72 
73 #define EXN_PHASE_DETECT_AF_MAX 4
74 char *EXN_NikonPhaseDetectAF[EXN_PHASE_DETECT_AF_MAX] = {"Off", "On (51-point)",
75                                                          "On (11-point)", "On (39-point)"};
76 
77 /* PrimaryAFPoint and AFPointsUsed only valid with PhaseDetectAF == On */
78 
79 #define EXN_PRIM_AF_PT_51_MAX 52
80 char * EXN_Prim_AF_Pt_51[EXN_PRIM_AF_PT_51_MAX] = {"(none)", "C6 (Center)", "B6", "A5",
81   "D6", "E5", "C7", "B7", "A6", "D7", "E6", "C5", "B5", "A4", "D5", "E4", "C8", "B8",
82   "A7", "D8", "E7", "C9", "B9", "A8", "D9", "E8", "C10", "B10", "A9", "D10", "E9",
83   "C11", "B11", "D11", "C4", "B4", "A3", "D4", "E3", "C3", "B3", "A2", "D3", "E2",
84   "C2", "B2", "A1", "D2", "E1", "C1", "B1", "D1"};
85 
86 #define EXN_PRIM_AF_PT_11_MAX 12
87 char * EXN_Prim_AF_Pt_11[EXN_PRIM_AF_PT_11_MAX] = {"(none)", "Center", "Top", "Bottom",
88   "Mid-left", "Upper-left", "Lower-left", "Far Left", "Mid-right", "Upper-right",
89   "Lower-right",  "Far Right"};
90 
91 #define EXN_PRIM_AF_PT_39_MAX 40
92 char * EXN_Prim_AF_Pt_39[EXN_PRIM_AF_PT_39_MAX] = {"(none)", "C6 (Center)", "B6", "A2",
93   "D6", "E2", "C7", "B7", "A3", "D7", "E3", "C5", "B5", "A1", "D5", "E1", "C8", "B8",
94   "D8", "C9", "B9", "D9", "C10", "B10", "D10", "C11", "B11", "D11", "C4", "B4", "D4",
95   "C3", "B3", "D3", "C2", "B2", "D2", "C1", "B1", "D1"};
96 
97 
98 #define EXN_PIC_CTRL_ADJ_MAX 3
99 char * EXN_Pic_Ctrl_Adj[EXN_PIC_CTRL_ADJ_MAX] = {"Default Settings",
100                                                  "Quick Adjust",
101                                                  "Full Control"};
102 
103 
104 
105 static void exn_get_prim_af_pt(unsigned int phasedetectaf,
106                                unsigned int primafpt,
107                                char * buffer,
108                                unsigned int maxsize);
109 static void exn_get_flash_output(unsigned int flashoutput, char * buffer, unsigned int maxsize);
110 static void exn_get_mnote_nikon_18(ExifData *ed, char * buffer, unsigned int maxsize);
111 static void exn_get_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize);
112 static void exn_get_mnote_nikon_35(ExifData *ed, char * buffer, unsigned int maxsize);
113 static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize);
114 static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize);
115 
116 
117 
118 /* get primary AF point */
exn_get_prim_af_pt(unsigned int phasedetectaf,unsigned int primafpt,char * buffer,unsigned int maxsize)119 static void exn_get_prim_af_pt(unsigned int phasedetectaf,
120                                unsigned int primafpt,
121                                char * buffer,
122                                unsigned int maxsize)
123 {
124 
125   switch(phasedetectaf)
126   {
127     case 0:
128     {
129       /* phasedetect not used. should not happen */
130       snprintf(buffer, maxsize, "FAIL");
131       return;
132     }
133     break;
134     case 1:
135     {
136       /* 51 pt */
137       if ( primafpt < EXN_PRIM_AF_PT_51_MAX )
138       {
139         snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_51[primafpt]);
140       }
141       return;
142     }
143     break;
144     case 2:
145     {
146       /* 11 pt */
147       if ( primafpt < EXN_PRIM_AF_PT_11_MAX )
148       {
149         snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_11[primafpt]);
150       }
151       return;
152     }
153     break;
154     case 3:
155     {
156       /* 39 pt */
157       if ( primafpt < EXN_PRIM_AF_PT_39_MAX )
158       {
159         snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_39[primafpt]);
160       }
161       return;
162     }
163     break;
164     default:
165     {
166       snprintf(buffer, maxsize, "?");
167       return;
168     }
169     break;
170 
171   }
172 
173 }
174 
175 
176 
177 /* get flash output power (for FlashInfo010x) */
exn_get_flash_output(unsigned int flashoutput,char * buffer,unsigned int maxsize)178 static void exn_get_flash_output(unsigned int flashoutput, char * buffer, unsigned int maxsize)
179 {
180 
181   if ( flashoutput == 0 )
182   {
183     /* full power */
184     snprintf(buffer, maxsize, "Full");
185   }
186   else
187   {
188     if ( (flashoutput % 6) == 0 )
189     {
190       /* value is a power of 2 */
191       snprintf(buffer, maxsize, "1/%d", 1<<(flashoutput/6));
192     }
193     else
194     {
195       /* something uneven...ugly. maybe introduce pow() function from libm later */
196       snprintf(buffer, maxsize, "1/2^(%f)", ((float)flashoutput)/6.0);
197     }
198   }
199 }
200 
201 
202 
203 /* get ActiveD-Lighting (18) info */
exn_get_mnote_nikon_18(ExifData * ed,char * buffer,unsigned int maxsize)204 static void exn_get_mnote_nikon_18(ExifData *ed, char * buffer, unsigned int maxsize)
205 {
206 
207   char buf[EXIF_STD_BUF_LEN];
208   float data = 0;
209 
210   buf[0] = '\0';
211   exif_get_mnote_tag(ed, 18, buf, sizeof(buf));
212 
213   sscanf(buf, "Flash Exposure Compensation: %f", &data); /* libexif buggy here. fix conversion */
214 
215   snprintf(buffer, maxsize, "FlashExposureCompensation: %+.1f EV\n", ((float)((signed char)round(data*6.0))) / 6.0 );
216 }
217 
218 
219 
220 /* get ActiveD-Lighting (34) info */
exn_get_mnote_nikon_34(ExifData * ed,char * buffer,unsigned int maxsize)221 static void exn_get_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize)
222 {
223   char buf[EXIF_STD_BUF_LEN];
224   unsigned int data = 0;
225   char *answer;
226 
227   buf[0] = '\0';
228   exif_get_mnote_tag(ed, 34, buf, sizeof(buf));
229   sscanf(buf, "(null): %u", &data); 	/* not directly supported by libexif yet */
230 
231   switch(data)
232   {
233     case 0:
234     {
235       answer = "Off";
236     }
237     break;
238     case 1:
239     {
240       answer = "Low";
241     }
242     break;
243     case 3:
244     {
245       answer = "Normal";
246     }
247     break;
248     case 5:
249     {
250       answer = "High";
251     }
252     break;
253     case 7:
254     {
255       answer = "Extra High";
256     }
257     break;
258     case 65535:
259     {
260       answer = "Auto";
261     }
262     break;
263     default:
264     {
265       answer = "N/A"; /* this is not a nikon value */
266     }
267 
268   }
269 
270   snprintf(buffer, maxsize, "Active D-Lightning: %s\n", answer);
271 
272 }
273 
274 
275 
276 /* get nikon PictureControlData (35) info */
exn_get_mnote_nikon_35(ExifData * ed,char * buffer,unsigned int maxsize)277 static void exn_get_mnote_nikon_35(ExifData *ed, char * buffer, unsigned int maxsize)
278 {
279   char buf[EXIF_STD_BUF_LEN];
280   char picturecontrolname[EXIF_STD_BUF_LEN];
281   char picturecontrolbase[EXIF_STD_BUF_LEN];
282   unsigned int version = 0;
283   unsigned int length = 0;
284   unsigned int piccontroladj = 0;
285   unsigned int piccontrolquickadj = 0;
286   unsigned int sharpness = 0;
287   unsigned int contrast = 0;
288   unsigned int brightness = 0;
289   unsigned int saturation = 0;
290   unsigned int hueadjustment = 0;
291   unsigned int i, j;
292 
293   /* libexif does not support PictureControlData 35 yet. so we have to parse the debug data :-( */
294   buf[0] = '\0';
295   exif_get_mnote_tag(ed, 35, buf, sizeof(buf));
296 
297   sscanf(buf, "(null): %u bytes unknown data: 303130%02X%40s%40s%*8s%02X%02X%02X%02X%02X%02X%02X",
298          &length, &version, &picturecontrolname[0], &picturecontrolbase[0],
299          &piccontroladj, &piccontrolquickadj,
300          &sharpness, &contrast, &brightness, &saturation, &hueadjustment
301         );
302 
303   /* printf("--%s %d-%d-\n", buf, version, piccontroladj); */
304 
305   for ( i=0; i<40; i++ )
306   {
307     sscanf(&picturecontrolname[2*i], "%2X", &j);
308     picturecontrolname[i] = j;
309     sscanf(&picturecontrolbase[2*i], "%2X", &j);
310     picturecontrolbase[i] = j;
311 
312   }
313   exif_trim_spaces(picturecontrolname);
314   exif_trim_spaces(picturecontrolbase);
315 
316   if ( ((length == 58) && (version == '0'))
317        && (piccontroladj < EXN_PIC_CTRL_ADJ_MAX)
318 
319      )
320   {
321     snprintf(buffer, maxsize,
322              "PictCtrlData: Name: %s; Base: %s; CtrlAdj: %s; Quick: %d; Shrp: %d; Contr: %d; Brght: %d; Sat: %d; Hue: %d\n",
323               picturecontrolname, picturecontrolbase,
324              EXN_Pic_Ctrl_Adj[piccontroladj], piccontrolquickadj,
325              sharpness, contrast, brightness, saturation, hueadjustment);
326   }
327 
328 }
329 
330 
331 
332 
333 /* get nikon Flash info: control mode (168) info */
exn_get_mnote_nikon_168(ExifData * ed,char * buffer,unsigned int maxsize)334 static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize)
335 {
336   char buf[EXIF_STD_BUF_LEN];
337   unsigned int version = 0;
338   unsigned int length = 0;
339   unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
340   unsigned int flashoutput = 0;
341   unsigned int externalflashflags = 0;
342   unsigned int flashcompensation = 0;
343 
344   /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
345   buf[0] = '\0';
346   exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
347   sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*8s%02X%02X%02X%02X", &length, &version, &externalflashflags, &exn_fcm, &flashoutput, &flashcompensation);
348   exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;
349 
350   /* printf("%s - %d %d %d %d\n", buf, externalflashflags, exn_fcm, flashoutput, (signed char)flashcompensation); */
351 
352   if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
353        && ( ((length == 22) && (version == '3'))      /* Nikon FlashInfo0103 */
354             || ((length == 22) && (version == '4'))   /* Nikon FlashInfo0104 */
355             || ((length == 21) && (version == '2'))   /* Nikon FlashInfo0102 */
356             || ((length == 19) && (version == '0'))   /* Nikon FlashInfo0100 */
357           )
358      )
359   {
360 
361     buf[0] = '\0';
362     exn_get_flash_output(flashoutput, buf, EXIF_STD_BUF_LEN);
363     snprintf(buffer, maxsize, "NikonFlashControlMode: %s (Power: %s)\n", EXN_NikonFlashControlModeValues[exn_fcm], buf);
364 
365     /* External Flash Flags. Not as useful as expected. Not used (yet). */
366     /* if ( (externalflashflags & (1<<2)) ) -> Bounce Flash */
367     /* if ( (externalflashflags & (1<<4)) ) -> Wide Flash Adapter */
368     /* if ( (externalflashflags & (1<<5)) ) -> Dome Diffusor */
369 
370   }
371 
372 }
373 
374 
375 
376 /* get nikon AFInfo2 (183) info */
exn_get_mnote_nikon_183(ExifData * ed,char * buffer,unsigned int maxsize)377 static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize)
378 {
379   char buf[EXIF_STD_BUF_LEN];
380   unsigned int contrastdetectaf = 0;
381   unsigned int afareamode = 0;
382   unsigned int phasedetectaf = 0;
383   unsigned int primaryafpoint = 0;
384   unsigned int version = 0;
385   unsigned int length = 0;
386 
387   /* AFInfo2 */
388   /* libexif does not support AFInfo2 183 yet. so we have to parse the debug data :-( */
389   buf[0] = '\0';
390   exif_get_mnote_tag(ed, 183, buf, sizeof(buf));
391   sscanf(buf, "(null): %u bytes unknown data: 303130%02X%02X%02X%02X%02X", &length, &version,
392     &contrastdetectaf,
393     &afareamode,
394     &phasedetectaf,
395     &primaryafpoint
396     );
397 
398 
399   if ( ((length == 30) && (version == '0'))
400        && (contrastdetectaf < EXN_CONTRAST_DETECT_AF_MAX)
401        && (phasedetectaf < EXN_PHASE_DETECT_AF_MAX)
402        )
403   {
404     if ( (contrastdetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_C_MAX) )
405     {
406       /* Contrast AF (live view) */
407       snprintf(buffer, maxsize,
408                "ContrastDetectAF: %s; AFAreaMode: %s\n",
409                EXN_NikonContrastDetectAF[contrastdetectaf],
410                EXN_NikonAFAreaModeContr[afareamode]);
411 
412     }
413     else if ( (phasedetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_P_MAX) )
414     {
415       /* Phase AF */
416       buf[0] = '\0';
417       exn_get_prim_af_pt(phasedetectaf, primaryafpoint, buf, EXIF_STD_BUF_LEN);
418 
419       snprintf(buffer, maxsize,
420                "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n",
421                EXN_NikonPhaseDetectAF[phasedetectaf],
422                EXN_NikonAFAreaModePhase[afareamode],
423                buf
424                );
425     }
426 
427   }
428 }
429 
430 
431 
432 /* get interesting nikon maker note tags in readable form */
exn_get_mnote_nikon_tags(ExifData * ed,unsigned int tag,char * buffer,unsigned int maxsize)433 void exn_get_mnote_nikon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize)
434 {
435   char buf[EXIF_STD_BUF_LEN];
436 
437   buf[0] = '\0';
438   exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
439   exif_trim_spaces(buf);
440 
441   switch(tag)
442   {
443     /* show only if flash was used */
444     case 8:   /* Flash Setting */
445     case 9:   /* Flash Mode */
446     case 135: /* Flash used */
447     {
448       if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
449       {
450         /* show extended flash info only if flash was fired */
451         exif_get_mnote_tag(ed, tag, buffer, maxsize);
452       }
453     }
454     break;
455 
456     case 18:  /* FlashExposureComp */
457     {
458       if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
459       {
460         /* show only if flash was fired */
461         exn_get_mnote_nikon_18(ed, buffer, maxsize);
462       }
463     }
464     break;
465 
466     case 34:
467     {
468       /* ActiveD-Lighting */
469       exn_get_mnote_nikon_34(ed, buffer, maxsize);
470     }
471     break;
472 
473     case 35:
474     {
475       /* PictureControlData */
476       exn_get_mnote_nikon_35(ed, buffer, maxsize);
477     }
478     break;
479 
480     case 168:
481     {
482       /* Flash info: control mode */
483       if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
484       {
485         /* show extended flash info only if flash was fired */
486         exn_get_mnote_nikon_168(ed, buffer, maxsize);
487       }
488     }
489     break;
490 
491     case 183:
492     {
493       /* AFInfo 2 */
494       exn_get_mnote_nikon_183(ed, buffer, maxsize);
495     }
496     break;
497 
498     default:
499     {
500       /* normal makernote tags without special treatment */
501       exif_get_mnote_tag(ed, tag, buffer, maxsize);
502     }
503     break;
504   }
505 
506 
507   return;
508 }
509 
510 #endif
511