summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--ChangeLog4
-rw-r--r--src/exif.c239
-rw-r--r--src/exif.h10
-rw-r--r--src/exif_canon.c61
-rw-r--r--src/exif_canon.h33
-rw-r--r--src/exif_cfg.h99
-rw-r--r--src/exif_nikon.c370
-rw-r--r--src/exif_nikon.h14
-rw-r--r--src/imlib.c10
-rw-r--r--test/list/filename_recursive7
-rw-r--r--test/ok/jpg_exifbin0 -> 9821 bytes
12 files changed, 748 insertions, 102 deletions
diff --git a/.gitignore b/.gitignore
index 559c5ab..bbfa508 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@
/src/*.inc
/src/feh
/man/*.1
-*~ \ No newline at end of file
+*~
+core
diff --git a/ChangeLog b/ChangeLog
index 13263d3..27c347b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+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
diff --git a/src/exif.c b/src/exif.c
index dcf2a88..a30b2ef 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -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;
@@ -45,25 +48,27 @@ static void exif_trim_spaces(char *str)
{
if (*str != ' ')
{
- end = str+1;
+ end = str + 1;
}
}
*end = '\0';
}
-/* show given exif tag content */
-static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize)
-{
- char s[MAX_EXIF_DATA];
- if ( (d != NULL) && (buffer != NULL) && (maxsize>0) )
+/* 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[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,15 +239,14 @@ 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) )
{
return;
@@ -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)
{
@@ -184,58 +273,46 @@ void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize)
if (exif_entry_get_value(entry, buf, sizeof(buf)))
{
exif_trim_spaces(buf);
-
- /* Nikon */
- if ( 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) )
+ if ( (strcmp(buf, "NIKON CORPORATION") == 0)
+ || (strcmp(buf, "Nikon") == 0)
+ || (strcmp(buf, "NIKON") == 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 */
-
- /* 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]);
- }
+ exn_get_mnote_nikon_tags(ed, Exif_makernote_nikon_tag_list[i],
+ buffer + strlen(buffer), maxsize - strlen(buffer));
+ i++;
}
- /* 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));
}
-
+ 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++;
+ }
+
+ }
+ else
+ {
+ }
}
+
}
+
+ /* show gps coordinates */
+ exif_get_gps_coords(ed, buffer + strlen(buffer), maxsize - strlen(buffer));
+
}
+
}
#endif
diff --git a/src/exif.h b/src/exif.h
index 4d72a57..79187f4 100644
--- a/src/exif.h
+++ b/src/exif.h
@@ -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);
diff --git a/src/exif_canon.c b/src/exif_canon.c
new file mode 100644
index 0000000..8801899
--- /dev/null
+++ b/src/exif_canon.c
@@ -0,0 +1,61 @@
+/* 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
diff --git a/src/exif_canon.h b/src/exif_canon.h
new file mode 100644
index 0000000..d8682c3
--- /dev/null
+++ b/src/exif_canon.h
@@ -0,0 +1,33 @@
+/* exif_canon.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_CANON_H
+#define EXIF_CANON_H
+
+#include <libexif/exif-data.h>
+
+extern void exc_get_mnote_canon_tags(ExifData *ed, unsigned int tag, char * buffer, unsigned int maxsize);
+
+#endif
diff --git a/src/exif_cfg.h b/src/exif_cfg.h
new file mode 100644
index 0000000..31acc50
--- /dev/null
+++ b/src/exif_cfg.h
@@ -0,0 +1,99 @@
+/* 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 */
+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 */
+};
+
+
+
+/* Nikon */
+
+#define EXIF_NIKON_MAKERNOTE_END 0 /* end marker: if 0 used as a tag we must find something else */
+
+/* show these nikon makernote tags */
+const unsigned int Exif_makernote_nikon_tag_list [] =
+{
+ 8, /* Flash Setting */
+ 9, /* Flash Mode */
+ 24, /* Flash exposure bracket value */
+ 135, /* Flash used */
+ 168, /* Flash info: control mode */
+
+ 132, /* Lens */
+ 171, /* Digital Vari-Program */
+ 34, /* ActiveD-Lighting */
+ 183, /* AFInfo2 */
+
+ EXIF_NIKON_MAKERNOTE_END /* end marker */
+};
+
+
+
+/* Canon */
+#define EXIF_CANON_MAKERNOTE_END 0xFFFF /* end marker: if this is used as a tag we must find something else */
+
+/* show these canon makernote tags */
+const unsigned int Exif_makernote_canon_tag_list [] =
+{
+ 8, /* Image Number */
+ 9, /* Owner Name */
+
+ EXIF_CANON_MAKERNOTE_END /* end marker */
+};
+
+
+#endif
diff --git a/src/exif_nikon.c b/src/exif_nikon.c
new file mode 100644
index 0000000..f4a8eea
--- /dev/null
+++ b/src/exif_nikon.c
@@ -0,0 +1,370 @@
+/* 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 <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_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize);
+static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize);
+static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize);
+
+
+
+/* get primary AF point */
+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 ActiveD-Lighting (34) info */
+static void exn_get_mnote_nikon_34(ExifData *ed, char * buffer, unsigned int maxsize)
+{
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int data = 0;
+ char *answer;
+
+ buf[0] = '\0';
+ exif_get_mnote_tag(ed, 34, buf, sizeof(buf));
+ sscanf(buf, "(null): %u", &data); /* not directly supported by libexif yet */
+
+ switch(data)
+ {
+ case 0:
+ {
+ answer = "Off";
+ }
+ break;
+ case 1:
+ {
+ answer = "Low";
+ }
+ break;
+ case 3:
+ {
+ answer = "Normal";
+ }
+ break;
+ case 5:
+ {
+ answer = "High";
+ }
+ break;
+ case 7:
+ {
+ answer = "Extra High";
+ }
+ break;
+ case 65535:
+ {
+ answer = "Auto";
+ }
+ break;
+ default:
+ {
+ answer = "N/A"; /* this is not a nikon value */
+ }
+
+ }
+
+ snprintf(buffer, maxsize, "Active D-Lightning: %s\n", answer);
+
+}
+
+
+
+/* get nikon Flash info: control mode (168) info */
+static void exn_get_mnote_nikon_168(ExifData *ed, char * buffer, unsigned int maxsize)
+{
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int version = 0;
+ unsigned int length = 0;
+ unsigned int exn_fcm = (EXN_FLASH_CONTROL_MODES_MAX-1); /* default to N/A */
+
+ /* 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, maxsize, "NikonFlashControlMode: %s\n", EXN_NikonFlashControlModeValues[exn_fcm]);
+ }
+
+}
+
+
+
+/* get nikon AFInfo2 (183) info */
+static void exn_get_mnote_nikon_183(ExifData *ed, char * buffer, unsigned int maxsize)
+{
+ char buf[EXIF_STD_BUF_LEN];
+ unsigned int contrastdetectaf = 0;
+ unsigned int afareamode = 0;
+ unsigned int phasedetectaf = 0;
+ unsigned int primaryafpoint = 0;
+ unsigned int version = 0;
+ unsigned int length = 0;
+
+ /* 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, maxsize,
+ "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, maxsize,
+ "PhaseDetectAF: %s; AreaMode: %s; PrimaryAFPoint: %s\n",
+ EXN_NikonPhaseDetectAF[phasedetectaf],
+ EXN_NikonAFAreaModePhase[afareamode],
+ buf
+ );
+ }
+
+ }
+}
+
+
+
+/* get interesting nikon maker note tags in readable form */
+void exn_get_mnote_nikon_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)
+ {
+ /* show only if flash was used */
+ case 8: /* Flash Setting */
+ case 9: /* Flash Mode */
+ case 24: /* Flash exposure bracket value */
+ case 135: /* Flash used */
+ {
+ if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
+ {
+ /* show extended flash info only if flash was fired */
+ exif_get_mnote_tag(ed, tag, buffer, maxsize);
+ }
+ }
+ break;
+
+ case 34:
+ {
+ /* ActiveD-Lighting */
+ exn_get_mnote_nikon_34(ed, buffer, maxsize);
+ }
+ break;
+
+ case 168:
+ {
+ /* Flash info: control mode */
+ if ( !(strcmp("Flash: Flash did not fire\n", buf) == 0) )
+ {
+ /* show extended flash info only if flash was fired */
+ exn_get_mnote_nikon_168(ed, buffer, maxsize);
+ }
+ }
+ break;
+
+ case 183:
+ {
+ /* AFInfo 2 */
+ exn_get_mnote_nikon_183(ed, buffer, maxsize);
+ }
+ break;
+
+ default:
+ {
+ /* normal makernote tags without special treatment */
+ exif_get_mnote_tag(ed, tag, buffer, maxsize);
+ }
+ break;
+ }
+
+
+ return;
+}
+
+#endif
diff --git a/src/exif_nikon.h b/src/exif_nikon.h
index e2baf0d..16e8fb9 100644
--- a/src/exif_nikon.h
+++ b/src/exif_nikon.h
@@ -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, unsigned int tag, char * buffer, unsigned int maxsize);
#endif
diff --git a/src/imlib.c b/src/imlib.c
index 09391fa..4f7ff24 100644
--- a/src/imlib.c
+++ b/src/imlib.c
@@ -613,7 +613,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) )
@@ -623,20 +623,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;
@@ -649,7 +649,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
diff --git a/test/list/filename_recursive b/test/list/filename_recursive
index d4d27dd..6e2de8a 100644
--- a/test/list/filename_recursive
+++ b/test/list/filename_recursive
@@ -1,6 +1,7 @@
NUM FORMAT WIDTH HEIGHT PIXELS SIZE ALPHA FILENAME
1 gif 16 16 256 953 - test/ok/gif
2 jpeg 16 16 256 354 - test/ok/jpg
-3 png 16 16 256 403 X test/ok/png
-4 pnm 16 16 256 269 - test/ok/pnm
-5 png 16 16 256 403 X test/ok/recursive/png
+3 jpeg 16 16 256 9k - test/ok/jpg_exif
+4 png 16 16 256 403 X test/ok/png
+5 pnm 16 16 256 269 - test/ok/pnm
+6 png 16 16 256 403 X test/ok/recursive/png
diff --git a/test/ok/jpg_exif b/test/ok/jpg_exif
new file mode 100644
index 0000000..34c3846
--- /dev/null
+++ b/test/ok/jpg_exif
Binary files differ