From 9e1bbf874500e99506baffec3c6b54ed04e60a2f Mon Sep 17 00:00:00 2001
From: Dennis Real <github@tildepipe.org>
Date: Fri, 16 Mar 2012 22:20:58 +0100
Subject: [PATCH] - exif handling changed - gps info added if available

---
 src/exif.c     | 252 +++++++++++++++++++++++++++++++++++--------------
 src/exif.h     |   5 +-
 src/exif_cfg.h |  61 ++++++++++++
 src/imlib.c    |  10 +-
 4 files changed, 250 insertions(+), 78 deletions(-)
 create mode 100644 src/exif_cfg.h

diff --git a/src/exif.c b/src/exif.c
index dcf2a88..6f6440f 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -34,7 +34,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "debug.h"
 #include "exif.h"
 #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)
@@ -52,18 +59,19 @@ static void exif_trim_spaces(char *str)
 }
 
 
-/* show given exif tag content */
+/* show given exif tag content with tag name */
 static 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,6 +86,34 @@ 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)
+{
+  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", 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)
 {
@@ -119,6 +155,125 @@ 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)
+{
+  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,15 +291,14 @@ ExifData * exif_get_data(char *path)
 
 
 
+
 /* get 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];
+  int i = 0;
+  
   if ( (buffer == NULL) || (maxsize == 0) )
   {
     return;
@@ -157,24 +311,11 @@ 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));
+    while ( Exif_tag_list[i].ifd != EXIF_IFD_COUNT )
+    {
+      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 */
     entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
@@ -185,57 +326,24 @@ 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) )
-          {
-            /* extended flash info if it 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));
-
+          exif_get_mnote_nikon_tags(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
         }
 
       }
+      
     }
+    
+    /* gps info */
+    exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
+
   }
+  
 }
 
 #endif
diff --git a/src/exif.h b/src/exif.h
index 4d72a57..5d7def4 100644
--- a/src/exif.h
+++ b/src/exif.h
@@ -26,7 +26,10 @@ 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 ExifData * exif_get_data(char *path);
 extern void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize);
diff --git a/src/exif_cfg.h b/src/exif_cfg.h
new file mode 100644
index 0000000..c828f43
--- /dev/null
+++ b/src/exif_cfg.h
@@ -0,0 +1,61 @@
+/* exif_cfg.h
+
+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.
+
+*/
+
+#ifndef EXIF_CFG_H
+#define EXIF_CFG_H
+
+#include <libexif/exif-data.h>
+
+typedef struct
+{
+  ExifIfd ifd; /* section */
+  ExifTag tag;  /* tag */
+} t_EXIF_INFO;
+
+/* show these standard tags. section must be given first, than the tag itself */
+/* note: maker note specific tags are handled directly in exif.c up to now */
+const t_EXIF_INFO Exif_tag_list [] =
+{
+  {EXIF_IFD_0, EXIF_TAG_MAKE},
+  {EXIF_IFD_0, EXIF_TAG_MODEL},
+  {EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION},
+  {EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL},
+  {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME},
+  {EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE},
+  {EXIF_IFD_EXIF, EXIF_TAG_FNUMBER},
+  {EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE},
+  {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE},
+  {EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS},
+  {EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH},
+  {EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM},
+  {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE},
+  {EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM},
+  {EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE},
+  {EXIF_IFD_EXIF, EXIF_TAG_FLASH},
+  
+  {EXIF_IFD_COUNT, 0}	/* end marker */
+};
+
+#endif
diff --git a/src/imlib.c b/src/imlib.c
index eda3e2a..9aa166f 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -612,7 +612,7 @@ void feh_draw_exif(winwidget w)
 	int pos2 = 0;
 	char info_line[256];
 	char *info_buf[128];
-	char buffer[MAX_EXIF_DATA];
+	char buffer[EXIF_MAX_DATA];
 
 	if ( (!w->file) || (!FEH_FILE(w->file->data))
 			 || (!FEH_FILE(w->file->data)->filename) )
@@ -622,20 +622,20 @@ void feh_draw_exif(winwidget w)
 
 
 	buffer[0] = '\0';
-	exif_get_info(FEH_FILE(w->file->data)->ed, buffer, MAX_EXIF_DATA);
+	exif_get_info(FEH_FILE(w->file->data)->ed, buffer, EXIF_MAX_DATA);
 
 	fn = feh_load_font(w);
 
 	if (buffer == NULL) 
 	{
-		snprintf(buffer, MAX_EXIF_DATA, "%s", estrdup("Failed to run exif command"));
+		snprintf(buffer, EXIF_MAX_DATA, "%s", estrdup("Failed to run exif command"));
 		gib_imlib_get_text_size(fn, &buffer[0], NULL, &width, &height, IMLIB_TEXT_TO_RIGHT);
 		no_lines = 1;
 	}
 	else 
 	{
 
-		while ( (no_lines < 128) && (pos < MAX_EXIF_DATA) )
+		while ( (no_lines < 128) && (pos < EXIF_MAX_DATA) )
 		{
 			/* max 128 lines */
 			pos2 = 0;
@@ -648,7 +648,7 @@ void feh_draw_exif(winwidget w)
 			  }
 			  else if ( buffer[pos] == '\0' )
 			  {
-			    pos = MAX_EXIF_DATA; /* all data seen */
+			    pos = EXIF_MAX_DATA; /* all data seen */
 			    info_line[pos2] = '\0';
 				}
 			  else
-- 
GitLab