diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/exif.c | 197 | ||||
| -rw-r--r-- | src/exif.h | 34 | ||||
| -rw-r--r-- | src/feh.h | 3 | ||||
| -rw-r--r-- | src/filelist.c | 8 | ||||
| -rw-r--r-- | src/filelist.h | 7 | ||||
| -rw-r--r-- | src/help.raw | 1 | ||||
| -rw-r--r-- | src/imlib.c | 115 | ||||
| -rw-r--r-- | src/keyevents.c | 13 | ||||
| -rw-r--r-- | src/options.c | 14 | ||||
| -rw-r--r-- | src/options.h | 6 | ||||
| -rw-r--r-- | src/winwidget.c | 4 | 
11 files changed, 401 insertions, 1 deletions
| diff --git a/src/exif.c b/src/exif.c new file mode 100644 index 0000000..02154e4 --- /dev/null +++ b/src/exif.c @@ -0,0 +1,197 @@ +/* exif.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 "options.h" +#include "debug.h" +#include "exif.h" + + + +/* remove all spaces on the right end of a string */ +static void exif_trim_spaces(char *str) +{ +  char *end; +   +  for (end = str; *str!='\0'; str++)  +  { +    if (*str != ' ') +    { +      end = str; +    } +  } +  *++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) ) +  { +    ExifEntry *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); + +      /* 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\n", exif_tag_get_name_in_ifd(tag,ifd), 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) +{ +  ExifMnoteData *mn = NULL;  +  int i, num; +  char buf[1024]; + +  if ( (d!=NULL) && (buffer!=NULL) && (maxsize > 0) ) +  { +    mn = exif_data_get_mnote_data(d); +  } +  else +  { +    return; +  } +     +  if ( mn != NULL )  +  { +    num = exif_mnote_data_count(mn); + +    /* Loop through all MakerNote tags, searching for the desired one */ +    for (i=0; i < num; ++i)  +    { +      if (exif_mnote_data_get_id(mn, i) == tag)  +      { +        if (exif_mnote_data_get_value(mn, i, buf, sizeof(buf)))  +        { +          /* Don't bother printing it if it's entirely blank */ +          exif_trim_spaces(buf); +          if (*buf != '\0') +          { +             snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_mnote_data_get_title(mn, i), buf); +          } +        } +      } +    } +  } +} + + + +/* return data structure with exif data if available */ +ExifData * exif_get_data(char *path) +{ +  ExifData *ed = NULL; + +  /* Load an ExifData object from an EXIF file */ +  ed = exif_data_new_from_file(path); +  if (ed == NULL) +  { +    D(("File not readable or no Exif data present in %s\n", path)); +  } + +  return(ed); +} + + + +/* get exif data in readable form */ +void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize) +{ +  ExifEntry *entry = NULL; +  char buf[64]; + +  if ( (buffer == NULL) || (maxsize == 0) ) +  { +    return; +  } +  else if (ed == NULL ) +  { +    snprintf(buffer, (size_t)maxsize, "%s\n", "No Exif data in file."); +    return; +  } +  else if ( ed != NULL ) +  { +    /* 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 */ +    entry = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE); +    if (entry != NULL)  +    { +                 +      if (exif_entry_get_value(entry, buf, sizeof(buf)))  +      { +        exif_trim_spaces(buf); +         +        /* Nikon */                                     +        if ( strcmp(buf, "Nikon") != 0 ) +        { +          /* Digital Vari-Program */ +          exif_get_mnote_tag(ed, 171, buffer + strlen(buffer), maxsize - strlen(buffer)); +        } + +      } +    } +  } +} + +#endif diff --git a/src/exif.h b/src/exif.h new file mode 100644 index 0000000..4d72a57 --- /dev/null +++ b/src/exif.h @@ -0,0 +1,34 @@ +/* exif.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_H +#define EXIF_H + +#define MAX_EXIF_DATA 1024 + +extern ExifData * exif_get_data(char *path); +extern void exif_get_info(ExifData * ed, char *buffer, unsigned int maxsize); + +#endif @@ -146,6 +146,9 @@ void cb_reload_timer(void *data);  char *feh_http_load_image(char *url);  int feh_load_image_char(Imlib_Image * im, char *filename);  void feh_draw_filename(winwidget w); +#ifdef HAVE_LIBEXIF +void feh_draw_exif(winwidget w); +#endif  void feh_draw_actions(winwidget w);  void feh_draw_caption(winwidget w);  void feh_draw_info(winwidget w); diff --git a/src/filelist.c b/src/filelist.c index 522f3cc..32bc2a5 100644 --- a/src/filelist.c +++ b/src/filelist.c @@ -24,6 +24,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */ +#ifdef HAVE_LIBEXIF +#include <libexif/exif-data.h> +#endif +  #include "feh.h"  #include "filelist.h"  #include "options.h" @@ -65,6 +69,10 @@ void feh_file_free(feh_file * file)  		free(file->caption);  	if (file->info)  		feh_file_info_free(file->info); +#ifdef HAVE_LIBEXIF +	if (file->info) +		exif_data_unref(file->ed); +#endif		  	free(file);  	return;  } diff --git a/src/filelist.h b/src/filelist.h index 9ec302c..00e36e8 100644 --- a/src/filelist.h +++ b/src/filelist.h @@ -26,6 +26,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #ifndef FILELIST_H  #define FILELIST_H +#ifdef HAVE_LIBEXIF +#include <libexif/exif-data.h> +#endif +  struct __feh_file {  	char *filename;  	char *caption; @@ -33,6 +37,9 @@ struct __feh_file {  	/* info stuff */  	feh_file_info *info;	/* only set when needed */ +#ifdef HAVE_LIBEXIF +	ExifData *ed; +#endif  };  struct __feh_file_info { diff --git a/src/help.raw b/src/help.raw index f626580..818cea0 100644 --- a/src/help.raw +++ b/src/help.raw @@ -32,6 +32,7 @@ OPTIONS   -x, --borderless          Create borderless windows   -d, --draw-filename       Show the filename in the image window       --draw-tinted         Show overlay texts on semi-transparent background + -Q, --draw-exif           Show some Exif information   -^, --title TITLE         Set window title (see FORMAT SPECIFIERS)   -D, --slideshow-delay NUM Set delay between automatically changing slides       --cycle-once          Exit after one loop through the slideshow diff --git a/src/imlib.c b/src/imlib.c index 6d718f5..0b60180 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -39,6 +39,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  #include <curl/curl.h>  #endif +#ifdef HAVE_LIBEXIF +#include "exif.h" +#endif +  Display *disp = NULL;  Visual *vis = NULL;  Screen *scr = NULL; @@ -146,6 +150,9 @@ int feh_load_image(Imlib_Image * im, feh_file * file)  			file->filename = tmpname;  			feh_file_info_load(file, *im);  			file->filename = tempcpy; +#ifdef HAVE_LIBEXIF +			file->ed = exif_get_data(tmpname); +#endif		  		}  		if ((opt.slideshow) && (opt.reload == 0)) {  			/* Http, no reload, slideshow. Let's keep this image on hand... */ @@ -220,6 +227,10 @@ int feh_load_image(Imlib_Image * im, feh_file * file)  		return(0);  	} +#ifdef HAVE_LIBEXIF +	file->ed = exif_get_data(file->filename); +#endif		 +  	D(("Loaded ok\n"));  	return(1);  } @@ -492,6 +503,110 @@ void feh_draw_filename(winwidget w)  	return;  } +#ifdef HAVE_LIBEXIF   +void feh_draw_exif(winwidget w) +{ +	static Imlib_Font fn = NULL; +	int width = 0, height = 0, line_width = 0, line_height = 0; +	Imlib_Image im = NULL; +	int no_lines = 0, i; +	int pos = 0; +	int pos2 = 0; +	char info_line[256]; +	char *info_buf[128]; +	char buffer[MAX_EXIF_DATA]; + +	if ( (!w->file) || (!FEH_FILE(w->file->data)) +			 || (!FEH_FILE(w->file->data)->filename) ) +	{ +		return; +	} + +	exif_get_info(FEH_FILE(w->file->data)->ed, buffer, MAX_EXIF_DATA); + +	fn = feh_load_font(w); + +	if (buffer == NULL)  +	{ +		snprintf(buffer, MAX_EXIF_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) ) +		{ +			/* max 128 lines */ +			pos2 = 0; +			while ( pos2 < 256 ) /* max 256 chars per line */ +			{ +				if ( (buffer[pos] != '\n') +				      && (buffer[pos] != '\0') ) +				{ +			    info_line[pos2] = buffer[pos]; +			  } +			  else if ( buffer[pos] == '\0' ) +			  { +			    pos = MAX_EXIF_DATA; /* all data seen */ +			    info_line[pos2] = '\0'; +				} +			  else +			  { +			  	info_line[pos2] = '\0'; /* line finished, continue with next line*/ + +			    pos++; +			    break; +			  } +			         +			   pos++; +			   pos2++;   +			} + +			gib_imlib_get_text_size(fn, info_line, NULL, &line_width, +                              &line_height, IMLIB_TEXT_TO_RIGHT); + +			if (line_height > height) +				height = line_height; +			if (line_width > width) +				width = line_width; +			info_buf[no_lines] = estrdup(info_line); + +			no_lines++; +		} +	} + +	if (no_lines == 0) +		return; + +	height *= no_lines; +	width += 4; + +	im = imlib_create_image(width, height); +	if (!im) +	{ +		eprintf("Couldn't create image. Out of memory?"); +	} + +	feh_imlib_image_fill_text_bg(im, width, height); + +	for (i = 0; i < no_lines; i++)  +	{ +		gib_imlib_text_draw(im, fn, NULL, 2, (i * line_height) + 2, +				info_buf[i], IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255); +		gib_imlib_text_draw(im, fn, NULL, 1, (i * line_height) + 1, +				info_buf[i], IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255); + +	} + +	gib_imlib_render_image_on_drawable(w->bg_pmap, im, 0, w->h - height, 1, 1, 0); + +	gib_imlib_free_image_and_decache(im); +	return; + +} +#endif +  void feh_draw_info(winwidget w)  {  	static Imlib_Font fn = NULL; diff --git a/src/keyevents.c b/src/keyevents.c index 873e114..0ada751 100644 --- a/src/keyevents.c +++ b/src/keyevents.c @@ -136,6 +136,9 @@ void init_keyevents(void) {  	feh_set_kb(&keys.toggle_actions, 0, XK_a, 0, 0, 0, 0);  	feh_set_kb(&keys.toggle_aliasing, 0, XK_A, 0, 0, 0, 0);  	feh_set_kb(&keys.toggle_filenames, 0, XK_d, 0, 0, 0, 0); +#ifdef HAVE_LIBEXIF +	feh_set_kb(&keys.toggle_exif, 0, XK_e, 0, 0, 0, 0);	 +#endif  	feh_set_kb(&keys.toggle_info, 0, XK_i, 0, 0, 0, 0);  	feh_set_kb(&keys.toggle_pointer, 0, XK_o, 0, 0, 0, 0);  	feh_set_kb(&keys.toggle_caption, 0, XK_c, 0, 0, 0, 0); @@ -270,6 +273,10 @@ void init_keyevents(void) {  			cur_kb = &keys.toggle_aliasing;  		else if (!strcmp(action, "toggle_filenames"))  			cur_kb = &keys.toggle_filenames; +#ifdef HAVE_LIBEXIF +		else if (!strcmp(action, "toggle_exif")) +			cur_kb = &keys.toggle_exif;			 +#endif  		else if (!strcmp(action, "toggle_info"))  			cur_kb = &keys.toggle_info;  		else if (!strcmp(action, "toggle_pointer")) @@ -628,6 +635,12 @@ void feh_event_handle_keypress(XEvent * ev)  		opt.draw_filename = !opt.draw_filename;  		winwidget_rerender_all(0);  	} +#ifdef HAVE_LIBEXIF +	else if (feh_is_kp(&keys.toggle_exif, keysym, state)) { +		opt.draw_exif = !opt.draw_exif; +		winwidget_rerender_all(0); +	} +#endif		  	else if (feh_is_kp(&keys.toggle_info, keysym, state)) {  		opt.draw_info = !opt.draw_info;  		winwidget_rerender_all(0); diff --git a/src/options.c b/src/options.c index 89f5e71..4c0ad5d 100644 --- a/src/options.c +++ b/src/options.c @@ -301,7 +301,11 @@ static void feh_getopt_theme(int argc, char **argv)  static void feh_parse_option_array(int argc, char **argv, int finalrun)  {  	static char stropts[] = -		"a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ" +#ifdef HAVE_LIBEXIF +		"a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPQqrR:sS:tT:uUvVwW:xXy:YzZ" +#else		 +		"a:A:b:B:cC:dD:e:E:f:Fg:GhH:iIj:J:kK:lL:mM:nNo:O:pPqrR:sS:tT:uUvVwW:xXy:YzZ"		 +#endif  		".@:^:~:):|:+:";  	/* (*name, has_arg, *flag, val) See: struct option in getopts.h */ @@ -329,6 +333,9 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)  		{"auto-zoom"     , 0, 0, 'Z'},  		{"ignore-aspect" , 0, 0, 'X'},  		{"draw-filename" , 0, 0, 'd'}, +#ifdef HAVE_LIBEXIF +		{"draw-exif"     , 0, 0, 'Q'}, +#endif  		{"preload"       , 0, 0, 'p'},  		{"reverse"       , 0, 0, 'n'},  		{"thumbnails"    , 0, 0, 't'}, @@ -476,6 +483,11 @@ static void feh_parse_option_array(int argc, char **argv, int finalrun)  		case 'd':  			opt.draw_filename = 1;  			break; +#ifdef HAVE_LIBEXIF +		case 'Q': +			opt.draw_exif = 1; +			break; +#endif  		case 'F':  			opt.full_screen = 1;  			break; diff --git a/src/options.h b/src/options.h index 899bcf1..bee7c73 100644 --- a/src/options.h +++ b/src/options.h @@ -49,6 +49,9 @@ struct __fehoptions {  	unsigned char jump_on_resort;  	unsigned char full_screen;  	unsigned char draw_filename; +#ifdef HAVE_LIBEXIF +	unsigned char draw_exif; +#endif  	unsigned char list;  	unsigned char quiet;  	unsigned char preload; @@ -163,6 +166,9 @@ struct __fehkb {  	struct __fehkey render;  	struct __fehkey toggle_actions;  	struct __fehkey toggle_filenames; +#ifdef HAVE_LIBEXIF +	struct __fehkey toggle_exif; +#endif  	struct __fehkey toggle_info;  	struct __fehkey toggle_pointer;  	struct __fehkey toggle_aliasing; diff --git a/src/winwidget.c b/src/winwidget.c index ed7002a..e263702 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -574,6 +574,10 @@ void winwidget_render_image(winwidget winwid, int resize, int force_alias)  			winwidget_update_caption(winwid);  		if (opt.draw_filename)  			feh_draw_filename(winwid); +#ifdef HAVE_LIBEXIF +		if (opt.draw_exif) +			feh_draw_exif(winwid); +#endif  		if (opt.draw_actions)  			feh_draw_actions(winwid);  		if (opt.draw_info && opt.info_cmd) | 
