From 84a0008e3167969e2250ac1169da57ad8464624d Mon Sep 17 00:00:00 2001 From: Vladimir Nadvornik Date: Wed, 2 Apr 2008 20:44:40 +0000 Subject: [PATCH] various exif improvements based on patch by Uwe Ohse try to compute 35mm focal length --- src/bar_exif.c | 75 +++++++++++++++++++++++------ src/bar_exif.h | 13 +++++ src/exif-common.c | 119 +++++++++++++++++++++++++++++++++++++++++++--- src/exif.c | 115 +++++++++++++++++++++++++++++--------------- src/image.c | 2 +- src/preferences.c | 76 +++++++++++++++++++++++++++++ src/rcfile.c | 17 +++++++ 7 files changed, 356 insertions(+), 61 deletions(-) diff --git a/src/bar_exif.c b/src/bar_exif.c index 38b2c51d..7a0b2a6a 100644 --- a/src/bar_exif.c +++ b/src/bar_exif.c @@ -36,6 +36,7 @@ static const gchar *bar_exif_key_list_real[] = { "fExposureBias", "fISOSpeedRating", "fFocalLength", + "fFocalLength35mmFilm", "fSubjectDistance", "Exif.Photo.MeteringMode", "fFlash", @@ -49,6 +50,27 @@ static const gchar *bar_exif_key_list_real[] = { const gchar **bar_exif_key_list = bar_exif_key_list_real; const gint bar_exif_key_count = (sizeof(bar_exif_key_list_real) / sizeof(gchar *)); +ExifUI ExifUIList[]={ + { 0, 0, EXIF_UI_ON, "fCamera"}, + { 0, 0, EXIF_UI_ON, "fDateTime"}, + { 0, 0, EXIF_UI_ON, "fShutterSpeed"}, + { 0, 0, EXIF_UI_ON, "fAperture"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Photo.ExposureProgram"}, + { 0, 0, EXIF_UI_IFSET, "fExposureBias"}, + { 0, 0, EXIF_UI_IFSET, "fISOSpeedRating"}, + { 0, 0, EXIF_UI_ON, "fFocalLength"}, + { 0, 0, EXIF_UI_IFSET, "fFocalLength35mmFilm"}, + { 0, 0, EXIF_UI_IFSET, "fSubjectDistance"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Photo.MeteringMode"}, + { 0, 0, EXIF_UI_ON, "fFlash"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Photo.LightSource"}, + { 0, 0, EXIF_UI_OFF, "fResolution"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Image.Orientation"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Image.ImageDescription"}, + { 0, 0, EXIF_UI_IFSET, "Exif.Image.Copyright"}, + { 0, 0, EXIF_UI_OFF, NULL} +}; + /* *------------------------------------------------------------------- @@ -87,7 +109,8 @@ static void table_add_line_custom(GtkWidget *table, gint x, gint y, } static GtkWidget *table_add_line(GtkWidget *table, gint x, gint y, - const gchar *description, const gchar *text) + const gchar *description, const gchar *text, + GtkWidget **keyret) { GtkWidget *key; GtkWidget *label; @@ -95,6 +118,7 @@ static GtkWidget *table_add_line(GtkWidget *table, gint x, gint y, table_add_line_custom(table, x, y, description, text, &key, &label); gtk_widget_show(key); gtk_widget_show(label); + if (keyret) *keyret = key; return label; } @@ -114,6 +138,7 @@ struct _ExifBar GtkWidget *table; GtkWidget *advanced_scrolled; GtkWidget *listview; + GtkWidget **keys; GtkWidget **labels; GtkWidget *custom_sep; @@ -185,12 +210,27 @@ static void bar_exif_update(ExifBar *eb) if (GTK_WIDGET_VISIBLE(eb->scrolled)) { GList *list; - len = bar_exif_key_count; - for (i = 0; i < len; i++) + for (i = 0; ExifUIList[i].key; i++) { gchar *text; - text = exif_get_data_as_text(exif, bar_exif_key_list[i]); + + if (ExifUIList[i].current == EXIF_UI_OFF) + { + gtk_widget_hide(eb->labels[i]); + gtk_widget_hide(eb->keys[i]); + continue; + } + text = exif_get_data_as_text(exif, ExifUIList[i].key); text = bar_exif_validate_text(text); + if (ExifUIList[i].current == EXIF_UI_IFSET + && (!text || !*text)) + { + gtk_widget_hide(eb->labels[i]); + gtk_widget_hide(eb->keys[i]); + continue; + } + gtk_widget_show(eb->labels[i]); + gtk_widget_show(eb->keys[i]); gtk_label_set_text(GTK_LABEL(eb->labels[i]), text); g_free(text); } @@ -286,13 +326,11 @@ static void bar_exif_update(ExifBar *eb) static void bar_exif_clear(ExifBar *eb) { - gint len; gint i; if (!GTK_WIDGET_SENSITIVE(eb->labels[0])) return; - len = bar_exif_key_count; - for (i = 0; i < len; i++) + for (i = 0; ExifUIList[i].key; i++) { gtk_label_set_text(GTK_LABEL(eb->labels[i]), ""); } @@ -519,6 +557,7 @@ static void bar_exif_destroy(GtkWidget *widget, gpointer data) { ExifBar *eb = data; + g_free(eb->keys); g_free(eb->labels); file_data_unref(eb->fd); g_free(eb); @@ -533,10 +572,15 @@ GtkWidget *bar_exif_new(gint show_title, FileData *fd, gint advanced, GtkWidget GtkWidget *button; gint len; gint i; + gint exif_len; + + for (exif_len = 0; ExifUIList[exif_len].key; exif_len++) + ; eb = g_new0(ExifBar, 1); - eb->labels = g_new0(GtkWidget *, bar_exif_key_count); + eb->keys = g_new0(GtkWidget *, exif_len); + eb->labels = g_new0(GtkWidget *, exif_len); eb->vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); g_object_set_data(G_OBJECT(eb->vbox), "bar_exif_data", eb); @@ -590,27 +634,28 @@ GtkWidget *bar_exif_new(gint show_title, FileData *fd, gint advanced, GtkWidget gtk_widget_show(box); } - table = gtk_table_new(2, bar_exif_key_count + 1 + EXIF_BAR_CUSTOM_COUNT, FALSE); + + table = gtk_table_new(2, exif_len + 1 + EXIF_BAR_CUSTOM_COUNT, FALSE); eb->table = table; - len = bar_exif_key_count; - for (i = 0; i < len; i++) + for (i = 0; ExifUIList[i].key; i++) { const gchar *text; - text = exif_get_description_by_key(bar_exif_key_list[i]); - eb->labels[i] = table_add_line(table, 0, i, text, NULL); + text = exif_get_description_by_key(ExifUIList[i].key); + eb->labels[i] = table_add_line(table, 0, i, text, NULL, + &eb->keys[i]); } eb->custom_sep = gtk_hseparator_new(); gtk_table_attach(GTK_TABLE(table), eb->custom_sep, 0, 1, - bar_exif_key_count, bar_exif_key_count + 1, + exif_len, exif_len + 1, GTK_FILL, GTK_FILL, 2, 2); for (i = 0; i < EXIF_BAR_CUSTOM_COUNT; i++) { - table_add_line_custom(table, 0, bar_exif_key_count + 1 + i, + table_add_line_custom(table, 0, exif_len + 1 + i, "", "", &eb->custom_name[i], &eb->custom_value[i]); } diff --git a/src/bar_exif.h b/src/bar_exif.h index 0f67374b..3214dc96 100644 --- a/src/bar_exif.h +++ b/src/bar_exif.h @@ -13,6 +13,19 @@ #ifndef BAR_EXIF_H #define BAR_EXIF_H +#define EXIF_UI_OFF 0 +#define EXIF_UI_IFSET 1 +#define EXIF_UI_ON 2 + +typedef struct _ExifUI ExifUI; +struct _ExifUI { + gint current; + gint temp; + gint default_value; + const gchar *key; +}; +extern ExifUI ExifUIList[]; + GtkWidget *bar_exif_new(gint show_title, FileData *fd, gint advanced, GtkWidget *bounding_widget); void bar_exif_close(GtkWidget *bar); diff --git a/src/exif-common.c b/src/exif-common.c index eb827b26..73cc0751 100644 --- a/src/exif-common.c +++ b/src/exif-common.c @@ -38,6 +38,7 @@ ExifFormattedText ExifFormattedList[] = { { "fExposureBias", N_("Exposure bias") }, { "fISOSpeedRating", N_("ISO sensitivity") }, { "fFocalLength", N_("Focal length") }, + { "fFocalLength35mmFilm",N_("Focal length 35mm") }, { "fSubjectDistance", N_("Subject distance") }, { "fFlash", N_("Flash") }, { "fResolution", N_("Resolution") }, @@ -52,7 +53,6 @@ static ExifTextList ExifFlashList[] = { EXIF_TEXT_LIST_END }; - double exif_rational_to_double(ExifRational *r, gint sign) { if (!r || r->den == 0.0) return 0.0; @@ -78,6 +78,58 @@ static GString *append_comma_text(GString *string, const gchar *text) return string; } +static gchar *remove_common_prefix(gchar *s, gchar *t) +{ + gint i; + + if (!s || !t) return t; + + for (i = 0; s[i] == t[i]; i++) + ; + if (!i) + return t; + if (s[i]==' ' || s[i]==0) + { + while (t[i] == ' ') + i++; + return t + i; + } + return s; +} + +static double get_crop_factor(ExifData *exif) +{ + double res_unit_tbl[] = {0.0, 25.4, 25.4, 10.0, 1.0, 0.001 }; + + double xres = exif_get_rational_as_double(exif, "Exif.Photo.FocalPlaneXResolution"); + double yres = exif_get_rational_as_double(exif, "Exif.Photo.FocalPlaneYResolution"); + int res_unit; + int w, h; + double xsize, ysize, size, ratio; + + if (xres == 0.0 || yres == 0.0) return 0.0; + + if (!exif_get_integer(exif, "Exif.Photo.FocalPlaneResolutionUnit", &res_unit)) return 0.0; + if (res_unit < 1 || res_unit > 5) return 0.0; + + if (!exif_get_integer(exif, "Exif.Photo.PixelXDimension", &w)) return 0.0; + if (!exif_get_integer(exif, "Exif.Photo.PixelYDimension", &h)) return 0.0; + + xsize = w * res_unit_tbl[res_unit] / xres; + ysize = h * res_unit_tbl[res_unit] / yres; + + ratio = xsize / ysize; + + if (ratio < 0.5 || ratio > 2.0) return 0.0; /* reasonable ratio */ + + size = sqrt(xsize * xsize + ysize * ysize); + + if (size < 1.0 || size > 100.0) return 0.0; /* reasonable sensor size in mm */ + + return sqrt(36*36+24*24) / size; + +} + gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_valid) { @@ -96,12 +148,47 @@ gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_val gchar *make = exif_get_data_as_text(exif, "Exif.Image.Make"); gchar *model = exif_get_data_as_text(exif, "Exif.Image.Model"); gchar *software = exif_get_data_as_text(exif, "Exif.Image.Software"); + gchar *model2; + gchar *software2; + gint i; + + if (make) + { + gchar *x; + + g_strstrip(make); +#define REMOVE_SUFFIX(str,suff) \ +do { \ + if (g_str_has_suffix(str,suff)) \ + str[strlen(str)-(sizeof(suff)-1)] = 0; \ +} while(0) + REMOVE_SUFFIX(make," Corporation"); /* Pentax */ + REMOVE_SUFFIX(make," OPTICAL CO.,LTD"); /* OLYMPUS */ + } + if (model) + g_strstrip(model); + if (software) + g_strstrip(software); + /* remove superfluous spaces (pentax K100D) */ + for (i=0; software && software[i]; i++) + if (software[i] == ' ' && software[i+1] == ' ') + { + gint j; + + for (j=1; software[i+j]; j++) + if (software[i+j] != ' ') + break; + memmove(software+i+1, software+i+j, strlen(software+i+j)+1); + } + + model2 = remove_common_prefix(make, model); + software2 = remove_common_prefix(model2, software); text = g_strdup_printf("%s%s%s%s%s%s", (make) ? make : "", ((make) && (model)) ? " " : "", - (model) ? model : "", - (software) ? " (" : "", - (software) ? software : "", - (software) ? ")" : ""); + (model2) ? model2 : "", + (software2) ? " (" : "", + (software2) ? software2 : "", + (software2) ? ")" : ""); g_free(make); g_free(model); @@ -179,7 +266,27 @@ gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint *key_val n = exif_get_rational_as_double(exif, "Exif.Photo.FocalLength"); if (n == 0.0) return NULL; - return g_strdup_printf("%.2f mm", n); + return g_strdup_printf("%.0f mm", n); + } + if (strcmp(key, "fFocalLength35mmFilm") == 0) + { + gint n; + double f, c; + + if (exif_get_integer(exif, "Exif.Photo.FocalLengthIn35mmFilm", &n) && n != 0) + { + return g_strdup_printf("%d mm", n); + } + + f = exif_get_rational_as_double(exif, "Exif.Photo.FocalLength"); + c = get_crop_factor(exif); + + if (f != 0.0 && c != 0.0) + { + return g_strdup_printf("%.0f mm", f * c); + } + + return NULL; } if (strcmp(key, "fISOSpeedRating") == 0) { diff --git a/src/exif.c b/src/exif.c index 768d5bd5..bf5b177c 100644 --- a/src/exif.c +++ b/src/exif.c @@ -109,6 +109,36 @@ ExifFormatAttrib ExifFormatList[] = { * Data *----------------------------------------------------------------------------- */ +static ExifTextList ExifCompressionList[] = { + { 1, "Uncompressed" }, + { 2, "CCITT 1D" }, + { 3, "T4/Group 3 Fax" }, + { 4, "T6/Group 4 Fax" }, + { 5, "LZW" }, + { 6, "JPEG (old style)" }, + { 7, "JPEG" }, + { 8, "Adobe Deflate" }, + { 9, "JBIG B&W" }, + { 10, "JBIG Color" }, + { 32766, "Next" }, + { 32771, "CCIRLEW" }, + { 32773, "PackBits" }, + { 32809, "ThunderScan" }, + { 32895, "IT8CTPAD" }, + { 32896, "IT8LW" }, + { 32897, "IT8MP" }, + { 32898, "IT8BL" }, + { 32908, "PixasFilm" }, + { 32909, "PixasLog" }, + { 32946, "Deflate" }, + { 32947, "DCS" }, + { 34661, "JBIG" }, + { 34676, "SGILog" }, + { 34677, "SGILog24" }, + { 34712, "JPEF 2000" }, + { 34713, "Nikon NEF Compressed" }, + EXIF_TEXT_LIST_END +}; static ExifTextList ExifOrientationList[] = { { EXIF_ORIENTATION_UNKNOWN, N_("unknown") }, @@ -287,31 +317,40 @@ static ExifTextList ExifSubjectRangeList[] = { EXIF_TEXT_LIST_END }; +/* +Tag names should match to exiv2 keys, http://www.exiv2.org/metadata.html +Tags that don't match are not supported by exiv2 and should not be used anywhere in the code +*/ + ExifMarker ExifKnownMarkersList[] = { +{ 0x0100, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Image.ImageWidth", N_("Image Width"), NULL }, +{ 0x0101, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Image.ImageLength", N_("Image Height"), NULL }, +{ 0x0102, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.BitsPerSample", N_("Bits per Sample/Pixel"), NULL }, +{ 0x0103, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.Compression", N_("Compression"), ExifCompressionList }, { 0x010e, EXIF_FORMAT_STRING, -1, "Exif.Image.ImageDescription", N_("Image description"), NULL }, -{ 0x010f, EXIF_FORMAT_STRING, -1, "Exif.Image.Make", "Camera make", NULL }, +{ 0x010f, EXIF_FORMAT_STRING, -1, "Exif.Image.Make", "Camera make", NULL }, { 0x0110, EXIF_FORMAT_STRING, -1, "Exif.Image.Model", "Camera model", NULL }, -{ 0x0112, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.Orientation", N_("Orientation"), ExifOrientationList }, -{ 0x011a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Image.XResolution", "X resolution", NULL }, -{ 0x011b, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Image.YResolution", "Y Resolution", NULL }, +{ 0x0112, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.Orientation", N_("Orientation"), ExifOrientationList }, +{ 0x011a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Image.XResolution", "X resolution", NULL }, +{ 0x011b, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Image.YResolution", "Y Resolution", NULL }, { 0x0128, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.ResolutionUnit", "Resolution units", ExifUnitList }, { 0x0131, EXIF_FORMAT_STRING, -1, "Exif.Image.Software", "Firmware", NULL }, { 0x0132, EXIF_FORMAT_STRING, 20, "Exif.Image.DateTime", N_("Date"), NULL }, -{ 0x013e, EXIF_FORMAT_RATIONAL_UNSIGNED, 2, "Exif.Image.WhitePoint", "White point", NULL }, +{ 0x013e, EXIF_FORMAT_RATIONAL_UNSIGNED, 2, "Exif.Image.WhitePoint", "White point", NULL }, { 0x013f, EXIF_FORMAT_RATIONAL_UNSIGNED, 6, "Exif.Image.PrimaryChromaticities","Primary chromaticities", NULL }, { 0x0211, EXIF_FORMAT_RATIONAL_UNSIGNED, 3, "Exif.Image.YCbCrCoefficients", "YCbCy coefficients", NULL }, { 0x0213, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Image.YCbCrPositioning", "YCbCr positioning", ExifYCbCrPosList }, -{ 0x0214, EXIF_FORMAT_RATIONAL_UNSIGNED, 6, "Exif.Image.ReferenceBlackWhite", "Black white reference", NULL }, +{ 0x0214, EXIF_FORMAT_RATIONAL_UNSIGNED, 6, "Exif.Image.ReferenceBlackWhite","Black white reference", NULL }, { 0x8298, EXIF_FORMAT_STRING, -1, "Exif.Image.Copyright", N_("Copyright"), NULL }, -{ 0x8769, EXIF_FORMAT_LONG_UNSIGNED, 1, "ExifOffset", "SubIFD Exif offset", NULL }, +{ 0x8769, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Image.ExifTag", "SubIFD Exif offset", NULL }, /* subIFD follows */ -{ 0x829a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.ExposureTime", "Exposure time (seconds)", NULL }, +{ 0x829a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.ExposureTime", "Exposure time (seconds)", NULL }, { 0x829d, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FNumber", "FNumber", NULL }, { 0x8822, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.ExposureProgram", N_("Exposure program"), ExifExposureProgramList }, -{ 0x8824, EXIF_FORMAT_STRING, -1, "Exif.Photo.SpectralSensitivity", "Spectral Sensitivity", NULL }, +{ 0x8824, EXIF_FORMAT_STRING, -1, "Exif.Photo.SpectralSensitivity","Spectral Sensitivity", NULL }, { 0x8827, EXIF_FORMAT_SHORT_UNSIGNED, -1, "Exif.Photo.ISOSpeedRatings", N_("ISO sensitivity"), NULL }, -{ 0x8828, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.OECF", "Optoelectric conversion factor", NULL }, -{ 0x9000, EXIF_FORMAT_UNDEFINED, 4, "Exif.Photo.ExifVersion", "Exif version", NULL }, +{ 0x8828, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.OECF", "Optoelectric conversion factor", NULL }, +{ 0x9000, EXIF_FORMAT_UNDEFINED, 4, "Exif.Photo.ExifVersion", "Exif version", NULL }, { 0x9003, EXIF_FORMAT_STRING, 20, "Exif.Photo.DateTimeOriginal", N_("Date original"), NULL }, { 0x9004, EXIF_FORMAT_STRING, 20, "Exif.Photo.DateTimeDigitized", N_("Date digitized"), NULL }, { 0x9101, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.ComponentsConfiguration","Pixel format", NULL }, @@ -322,24 +361,24 @@ ExifMarker ExifKnownMarkersList[] = { { 0x9204, EXIF_FORMAT_RATIONAL, 1, "Exif.Photo.ExposureBiasValue", N_("Exposure bias"), NULL }, { 0x9205, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.MaxApertureValue", "Maximum aperture", NULL }, { 0x9206, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.SubjectDistance", N_("Subject distance"), NULL }, -{ 0x9207, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.MeteringMode", N_("Metering mode"), ExifMeteringModeList }, -{ 0x9208, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.LightSource", N_("Light source"), ExifLightSourceList }, +{ 0x9207, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.MeteringMode", N_("Metering mode"), ExifMeteringModeList }, +{ 0x9208, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.LightSource", N_("Light source"), ExifLightSourceList }, { 0x9209, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.Flash", N_("Flash"), ExifFlashList }, -{ 0x920a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FocalLength", N_("Focal length"), NULL }, -{ 0x9214, EXIF_FORMAT_SHORT_UNSIGNED, -1, "Exif.Photo.SubjectArea", "Subject area", NULL }, +{ 0x920a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FocalLength", N_("Focal length"), NULL }, +{ 0x9214, EXIF_FORMAT_SHORT_UNSIGNED, -1, "Exif.Photo.SubjectArea", "Subject area", NULL }, { 0x927c, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.MakerNote", "MakerNote", NULL }, -{ 0x9286, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.UserComment", "UserComment", NULL }, -{ 0x9290, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTime", "Subsecond time", NULL }, -{ 0x9291, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTimeOriginal", "Subsecond time original", NULL }, -{ 0x9292, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTimeDigitized", "Subsecond time digitized", NULL }, -{ 0xa000, EXIF_FORMAT_UNDEFINED, 4, "FlashPixVersion", "FlashPix version", NULL }, -{ 0xa001, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.ColorSpace", "Colorspace", ExifColorSpaceList }, +{ 0x9286, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.UserComment", "UserComment", NULL }, +{ 0x9290, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTime", "Subsecond time", NULL }, +{ 0x9291, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTimeOriginal","Subsecond time original", NULL }, +{ 0x9292, EXIF_FORMAT_STRING, -1, "Exif.Photo.SubSecTimeDigitized","Subsecond time digitized", NULL }, +{ 0xa000, EXIF_FORMAT_UNDEFINED, 4, "Exif.Photo.FlashpixVersion", "FlashPix version", NULL }, +{ 0xa001, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.ColorSpace", "Colorspace", ExifColorSpaceList }, /* ExifImageWidth, ExifImageHeight can also be unsigned short */ -{ 0xa002, EXIF_FORMAT_LONG_UNSIGNED, 1, "ExifImageWidth", N_("Width"), NULL }, -{ 0xa003, EXIF_FORMAT_LONG_UNSIGNED, 1, "ExifImageHeight", N_("Height"), NULL }, +{ 0xa002, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Photo.PixelXDimension", N_("Width"), NULL }, +{ 0xa003, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Photo.PixelYDimension", N_("Height"), NULL }, { 0xa004, EXIF_FORMAT_STRING, -1, "Exif.Photo.RelatedSoundFile", "Audio data", NULL }, -{ 0xa005, EXIF_FORMAT_LONG_UNSIGNED, 1, "ExifInteroperabilityOffset", "ExifR98 extension", NULL }, -{ 0xa20b, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FlashEnergy", "Flash strength", NULL }, +{ 0xa005, EXIF_FORMAT_LONG_UNSIGNED, 1, "ExifInteroperabilityOffset", "ExifR98 extension", NULL }, +{ 0xa20b, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FlashEnergy", "Flash strength", NULL }, { 0xa20c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.SpatialFrequencyResponse","Spatial frequency response", NULL }, { 0xa20e, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FocalPlaneXResolution", "X Pixel density", NULL }, { 0xa20f, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.FocalPlaneYResolution", "Y Pixel density", NULL }, @@ -347,26 +386,26 @@ ExifMarker ExifKnownMarkersList[] = { { 0x0214, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Exif.Photo.SubjectLocation", "Subject location", NULL }, { 0xa215, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.ExposureIndex", N_("ISO sensitivity"), NULL }, { 0xa217, EXIF_FORMAT_SHORT_UNSIGNED, -1, "Exif.Photo.SensingMethod", "Sensor type", ExifSensorList }, -{ 0xa300, EXIF_FORMAT_UNDEFINED, 1, "Exif.Photo.FileSource", "Source type", ExifSourceList }, +{ 0xa300, EXIF_FORMAT_UNDEFINED, 1, "Exif.Photo.FileSource", "Source type", ExifSourceList }, { 0xa301, EXIF_FORMAT_UNDEFINED, 1, "Exif.Photo.SceneType", "Scene type", ExifSceneList }, -{ 0xa302, EXIF_FORMAT_UNDEFINED, -1, "Exif.Image.CFAPattern", "Color filter array pattern", NULL }, +{ 0xa302, EXIF_FORMAT_UNDEFINED, -1, "Exif.Image.CFAPattern", "Color filter array pattern", NULL }, /* tags a4xx were added for Exif 2.2 (not just these - some above, as well) */ { 0xa401, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.CustomRendered", "Render process", ExifCustRenderList }, -{ 0xa402, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.ExposureMode", "Exposure mode", ExifExposureModeList }, -{ 0xa403, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.WhiteBalance", "White balance", ExifWhiteBalanceList }, +{ 0xa402, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.ExposureMode", "Exposure mode", ExifExposureModeList }, +{ 0xa403, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.WhiteBalance", "White balance", ExifWhiteBalanceList }, { 0xa404, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Photo.DigitalZoomRatio", "Digital zoom ratio", NULL }, -{ 0xa405, EXIF_FORMAT_SHORT_UNSIGNED, 1, "FocalLength35mmFilm", "Focal length (35mm)", NULL }, -{ 0xa406, EXIF_FORMAT_SHORT_UNSIGNED, 1, "SceneCapturetype", "Scene capture type", ExifSceneCaptureList }, -{ 0xa407, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.GainControl", "Gain control", ExifGainControlList }, +{ 0xa405, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.FocalLengthIn35mmFilm","Focal length (35mm)", NULL }, +{ 0xa406, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.SceneCaptureType", "Scene capture type", ExifSceneCaptureList }, +{ 0xa407, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.GainControl", "Gain control", ExifGainControlList }, { 0xa408, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.Contrast", "Contrast", ExifContrastList }, -{ 0xa409, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.Saturation", "Saturation", ExifSaturationList }, +{ 0xa409, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.Saturation", "Saturation", ExifSaturationList }, { 0xa40a, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.Sharpness", "Sharpness", ExifSharpnessList }, { 0xa40b, EXIF_FORMAT_UNDEFINED, -1, "Exif.Photo.DeviceSettingDescription","Device setting", NULL }, -{ 0xa40c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.SubjectDistanceRange", "Subject range", ExifSubjectRangeList }, +{ 0xa40c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Exif.Photo.SubjectDistanceRange","Subject range", ExifSubjectRangeList }, { 0xa420, EXIF_FORMAT_STRING, -1, "Exif.Photo.ImageUniqueID", "Image serial number", NULL }, /* place known, but undocumented or lesser used tags here */ { 0x00fe, EXIF_FORMAT_LONG_UNSIGNED, 1, "Exif.Image.NewSubfileType", NULL, NULL }, -{ 0x00ff, EXIF_FORMAT_SHORT_UNSIGNED, 1, "SubfileType", NULL, NULL }, +{ 0x00ff, EXIF_FORMAT_SHORT_UNSIGNED, 1, "SubfileType", NULL, NULL }, { 0x012d, EXIF_FORMAT_SHORT_UNSIGNED, 3, "Exif.Image.TransferFunction", NULL, NULL }, { 0x013b, EXIF_FORMAT_STRING, -1, "Exif.Image.Artist", "Artist", NULL }, { 0x013d, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Predictor", NULL, NULL }, @@ -380,7 +419,7 @@ ExifMarker ExifKnownMarkersList[] = { { 0x828e, EXIF_FORMAT_BYTE_UNSIGNED, -1, "Exif.Image.CFAPattern", NULL, NULL }, { 0x828f, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Exif.Image.BatteryLevel", NULL, NULL }, { 0x83bb, EXIF_FORMAT_LONG_UNSIGNED, -1, "IPTC/NAA", NULL, NULL }, -{ 0x8773, EXIF_FORMAT_UNDEFINED, -1, "ColorProfile", NULL, NULL }, +{ 0x8773, EXIF_FORMAT_UNDEFINED, -1, "Exif.Image.InterColorProfile", NULL, NULL }, { 0x8825, EXIF_FORMAT_LONG_UNSIGNED, 1, "GPSInfo", "SubIFD GPS offset", NULL }, { 0x8829, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Interlace", NULL, NULL }, { 0x882a, EXIF_FORMAT_SHORT, 1, "TimeZoneOffset", NULL, NULL }, @@ -1013,7 +1052,7 @@ static gint exif_jpeg_segment_find(unsigned char *data, guint size, return FALSE; } -static ExifMarker jpeg_color_marker = { 0x8773, EXIF_FORMAT_UNDEFINED, -1, "ColorProfile", NULL, NULL }; +static ExifMarker jpeg_color_marker = { 0x8773, EXIF_FORMAT_UNDEFINED, -1, "Exif.Image.InterColorProfile", NULL, NULL }; static gint exif_jpeg_parse_color(ExifData *exif, unsigned char *data, guint size) { @@ -1508,8 +1547,6 @@ ExifRational *exif_item_get_rational(ExifItem *item, gint *sign) return NULL; } - - const gchar *exif_get_tag_description_by_key(const gchar *key) { gint i; diff --git a/src/image.c b/src/image.c index 5f6a1bee..a80ef1ac 100644 --- a/src/image.c +++ b/src/image.c @@ -364,7 +364,7 @@ static gint image_post_process_color(ImageWindow *imd, gint start_row, ExifData if (imd->color_profile_use_image && exif) { - item = exif_get_item(exif, "ColorProfile"); + item = exif_get_item(exif, "Exif.Image.InterColorProfile"); if (!item) { gint cs; diff --git a/src/preferences.c b/src/preferences.c index 186e8526..ac40207e 100644 --- a/src/preferences.c +++ b/src/preferences.c @@ -28,6 +28,8 @@ #include "ui_misc.h" #include "ui_tabcomp.h" #include "ui_utildlg.h" +#include "bar_exif.h" +#include "exif.h" #include @@ -330,6 +332,11 @@ static void config_window_apply(void) if (buf && strlen(buf) > 0) color_profile_screen_file = g_strdup(buf); #endif + for (i=0; ExifUIList[i].key; i++) + { + ExifUIList[i].current = ExifUIList[i].temp; + } + l_conf = layout_config_get(layout_widget, &new_style); if (new_style != layout_style || @@ -396,6 +403,41 @@ static void config_window_apply_cb(GtkWidget *widget, gpointer data) *----------------------------------------------------------------------------- */ +static void exif_item_cb(GtkWidget *combo, gpointer data) +{ + gint *option = data; + *option = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); +} + +static void exif_item(GtkWidget *table, gint column, gint row, + const gchar *text, gint option, gint *option_c) +{ + GtkWidget *combo; + gint current = 0; + + *option_c = option; + + pref_table_label(table, column, row, text, 0.0); + + combo = gtk_combo_box_new_text(); + + /* note: the order is important, it must match the values of + * EXIF_UI_OFF, _IFSET, _ON */ + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Never")); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("If set")); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), _("Always")); + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), option); + + g_signal_connect(G_OBJECT(combo), "changed", + G_CALLBACK(exif_item_cb), option_c); + + gtk_table_attach(GTK_TABLE(table), combo, + column + 1, column + 2, row, row + 1, + GTK_EXPAND | GTK_FILL, 0, 0, 0); + gtk_widget_show(combo); +} + static void quality_menu_cb(GtkWidget *combo, gpointer data) { gint *option = data; @@ -1217,6 +1259,40 @@ static void config_window_create(void) gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); + /* exif tab */ + + scrolled = gtk_scrolled_window_new(NULL, NULL); + gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + label = gtk_label_new(_("Exif")); + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label); + gtk_widget_show(scrolled); + + viewport = gtk_viewport_new(NULL, NULL); + gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); + gtk_container_add(GTK_CONTAINER(scrolled), viewport); + gtk_widget_show(viewport); + + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(viewport), vbox); + gtk_widget_show(vbox); + + group = pref_group_new(vbox, FALSE, _("What to show in properties dialog:"), + GTK_ORIENTATION_VERTICAL); + table = pref_table_new(group, 2, 2, FALSE, FALSE); + + for (i = 0; ExifUIList[i].key; i++) + { + static gint cc; + const gchar *title; + + title = exif_get_description_by_key(ExifUIList[i].key); + exif_item(table, 0, i, title, ExifUIList[i].current, + &ExifUIList[i].temp); + } + /* advanced entry tab */ scrolled = gtk_scrolled_window_new(NULL, NULL); diff --git a/src/rcfile.c b/src/rcfile.c index 159d199b..19d75e43 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -16,6 +16,7 @@ #include "filelist.h" #include "slideshow.h" #include "ui_fileops.h" +#include "bar_exif.h" /* @@ -437,6 +438,13 @@ void save_options(void) write_int_option(f, "divider_position_h", window_hdivider_pos); write_int_option(f, "divider_position_v", window_vdivider_pos); + fprintf(f,"\n##### Exif #####\n# 0: never\n# 1: if set\n# 2: always\n"); + for (i = 0; ExifUIList[i].key; i++) + { + fprintf(f,"exif_"); + write_int_option(f, (gchar *)ExifUIList[i].key, ExifUIList[i].current); + } + fprintf(f,"######################################################################\n"); fprintf(f,"# end of Geeqie config file #\n"); fprintf(f,"######################################################################\n"); @@ -464,6 +472,9 @@ void load_options(void) gchar value_all[1024]; gint c,l,i; + for (i = 0; ExifUIList[i].key; i++) + ExifUIList[i].current = ExifUIList[i].default_value; + rc_path = g_strconcat(homedir(), "/", GQVIEW_RC_DIR, "/", RC_FILE_NAME, NULL); rc_pathl = path_from_utf8(rc_path); @@ -753,6 +764,12 @@ void load_options(void) window_vdivider_pos = read_int_option(f, option, "divider_position_v", value, window_vdivider_pos); + if (0 == strncasecmp(option, "exif_", 5)) + { + for (i = 0; ExifUIList[i].key; i++) + if (0 == strcasecmp(option+5, ExifUIList[i].key)) + ExifUIList[i].current = strtol(value, NULL, 10); + } } fclose(f); -- 2.20.1