Commit e401bd9c authored by Dennis Real's avatar Dennis Real
Browse files

1. Own module for nikon maker notes

2. Support for AFInfo2
parent 39cbd1ed
Loading
Loading
Loading
Loading
+23 −76
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdio.h>
#include <string.h>
#include <libexif/exif-data.h>
#include <limits.h>

#include "feh.h"
#include "options.h"
@@ -36,15 +37,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "exif_nikon.h"
#include "exif_cfg.h"

static void exif_trim_spaces(char *str);
static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize);
static void exif_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize);
static void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize);

/* remove all spaces on the right end of a string */
static void exif_trim_spaces(char *str)
void exif_trim_spaces(char *str)
{
  char *end;
  
@@ -59,8 +54,9 @@ static void exif_trim_spaces(char *str)
}



/* show given exif tag content with tag name */
static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
{
  char s[EXIF_MAX_DATA];
  ExifEntry *entry = NULL;
@@ -87,7 +83,7 @@ static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, un


/* show given exif tag content without tag name */
static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
{
  char s[EXIF_MAX_DATA];
  ExifEntry *entry = NULL;
@@ -104,7 +100,7 @@ static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* bu
      exif_trim_spaces(s);
      if (*s != '\0')
      {
        D(("%s", exif_tag_get_name_in_ifd(tag,ifd), s));
        D(("%s - %s\n", exif_tag_get_name_in_ifd(tag,ifd), s));
        snprintf(buffer, (size_t)maxsize, "%s", s);
      }
    }
@@ -115,7 +111,7 @@ static void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* bu


/* Show the given MakerNote tag if it exists */
static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize)
void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize)
{
  ExifMnoteData *mn = NULL; 
  int i, num;
@@ -137,6 +133,11 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi
    /* Loop through all MakerNote tags, searching for the desired one */
    for (i=0; i < num; ++i) 
    {
      D(("%d/%d %d 0x%2x %s; %s\n", i, num, exif_mnote_data_get_id(mn, i), 
        exif_mnote_data_get_id(mn, i),
        exif_mnote_data_get_name(mn,i), 
        exif_mnote_data_get_title(mn, i) ));
      
      if (exif_mnote_data_get_id(mn, i) == tag) 
      {
        if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf))) 
@@ -145,6 +146,7 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi
          exif_trim_spaces(buf);
          if (*buf != '\0')
          {
             D(("%s\n", buf));
             snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_mnote_data_get_title(mn, i), buf);
          }
        }
@@ -155,63 +157,8 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi



/* get interesting nikon maker note tags in readable form */
static void exif_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize)
{
  char buf[EXIF_STD_BUF_LEN];
  unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
  unsigned int version = 0;
  unsigned int length = 0;

  buf[0] = '\0';
  exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
  exif_trim_spaces(buf);

  if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
  {
    /* show extended flash info if flash was fired */
  
    /* Flash Setting */
    exif_get_mnote_tag(ed, 8, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* Flash Mode */
    exif_get_mnote_tag(ed, 9, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* flash exposure bracket value */
    exif_get_mnote_tag(ed, 24, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* Flash used */
    exif_get_mnote_tag(ed, 135, buffer + strlen(buffer), maxsize - strlen(buffer));

    /* Flash info: control mode. */
    /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
    buf[0] = '\0';
    exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
    sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*10s%02X", &length, &version, &exn_fcm);
    exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;

    if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
         && ( ((length == 22) && (version == '3'))      /* Nikon FlashInfo0103 */
              || ((length == 22) && (version == '4'))   /* Nikon FlashInfo0104 */
              || ((length == 21) && (version == '2'))   /* Nikon FlashInfo0102 */
              || ((length == 19) && (version == '0'))   /* Nikon FlashInfo0100 */
            )
       )
    {
      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "NikonFlashControlMode: %s\n", 
      EXN_NikonFlashControlModeValues[exn_fcm]);
    }
  }

  /* Lens */
  exif_get_mnote_tag(ed, 132, buffer + strlen(buffer), maxsize - strlen(buffer));
  /* Digital Vari-Program */
  exif_get_mnote_tag(ed, 171, buffer + strlen(buffer), maxsize - strlen(buffer));

  return;
}



/* get gps coordinates if available */
static void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
{
  char buf[EXIF_STD_BUF_LEN];
  
@@ -297,7 +244,7 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
{
  ExifEntry *entry = NULL;
  char buf[EXIF_STD_BUF_LEN];
  int i = 0;
  unsigned short int i = 0;
  
  if ( (buffer == NULL) || (maxsize == 0) )
  {
@@ -310,14 +257,14 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
  }
  else
  {
    /* normal exif tags */
    while ( Exif_tag_list[i].ifd != EXIF_IFD_COUNT )
    /* show normal exif tags. list must be defined in exif_cfg.h  */
    while ( (Exif_tag_list[i].ifd != EXIF_IFD_COUNT) && (i < USHRT_MAX) )
    {
      exif_get_tag(ed, Exif_tag_list[i].ifd, Exif_tag_list[i].tag, buffer + strlen(buffer), maxsize - strlen(buffer));
      i++; 
    }

    /* vendor specific makernote tags */
    /* show vendor specific makernote tags */
    entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
    if (entry != NULL) 
    {
@@ -332,14 +279,14 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
           )
        {
          /* this is a nikon camera */
          exif_get_mnote_nikon_tags(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
          exn_get_mnote_nikon_tags(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
        }

      }
      
    }
    
    /* gps info */
    /* show gps coordinates */
    exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));

  }
+5 −0
Original line number Diff line number Diff line
@@ -31,6 +31,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define EXIF_MAX_DATA 1024
#define EXIF_STD_BUF_LEN 128

extern void exif_trim_spaces(char *str);
extern void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
extern void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize);
extern void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsigned int maxsize);
extern void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize);
extern ExifData * exif_get_data(char *path);
extern void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize);

src/exif_nikon.c

0 → 100644
+265 −0
Original line number Diff line number Diff line
/* exif_nikon.c

Copyright (C) 2012      Dennis Real.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies of the Software and its documentation and acknowledgment shall be
given in the documentation and software packages that this Software was
used.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

#ifdef HAVE_LIBEXIF

#include <stdio.h>
#include <string.h>
#include <libexif/exif-data.h>

#include "feh.h"
#include "debug.h"
#include "exif.h"
#include "exif_nikon.h"


/* Flash control mode */
/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
#define EXN_FLASH_CONTROL_MODES_MAX 9
char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off", 
                                       "iTTL-BL", "iTTL", "Auto Aperture", 
                                       "Automatic", "GN (distance priority)", 
                                       "Manual", "Repeating Flash", 
                                       "N/A" /* "N/A" is not a nikon setting */
                                       };

#define EXN_FLASH_CONTROL_MODE_MASK 0x7F


/* AFInfo2 */
/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#AFInfo2 */
#define EXN_CONTRAST_DETECT_AF_MAX 2
char *EXN_NikonContrastDetectAF[EXN_CONTRAST_DETECT_AF_MAX] = {"Off", "On"};

/* AFArea Mode for ContrastDetectAF Off */
#define EXN_AF_AREA_MODE_P_MAX 13
char *EXN_NikonAFAreaModePhase[EXN_AF_AREA_MODE_P_MAX] = {
  "Single Area", "Dynamic Area", "Dynamic Area (closest subject)",
  "Group Dynamic ", "Dynamic Area (9 points) ", "Dynamic Area (21 points)",
  "Dynamic Area (51 points) ", "Dynamic Area (51 points, 3D-tracking)",
  "Auto-area", "Dynamic Area (3D-tracking)", "Single Area (wide)",
  "Dynamic Area (wide)", "Dynamic Area (wide, 3D-tracking)"};

/* AFArea Mode for ContrastDetectAF On */
#define EXN_AF_AREA_MODE_C_MAX 5
char *EXN_NikonAFAreaModeContr[EXN_AF_AREA_MODE_C_MAX] = {
  "Contrast-detect", 
  "Contrast-detect (normal area)", 
  "Contrast-detect (wide area)", 
  "Contrast-detect (face priority)", 
  "Contrast-detect (subject tracking)"};

#define EXN_PHASE_DETECT_AF_MAX 4
char *EXN_NikonPhaseDetectAF[EXN_PHASE_DETECT_AF_MAX] = {"Off", "On (51-point)", 
                                                         "On (11-point)", "On (39-point)"};

/* PrimaryAFPoint and AFPointsUsed only valid with PhaseDetectAF == On */

#define EXN_PRIM_AF_PT_51_MAX 52
char * EXN_Prim_AF_Pt_51[EXN_PRIM_AF_PT_51_MAX] = {"(none)", "C6 (Center)", "B6", "A5",
  "D6", "E5", "C7", "B7", "A6", "D7", "E6", "C5", "B5", "A4", "D5", "E4", "C8", "B8",
  "A7", "D8", "E7", "C9", "B9", "A8", "D9", "E8", "C10", "B10", "A9", "D10", "E9",
  "C11", "B11", "D11", "C4", "B4", "A3", "D4", "E3", "C3", "B3", "A2", "D3", "E2",
  "C2", "B2", "A1", "D2", "E1", "C1", "B1", "D1"};
  
#define EXN_PRIM_AF_PT_11_MAX 12
char * EXN_Prim_AF_Pt_11[EXN_PRIM_AF_PT_11_MAX] = {"(none)", "Center", "Top", "Bottom",
  "Mid-left", "Upper-left", "Lower-left", "Far Left", "Mid-right", "Upper-right",
  "Lower-right",  "Far Right"};

#define EXN_PRIM_AF_PT_39_MAX 40
char * EXN_Prim_AF_Pt_39[EXN_PRIM_AF_PT_39_MAX] = {"(none)", "C6 (Center)", "B6", "A2",
  "D6", "E2", "C7", "B7", "A3", "D7", "E3", "C5", "B5", "A1", "D5", "E1", "C8", "B8",
  "D8", "C9", "B9", "D9", "C10", "B10", "D10", "C11", "B11", "D11", "C4", "B4", "D4",
  "C3", "B3", "D3", "C2", "B2", "D2", "C1", "B1", "D1"};


static void exn_get_prim_af_pt(unsigned int phasedetectaf,
                               unsigned int primafpt,
                               char * buffer,
                               unsigned int maxsize);
                               
                               
                               

static void exn_get_prim_af_pt(unsigned int phasedetectaf,
                               unsigned int primafpt,
                               char * buffer,
                               unsigned int maxsize)
{
  
  switch(phasedetectaf)
  {
    case 0:
    {
      /* phasedetect not used. should not happen */
      snprintf(buffer, maxsize, "FAIL");
      return;
    }
    break;
    case 1:
    {
      /* 51 pt */
      if ( primafpt < EXN_PRIM_AF_PT_51_MAX )
      {
        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_51[primafpt]);
      }
      return;
    }
    break;
    case 2:
    {
      /* 11 pt */
      if ( primafpt < EXN_PRIM_AF_PT_11_MAX )
      {
        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_11[primafpt]);
      }
      return;
    }
    break;
    case 3:
    {
      /* 39 pt */
      if ( primafpt < EXN_PRIM_AF_PT_39_MAX )
      {
        snprintf(buffer, maxsize, "%s", EXN_Prim_AF_Pt_39[primafpt]);
      }
      return;
    }
    break;
    default:
    {
      snprintf(buffer, maxsize, "?");
      return;    
    }
    break;
  
  }
   
}



/* get interesting nikon maker note tags in readable form */
void exn_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize)
{
  char buf[EXIF_STD_BUF_LEN];
  unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
  unsigned int version = 0;
  unsigned int length = 0;
  unsigned int contrastdetectaf = 0;
  unsigned int afareamode = 0;
  unsigned int phasedetectaf = 0;
  unsigned int primaryafpoint = 0;

  buf[0] = '\0';
  exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buf, sizeof(buf));
  exif_trim_spaces(buf);

  if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
  {
    /* show extended flash info if flash was fired */
  
    /* Flash Setting */
    exif_get_mnote_tag(ed, 8, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* Flash Mode */
    exif_get_mnote_tag(ed, 9, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* flash exposure bracket value */
    exif_get_mnote_tag(ed, 24, buffer + strlen(buffer), maxsize - strlen(buffer));
    /* Flash used */
    exif_get_mnote_tag(ed, 135, buffer + strlen(buffer), maxsize - strlen(buffer));

    /* Flash info: control mode. */
    /* libexif does not support flash info 168 yet. so we have to parse the debug data :-( */
    buf[0] = '\0';
    exif_get_mnote_tag(ed, 168, buf, sizeof(buf));
    sscanf(buf, "(null): %u bytes unknown data: 303130%02X%*10s%02X", &length, &version, &exn_fcm);
    exn_fcm = exn_fcm & EXN_FLASH_CONTROL_MODE_MASK;

    if ( (exn_fcm < EXN_FLASH_CONTROL_MODES_MAX)
         && ( ((length == 22) && (version == '3'))      /* Nikon FlashInfo0103 */
              || ((length == 22) && (version == '4'))   /* Nikon FlashInfo0104 */
              || ((length == 21) && (version == '2'))   /* Nikon FlashInfo0102 */
              || ((length == 19) && (version == '0'))   /* Nikon FlashInfo0100 */
            )
       )
    {
      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "NikonFlashControlMode: %s\n", 
        EXN_NikonFlashControlModeValues[exn_fcm]);
    }
  }

  /* Lens */
  exif_get_mnote_tag(ed, 132, buffer + strlen(buffer), maxsize - strlen(buffer));
  /* Digital Vari-Program */
  exif_get_mnote_tag(ed, 171, buffer + strlen(buffer), maxsize - strlen(buffer));

  /* AFInfo2 */
  /* libexif does not support AFInfo2 183 yet. so we have to parse the debug data :-( */
  buf[0] = '\0';
  exif_get_mnote_tag(ed, 183, buf, sizeof(buf));
  sscanf(buf, "(null): %u bytes unknown data: 303130%02X%02X%02X%02X%02X", &length, &version, 
    &contrastdetectaf,
    &afareamode,
    &phasedetectaf,
    &primaryafpoint
    );


  if ( ((length == 30) && (version == '0'))
       && (contrastdetectaf < EXN_CONTRAST_DETECT_AF_MAX)
       && (phasedetectaf < EXN_PHASE_DETECT_AF_MAX)
       
     )
  {
    if ( (contrastdetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_C_MAX) )
    {
      /* Contrast AF (live view) */
      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), 
        "ContrastDetectAF: %s; AFAreaMode: %s\n", 
        EXN_NikonContrastDetectAF[contrastdetectaf],
        EXN_NikonAFAreaModeContr[afareamode]);
      
    }
    else if ( (phasedetectaf != 0) && (afareamode < EXN_AF_AREA_MODE_P_MAX) )
    {
      /* Phase AF */
      buf[0] = '\0';
      exn_get_prim_af_pt(phasedetectaf, primaryafpoint, buf, EXIF_STD_BUF_LEN);

      snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), 
        "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n", 
        EXN_NikonPhaseDetectAF[phasedetectaf],
        EXN_NikonAFAreaModePhase[afareamode],
        buf
        );
    }
    
  }

  return;
}

#endif
+3 −11
Original line number Diff line number Diff line
@@ -26,16 +26,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef EXIF_NIKON_H
#define EXIF_NIKON_H

/* Flash control mode */
/* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#FlashControlMode */
#define EXN_FLASH_CONTROL_MODES_MAX 9
char *EXN_NikonFlashControlModeValues[EXN_FLASH_CONTROL_MODES_MAX] = {"Off", 
                                       "iTTL-BL", "iTTL", "Auto Aperture", 
                                       "Automatic", "GN (distance priority)", 
                                       "Manual", "Repeating Flash", 
                                       "N/A" /* "N/A" is not a nikon setting */
                                       };

#define EXN_FLASH_CONTROL_MODE_MASK 0x7F
#include <libexif/exif-data.h>

extern void exn_get_mnote_nikon_tags(ExifData *ed, char * buffer, unsigned int maxsize);

#endif