Commit bb954ff1 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Lots of EXIF mode fixes and improvements by Dennis Real (closes #87)

Squashed commit of the following:

commit 58dd2e30
Merge: cf6f0320 82a976e0
Author: Dennis Real <github@tildepipe.org>
Date:   Sat Mar 31 18:43:47 2012 +0200

    Merge branch 'master' of git://github.com/derf/feh

commit cf6f0320
Merge: 10b7b1e3 877e6346
Author: Dennis Real <github@tildepipe.org>
Date:   Sun Mar 25 19:07:30 2012 +0200

    Merge branch 'master' of git://github.com/derf/feh

commit 10b7b1e3
Author: Dennis Real <github@tildepipe.org>
Date:   Sat Mar 24 14:41:15 2012 +0100

    Support for Canon Exif makernote tags

commit 3c284dc8
Author: Dennis Real <github@tildepipe.org>
Date:   Thu Mar 22 19:44:32 2012 +0100

    Support for Active D-Lightning

commit ad5aea8c
Merge: cc6de200 9c43b648
Author: Dennis Real <github@tildepipe.org>
Date:   Thu Mar 22 19:01:38 2012 +0100

    Merge remote branch 'upstream/master'

commit cc6de200
Author: Dennis Real <github@tildepipe.org>
Date:   Thu Mar 22 19:00:30 2012 +0100

    Nikon makernote parts changed

commit e401bd9c
Author: Dennis Real <github@tildepipe.org>
Date:   Wed Mar 21 19:47:15 2012 +0100

    1. Own module for nikon maker notes
    2. Support for AFInfo2

commit 39cbd1ed
Merge: 9e1bbf87 a1001232
Author: Dennis Real <github@tildepipe.org>
Date:   Fri Mar 16 22:22:28 2012 +0100

    Merge remote branch 'upstream/master'

commit 9e1bbf87
Author: Dennis Real <github@tildepipe.org>
Date:   Fri Mar 16 22:20:58 2012 +0100

    - exif handling changed
    - gps info added if available

commit 8e963828
Merge: 77fa5aca 29cd8688
Author: Dennis Real <github@tildepipe.org>
Date:   Fri Mar 16 19:13:47 2012 +0100

    Merge branch 'master' of git://github.com/derf/feh

commit 77fa5aca
Merge: 93a90e60 3b2756bf
Author: Dennis Real <github@tildepipe.org>
Date:   Wed Mar 7 17:18:07 2012 +0100

    Merge branch 'master' of git://github.com/derf/feh

commit 93a90e60
Merge: a81465d0 52d5da9c
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Mar 6 21:42:40 2012 +0100

    Merge branch 'master' of git://github.com/derf/feh

commit a81465d0
Merge: a19e50de 31afac45
Author: Dennis Real <github@tildepipe.org>
Date:   Mon Mar 5 17:23:40 2012 +0100

    Merge branch 'master' of git://github.com/derf/feh

commit a19e50de
Merge: 1c89da12 fe9a16bc
Author: Dennis Real <github@tildepipe.org>
Date:   Sun Mar 4 15:35:45 2012 +0100

    Merge branch 'master' of ssh://github.com/reald/feh

commit 1c89da12
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Feb 28 22:37:22 2012 +0100

    test case adapted to new testfile

commit bb3c9d35
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Feb 28 22:34:51 2012 +0100

    test file with some exif data added

commit fe9a16bc
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Feb 28 22:37:22 2012 +0100

    test case adapted to new testfile

commit e0bedc04
Merge: 46801fee 69ecc5c1
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Feb 28 22:36:08 2012 +0100

    Merge remote branch 'upstream/master'

commit 46801fee
Author: Dennis Real <github@tildepipe.org>
Date:   Tue Feb 28 22:34:51 2012 +0100

    test file with some exif data added
parent 82a976e0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -4,3 +4,4 @@
/src/feh
/man/*.1
*~
core
+4 −0
Original line number Diff line number Diff line
git HEAD

    * Dennis Real: EXIF mode fixes, support for more camera models

Sun, 25 Mar 2012 13:13:26 +0200  Daniel Friesel <derf@finalrewind.org>

* Release v2.5
+158 −81
Original line number Diff line number Diff line
@@ -28,16 +28,19 @@ 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"
#include "debug.h"
#include "exif.h"
#include "exif_canon.h"
#include "exif_nikon.h"
#include "exif_cfg.h"


/* 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;
  
@@ -52,18 +55,20 @@ static void exif_trim_spaces(char *str)
}


/* show given exif tag content */
static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)

/* show given exif tag content with tag name */
void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
{
  char s[MAX_EXIF_DATA];
  char s[EXIF_MAX_DATA];
  ExifEntry *entry = NULL;
  
  if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
  {
    ExifEntry *entry = exif_content_get_entry(d->ifd[ifd], tag);
    entry = exif_content_get_entry(d->ifd[ifd], tag);
    if (entry != NULL) 
    {
      /* Get the contents of the tag in human-readable form */
      exif_entry_get_value(entry, s, maxsize);
      exif_entry_get_value(entry, s, EXIF_MAX_DATA);

      /* Don't bother printing it if it's entirely blank */
      exif_trim_spaces(s);
@@ -78,8 +83,36 @@ static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, un



/* show given exif tag content without tag name */
void exif_get_tag_content(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
{
  char s[EXIF_MAX_DATA];
  ExifEntry *entry = NULL;

  if ( (d != NULL) && (buffer != NULL) && (maxsize > 0) )
  {
    entry = exif_content_get_entry(d->ifd[ifd], tag);
    if (entry != NULL) 
    {
      /* Get the contents of the tag in human-readable form */
      exif_entry_get_value(entry, s, EXIF_MAX_DATA);

      /* Don't bother printing it if it's entirely blank */
      exif_trim_spaces(s);
      if (*s != '\0')
      {
        D(("%s - %s\n", exif_tag_get_name_in_ifd(tag,ifd), s));
        snprintf(buffer, (size_t)maxsize, "%s", s);
      }
    }
  }

}



/* 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;
@@ -101,6 +134,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))) 
@@ -109,6 +147,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);
          }
        }
@@ -119,6 +158,70 @@ static void exif_get_mnote_tag(ExifData *d, unsigned int tag, char* buffer, unsi



/* get gps coordinates if available */
void exif_get_gps_coords(ExifData * ed, char *buffer, unsigned int maxsize)
{
  char buf[EXIF_STD_BUF_LEN];
  
  buf[0] = '\0';
  exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, buf, sizeof(buf));
  if ( buf[0] != '\0' )
  {
    snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "GPS: %s ", buf);
  }
  else
  {
    return;
  }

  buf[0] = '\0';
  exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, buf, sizeof(buf));
  if ( buf[0] != '\0' )
  {
    snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "%s ", buf);
  }
  else
  {
    return;
  }

  buf[0] = '\0';
  exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, buf, sizeof(buf));
  if ( buf[0] != '\0' )
  {
    snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), ", %s ", buf);
  }
  else
  {
    return;
  }

  buf[0] = '\0';
  exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, buf, sizeof(buf));
  if ( buf[0] != '\0' )
  {
    snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "%s ", buf);
  }
  else
  {
    return;
  }

  buf[0] = '\0';
  exif_get_tag_content(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_MAP_DATUM, buf, sizeof(buf));
  if ( buf[0] != '\0' )
  {
    snprintf(buffer + strlen(buffer), maxsize - strlen(buffer), "(%s)\n", buf);
  }
  else
  {
    return;
  }

}



/* return data structure with exif data if available */
ExifData * exif_get_data(char *path)
{
@@ -136,14 +239,13 @@ ExifData * exif_get_data(char *path)



/* get exif data in readable form */

/* get all exif data in readable form */
void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
{
  ExifEntry *entry = NULL;
  char buf[128];
  unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
  unsigned int version = 0;
  unsigned int length = 0;
  char buf[EXIF_STD_BUF_LEN];
  unsigned short int i = 0;
  
  if ( (buffer == NULL) || (maxsize == 0) )
  {
@@ -156,27 +258,14 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
  }
  else
  {
    /* normal exif tags */
    exif_get_tag(ed, EXIF_IFD_0, EXIF_TAG_MAKE, buffer, maxsize);
    exif_get_tag(ed, EXIF_IFD_0, EXIF_TAG_MODEL, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH, buffer + strlen(buffer), maxsize - strlen(buffer));
    exif_get_tag(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH_ENERGY, buffer + strlen(buffer), maxsize - strlen(buffer));

    /* vendor specific makernote tags */
    /* 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++; 
    }

    /* show vendor specific makernote tags */
    entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
    if (entry != NULL) 
    {
@@ -185,57 +274,45 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
      {
        exif_trim_spaces(buf);

        /* Nikon */                                    
        if ( strcmp(buf, "Nikon") != 0 )
        if ( (strcmp(buf, "NIKON CORPORATION") == 0)
             || (strcmp(buf, "Nikon") == 0) 
             || (strcmp(buf, "NIKON") == 0)
           )
        {
          /* this is a nikon camera */
          
          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 nikon makernote exif tags. list must be defined in exif_cfg.h  */
          i=0;
          while ( (Exif_makernote_nikon_tag_list[i] != EXIF_NIKON_MAKERNOTE_END) && (i < USHRT_MAX) )
          {
            /* extended flash info if it was fired */
            exn_get_mnote_nikon_tags(ed, Exif_makernote_nikon_tag_list[i], 
                                     buffer + strlen(buffer), maxsize - strlen(buffer));
            i++; 
          }

            /* 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));
        }
        else if ( (strcmp(buf, "Canon") == 0) )
        {
          /* show canon makernote exif tags. list must be defined in exif_cfg.h  */
          i=0;
          while ( (Exif_makernote_canon_tag_list[i] != EXIF_CANON_MAKERNOTE_END) && (i < USHRT_MAX) )
          {
            exc_get_mnote_canon_tags(ed, Exif_makernote_canon_tag_list[i], 
                                     buffer + strlen(buffer), maxsize - strlen(buffer));
            i++; 
          }
        
            /* 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 */
                    )
               )
        }
        else
        {
              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));
      
    }
    
    /* show gps coordinates */
    exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));

  }
    }
  }
  
}

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

#define MAX_EXIF_DATA 1024
#include <libexif/exif-data.h>

#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_canon.c

0 → 100644
+61 −0
Original line number Diff line number Diff line
/* exif_canon.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 <libexif/exif-data.h>

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



/* get interesting canon maker note tags in readable form */
void exc_get_mnote_canon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize)
{
  /* char buf[EXIF_STD_BUF_LEN];

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

  switch(tag)
  {
    default:
    {
      /* normal makernote tags without special treatment */
      exif_get_mnote_tag(ed, tag, buffer, maxsize);
    }
    break;
  }


  return;
}

#endif
Loading