diff options
-rw-r--r-- | config.mk | 2 | ||||
-rw-r--r-- | src/exif.c | 252 | ||||
-rw-r--r-- | src/exif.h | 5 | ||||
-rw-r--r-- | src/exif_cfg.h | 61 | ||||
-rw-r--r-- | src/imlib.c | 10 | ||||
-rw-r--r-- | test/list/filename_recursive | 7 | ||||
-rw-r--r-- | test/ok/jpg_exif | bin | 0 -> 9821 bytes |
7 files changed, 255 insertions, 82 deletions
@@ -21,7 +21,7 @@ curl ?= 1 debug ?= 0 help ?= 0 xinerama ?= 1 -exif ?= 0 +exif ?= 1 ifeq (${curl},1) CFLAGS += -DHAVE_LIBCURL @@ -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 @@ -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 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 Binary files differnew file mode 100644 index 0000000..34c3846 --- /dev/null +++ b/test/ok/jpg_exif |