From 7953e558b89d1423c2843c6e5cb7e5a9718419cc Mon Sep 17 00:00:00 2001 From: John Ellis Date: Sat, 11 Jun 2005 01:09:30 +0000 Subject: [PATCH] Fri Jun 10 20:57:42 2005 John Ellis * exif.c (exif_parse_IFD_table): Fix offset count before testing against buffer size. * exif.h: Make exif_text_list_find_value available. * format_canon.c: Fix copy's length when duping Canon.SerialNumber, and adjust several text descriptions. * format_fuji.c: Remove "MkN." text from tag names. * format_nikon.c: Fix offset count before testing against buffer size, and remove "MkN." text from tag names. Add several new tags. * format_olympus.[ch]: New files for olympus makernote. * format_raw.c: Add exif olympus hook. * src/Makefile.am: Add format_olympus.[ch]. --- ChangeLog | 14 +++ TODO | 4 +- src/Makefile.am | 2 + src/exif.c | 10 +- src/exif.h | 2 + src/format_canon.c | 12 +- src/format_fuji.c | 30 ++--- src/format_nikon.c | 176 ++++++++++++++++++---------- src/format_olympus.c | 266 +++++++++++++++++++++++++++++++++++++++++++ src/format_olympus.h | 38 +++++++ src/format_raw.c | 2 + 11 files changed, 471 insertions(+), 85 deletions(-) create mode 100644 src/format_olympus.c create mode 100644 src/format_olympus.h diff --git a/ChangeLog b/ChangeLog index 575d32aa..f694a4e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Fri Jun 10 20:57:42 2005 John Ellis + + * exif.c (exif_parse_IFD_table): Fix offset count before testing + against buffer size. + * exif.h: Make exif_text_list_find_value available. + * format_canon.c: Fix copy's length when duping Canon.SerialNumber, and + adjust several text descriptions. + * format_fuji.c: Remove "MkN." text from tag names. + * format_nikon.c: Fix offset count before testing against buffer size, + and remove "MkN." text from tag names. Add several new tags. + * format_olympus.[ch]: New files for olympus makernote. + * format_raw.c: Add exif olympus hook. + * src/Makefile.am: Add format_olympus.[ch]. + Fri Jun 10 02:19:26 2005 John Ellis * pan-view.c: Add exif date sorting option to right click menu, and diff --git a/TODO b/TODO index b2f726d7..b3e996cf 100644 --- a/TODO +++ b/TODO @@ -33,8 +33,8 @@ Major: > canon_read_int can be substituted with, or wrap exif_get_int16/32. > CR2 tiff code can now use exif_tiff_directory_offset. - > support olympus MakerNote, investigate RAW - > support konica / minolta MakerNote, investigate RAW + d> support olympus MakerNote, investigate RAW (raw embedded jpeg appears to be tiny). + > support konica / minolta MakerNote, investigate RAW. > exif.c parser should not be using EXIF tags during tiff directory search for EXIF tag. diff --git a/src/Makefile.am b/src/Makefile.am index 555b3b14..e10659aa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,6 +90,8 @@ gqview_SOURCES = \ format_fuji.h \ format_nikon.c \ format_nikon.h \ + format_olympus.c \ + format_olympus.h \ format_raw.c \ format_raw.h \ fullscreen.c \ diff --git a/src/exif.c b/src/exif.c index 03918dfb..fb9b06b8 100644 --- a/src/exif.c +++ b/src/exif.c @@ -562,7 +562,7 @@ static GString *string_append_raw_bytes(GString *string, gpointer data, gint ne) return string; } -static gchar *text_list_find_value(ExifTextList *list, guint value) +gchar *exif_text_list_find_value(ExifTextList *list, guint value) { gchar *result = NULL; gint i; @@ -865,10 +865,10 @@ gint exif_parse_IFD_table(ExifData *exif, if (size < offset + 2) return -1; count = exif_byte_get_int16(tiff + offset, bo); + offset += 2; /* Entries and next IFD offset must be readable */ if (size < offset + count * EXIF_TIFD_SIZE + 4) return -1; - offset += 2; for (i = 0; i < count; i++) { @@ -1181,7 +1181,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) val = (unsigned char)(((signed char *)data)[0]); } - result = text_list_find_value(marker->list, (guint)val); + result = exif_text_list_find_value(marker->list, (guint)val); string = g_string_append(string, result); g_free(result); } @@ -1198,7 +1198,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) { gchar *result; - result = text_list_find_value(marker->list, ((unsigned short *)data)[0]); + result = exif_text_list_find_value(marker->list, ((unsigned short *)data)[0]); string = g_string_append(string, result); g_free(result); } @@ -1493,7 +1493,7 @@ static gchar *exif_get_formatted_by_key(ExifData *exif, const gchar *key, gint * if (!exif_get_integer(exif, "Flash", &n)) return NULL; /* Exif 2.1 only defines first 3 bits */ - if (n <= 0x07) return g_strdup(text_list_find_value(ExifFlashList, n)); + if (n <= 0x07) return g_strdup(exif_text_list_find_value(ExifFlashList, n)); /* must be Exif 2.2 */ string = g_string_new(""); diff --git a/src/exif.h b/src/exif.h index 3f313b6f..f8783df9 100644 --- a/src/exif.h +++ b/src/exif.h @@ -231,6 +231,8 @@ gint exif_tiff_directory_offset(unsigned char *data, const guint len, guint *offset, ExifByteOrder *bo); gint exif_tiff_parse(ExifData *exif, unsigned char *tiff, guint size, ExifMarker *list); +gchar *exif_text_list_find_value(ExifTextList *list, guint value); + #endif diff --git a/src/format_canon.c b/src/format_canon.c index e4ac6373..31abfc4f 100644 --- a/src/format_canon.c +++ b/src/format_canon.c @@ -505,14 +505,14 @@ static ExifTextList CanonSet1FlashMode[] = { { 2, "on" }, { 3, "red-eye reduction" }, { 4, "slow sync" }, - { 5, "red-eye reduction (auto)" }, - { 6, "red-eye reduction (on)" }, + { 5, "auto + red-eye reduction" }, + { 6, "on + red-eye reduction" }, { 16, "external flash" }, EXIF_TEXT_LIST_END }; static ExifTextList CanonSet1DriveMode[] = { - { 0, "single" }, + { 0, "single or timer" }, { 1, "continuous" }, EXIF_TEXT_LIST_END }; @@ -548,7 +548,7 @@ static ExifTextList CanonSet1ShootingMode[] = { { 8, "portrait" }, { 9, "sports" }, { 10, "macro" }, - { 11, "panoramic focus" }, + { 11, "pan focus" }, EXIF_TEXT_LIST_END }; @@ -663,7 +663,7 @@ EXIF_MARKER_LIST_END static ExifTextList CanonSet2WhiteBalance[] = { { 0, "auto" }, - { 1, "daylight" }, + { 1, "sunny" }, { 2, "cloudy" }, { 3, "tungsten" }, { 4, "fluorescent" }, @@ -834,7 +834,7 @@ static void canon_mknote_parse_convert(ExifData *exif) n = (guint32)((guint32 *)(result->data))[0]; text = g_strdup_printf("%04X%05d", n & 0xffff0000 >> 8, n & 0x0000ffff); - l = strlen(text); + l = strlen(text) + 1; item = exif_item_new(marker.format, marker.tag, l, &marker); memcpy(item->data, text, l); g_free(text); diff --git a/src/format_fuji.c b/src/format_fuji.c index 53e9fe42..6eef3666 100644 --- a/src/format_fuji.c +++ b/src/format_fuji.c @@ -149,22 +149,22 @@ static ExifTextList FujiTag[]= { static ExifMarker FujiExifMarkersList[] = { -{ 0x1000, EXIF_FORMAT_STRING, 8, "MkN.Fuji.Quality", "Quality", NULL }, -{ 0x1001, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.Sharpness", "Sharpness", FujiTagSharpness }, -{ 0x1002, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.WhiteBalance","White balance",FujiTagWhiteBalance }, -{ 0x1003, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.Color", "Color", FujiTagColorTone }, -{ 0x1004, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.Tone", "Tone", FujiTagColorTone }, -{ 0x1010, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.FlashMode", "Flash mode", FujiTagFlashMode }, -{ 0x1011, EXIF_FORMAT_RATIONAL, 1, "MkN.Fuji.FlashStrength", "Flash strength", NULL }, -{ 0x1020, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.Macro", "Macro", FujiTagOffOn }, -{ 0x1021, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.FocusMode", "Focus mode", FujiTagFocusMode }, -{ 0x1030, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.SlowSync", "Slow synchro", FujiTagOffOn }, -{ 0x1031, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.PictureMode", "Picture mode", FujiTagPictureMode }, -{ 0x1100, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.ContTake/Bracket", +{ 0x1000, EXIF_FORMAT_STRING, 8, "Fuji.Quality", "Quality", NULL }, +{ 0x1001, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.Sharpness", "Sharpness", FujiTagSharpness }, +{ 0x1002, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.WhiteBalance", "White balance",FujiTagWhiteBalance }, +{ 0x1003, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.Color", "Color", FujiTagColorTone }, +{ 0x1004, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.Tone", "Tone", FujiTagColorTone }, +{ 0x1010, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.FlashMode", "Flash mode", FujiTagFlashMode }, +{ 0x1011, EXIF_FORMAT_RATIONAL, 1, "Fuji.FlashStrength", "Flash strength", NULL }, +{ 0x1020, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.Macro", "Macro", FujiTagOffOn }, +{ 0x1021, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.FocusMode", "Focus mode", FujiTagFocusMode }, +{ 0x1030, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.SlowSync", "Slow synchro", FujiTagOffOn }, +{ 0x1031, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.PictureMode", "Picture mode", FujiTagPictureMode }, +{ 0x1100, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.ContTake/Bracket", "Continuous / Auto bracket", FujiTagOffOn }, -{ 0x1300, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.BlurWarning", "Blue warning", FujiTagNoYes }, -{ 0x1301, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.FocusWarning","Focus warning",FujiTagNoYes }, -{ 0x1302, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Fuji.AEWarning", "AE warning", FujiTagNoYes }, +{ 0x1300, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.BlurWarning", "Blue warning", FujiTagNoYes }, +{ 0x1301, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.FocusWarning", "Focus warning",FujiTagNoYes }, +{ 0x1302, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Fuji.AEWarning", "AE warning", FujiTagNoYes }, EXIF_MARKER_LIST_END }; diff --git a/src/format_nikon.c b/src/format_nikon.c index f5fcce6a..a3e9f410 100644 --- a/src/format_nikon.c +++ b/src/format_nikon.c @@ -109,9 +109,8 @@ static guint nikon_tiff_table(unsigned char *data, const guint len, guint offset if (len < offset + 2) return FALSE; count = exif_byte_get_int16(data + offset, bo); - - if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0; offset += 2; + if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0; for (i = 0; i < count; i++) { @@ -228,18 +227,17 @@ static ExifTextList NikonTag[]= { #endif static ExifMarker NikonExifMarkersList1[] = { -{ 0x0002, EXIF_FORMAT_STRING, 6, "MkN.Nikon.unknown", NULL, NULL }, -{ 0x0003, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.Quality", "Quality", NikonTagQuality }, -{ 0x0004, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.ColorMode", "Color mode", NikonTagColorMode }, -{ 0x0005, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.ImageAdjustment", +{ 0x0002, EXIF_FORMAT_STRING, 6, "Nikon.unknown", NULL, NULL }, +{ 0x0003, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.Quality", "Quality", NikonTagQuality }, +{ 0x0004, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.ColorMode", "Color mode", NikonTagColorMode }, +{ 0x0005, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.ImageAdjustment", "Image adjustment", NikonTagImgAdjust }, -{ 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.ISOSensitivity", +{ 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.ISOSensitivity", "ISO sensitivity", NikonTagISOSensitivity }, -{ 0x0007, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.WhiteBalance", - "White balance", NikonTagWhiteBalance }, -{ 0x0008, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "MkN.Nikon.Focus", "Focus", NULL }, -{ 0x000a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "MkN.Nikon.DigitalZoom","Digital zoom", NULL }, -{ 0x000b, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.Converter", "Converter", NikonTagConverter }, +{ 0x0007, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.WhiteBalance", "White balance",NikonTagWhiteBalance }, +{ 0x0008, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Nikon.Focus", "Focus", NULL }, +{ 0x000a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Nikon.DigitalZoom", "Digital zoom", NULL }, +{ 0x000b, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.Converter", "Converter", NikonTagConverter }, EXIF_MARKER_LIST_END }; @@ -264,8 +262,19 @@ static ExifTextList NikonTag2FlashComp[]= { EXIF_TEXT_LIST_END }; +static ExifTextList NikonTag2LensType[]= { + { 0, "AF non D" }, + { 1, "manual" }, + { 2, "AF-D or AF-s" }, + { 6, "AF-D G" }, + { 10, "AF-D VR" }, + EXIF_TEXT_LIST_END +}; + static ExifTextList NikonTag2FlashUsed[]= { { 0, "no" }, + { 4, "unit unknown" }, + { 7, "external" }, { 9, "yes" }, EXIF_TEXT_LIST_END }; @@ -283,63 +292,71 @@ static ExifTextList NikonTagi2Saturation[]= { #endif static ExifMarker NikonExifMarkersList2[] = { -{ 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 2, "MkN.Nikon.ISOSpeed", "ISO speed", NULL }, -{ 0x0003, EXIF_FORMAT_STRING, -1, "MkN.Nikon.ColorMode", "Color mode", NULL }, -{ 0x0004, EXIF_FORMAT_STRING, -1, "MkN.Nikon.Quality", "Quality", NULL }, -{ 0x0005, EXIF_FORMAT_STRING, -1, "MkN.Nikon.WhiteBalance", - "White balance", NULL }, -{ 0x0006, EXIF_FORMAT_STRING, -1, "MkN.Nikon.Sharpening", "Sharpening", NULL }, -{ 0x0007, EXIF_FORMAT_STRING, -1, "MkN.Nikon.FocusMode", "Focus mode", NULL }, -{ 0x0008, EXIF_FORMAT_STRING, -1, "MkN.Nikon.FlashSetting", - "Flash setting", NULL }, -{ 0x0009, EXIF_FORMAT_STRING, -1, "MkN.Nikon.AutoFlashMode","Auto flash mode",NULL }, -{ 0x000b, EXIF_FORMAT_SHORT, 1, "MkN.Nikon.WhiteBalanceBias", +{ 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Nikon.ISOSpeed", "ISO speed", NULL }, +{ 0x0003, EXIF_FORMAT_STRING, -1, "Nikon.ColorMode", "Color mode", NULL }, +{ 0x0004, EXIF_FORMAT_STRING, -1, "Nikon.Quality", "Quality", NULL }, +{ 0x0005, EXIF_FORMAT_STRING, -1, "Nikon.WhiteBalance", "White balance",NULL }, +{ 0x0006, EXIF_FORMAT_STRING, -1, "Nikon.Sharpening", "Sharpening", NULL }, +{ 0x0007, EXIF_FORMAT_STRING, -1, "Nikon.FocusMode", "Focus mode", NULL }, +{ 0x0008, EXIF_FORMAT_STRING, -1, "Nikon.FlashSetting", "Flash setting",NULL }, +{ 0x0009, EXIF_FORMAT_STRING, -1, "Nikon.AutoFlashMode","Auto flash mode",NULL }, +{ 0x000b, EXIF_FORMAT_SHORT, 1, "Nikon.WhiteBalanceBias", "White balance bias value", NULL }, -/* { 0x000c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.WhiteBalanceCoeff", - "White balance red/blue coefficents", NULL }, */ -/* { 0x000f, EXIF_FORMAT_STRING, -1, "MkN.Nikon.ISOSelect", "ISO selection",NULL }, */ -{ 0x0012, EXIF_FORMAT_UNDEFINED, 4, "MkN.Nikon.FlashCompensation", +/* { 0x000c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.WhiteBalanceRB", + "White balance red/blue coefficients", NULL }, */ +/* { 0x000f, EXIF_FORMAT_STRING, -1, "Nikon.ISOSelect", "ISO selection",NULL }, */ +{ 0x0012, EXIF_FORMAT_UNDEFINED, 4, "Nikon.FlashCompensation", "Flash compensation", NikonTag2FlashComp }, -{ 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2, "MkN.Nikon.ISOSpeedRequest", +{ 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Nikon.ISOSpeedRequest", "ISO speed requested", NULL }, -{ 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4, "MkN.Nikon.CornerCoord", +{ 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4, "Nikon.CornerCoord", "Corner coordinates", NULL }, -{ 0x0018, EXIF_FORMAT_UNDEFINED, 4, "MkN.Nikon.FlashBracketCompensation", +{ 0x0018, EXIF_FORMAT_UNDEFINED, 4, "Nikon.FlashBracketCompensation", "Flash bracket compensation", NikonTag2FlashComp }, -{ 0x0019, EXIF_FORMAT_RATIONAL, 1, "MkN.Nikon.AEBracketCompensation", +{ 0x0019, EXIF_FORMAT_RATIONAL, 1, "Nikon.AEBracketCompensation", "AE bracket compensation", NULL }, -{ 0x0080, EXIF_FORMAT_STRING, -1, "MkN.Nikon.ImageAdjustment", +{ 0x0080, EXIF_FORMAT_STRING, -1, "Nikon.ImageAdjustment", "Image adjustment", NULL }, -{ 0x0081, EXIF_FORMAT_STRING, -1, "MkN.Nikon.Contrast", "Contrast", NULL }, -{ 0x0082, EXIF_FORMAT_STRING, -1, "MkN.Nikon.AuxLens","Aux lens adapter", NULL }, -{ 0x0083, EXIF_FORMAT_BYTE_UNSIGNED, -1, "MkN.Nikon.LensType", "Lens type", NULL }, -{ 0x0084, EXIF_FORMAT_RATIONAL_UNSIGNED, -1, "MkN.Nikon.LensFocalLength", +{ 0x0081, EXIF_FORMAT_STRING, -1, "Nikon.Contrast", "Contrast", NULL }, +{ 0x0082, EXIF_FORMAT_STRING, -1, "Nikon.AuxLens", "Aux lens adapter", NULL }, +{ 0x0083, EXIF_FORMAT_BYTE_UNSIGNED, -1, "Nikon.LensType", "Lens type", NikonTag2LensType }, +{ 0x0084, EXIF_FORMAT_RATIONAL_UNSIGNED, -1, "Nikon.LensFocalLength", "Lens min/max focal length and aperture", NULL }, -{ 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.ManualFocusDistance", +{ 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.ManualFocusDistance", "Manual focus distance", NULL }, -{ 0x0086, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.DigitalZoomFactor", - "Digital zoom facotr", NULL }, -{ 0x0087, EXIF_FORMAT_BYTE_UNSIGNED, 1, "MkN.Nikon.FlashUsed", "Flash used", NikonTag2FlashUsed }, -{ 0x0088, EXIF_FORMAT_UNDEFINED, -1, "MkN.Nikon.AutoFocusArea", NULL, NULL }, -/* { 0x0089, EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Nikon.Bracket/ShootingMode", NULL, NULL }, */ -{ 0x008d, EXIF_FORMAT_STRING, -1, "MkN.Nikon.ColorMode", "Color mode", NULL }, -{ 0x008f, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.SceneMode", NULL, NULL }, -{ 0x0090, EXIF_FORMAT_STRING, -1, "MkN.Nikon.LightingType", "Lighting type", NULL }, -{ 0x0092, EXIF_FORMAT_SHORT, 1, "MkN.Nikon.HueAdjust", "Hue adjustment", NULL }, -/* { 0x0094, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Nikon.Saturation", "Saturation", NikonTag2Saturation }, */ -{ 0x0095, EXIF_FORMAT_STRING, -1, "MkN.Nikon.NoiseReduction", "Noise reduction", NULL }, -{ 0x00a7, EXIF_FORMAT_LONG_UNSIGNED, 1, "MkN.Nikon.ShutterCount", "Shutter release count", NULL }, -{ 0x00a9, EXIF_FORMAT_STRING, -1, "MkN.Nikon.ImageOptimization", "Image optimization", NULL }, -{ 0x00aa, EXIF_FORMAT_STRING, -1, "MkN.Nikon.Saturation", "Saturation", NULL }, -{ 0x00ab, EXIF_FORMAT_STRING, -1, "MkN.Nikon.DigitalVariProg", "Digital Vari-program", NULL }, +{ 0x0086, EXIF_FORMAT_RATIONAL, 1, "Nikon.DigitalZoomFactor", + "Digital zoom factor", NULL }, +{ 0x0087, EXIF_FORMAT_BYTE_UNSIGNED, 1, "Nikon.FlashUsed", "Flash used", NikonTag2FlashUsed }, +{ 0x0088, EXIF_FORMAT_UNDEFINED, 4, "Nikon.AutoFocusArea","Auto focus area",NULL }, +/* { 0x0089, EXIF_FORMAT_SHORT_UNSIGNED, -1, "Nikon.Bracket/ShootingMode", NULL, NULL }, */ +{ 0x008d, EXIF_FORMAT_STRING, -1, "Nikon.ColorMode", "Color mode", NULL }, +{ 0x008f, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.SceneMode", "Scene mode", NULL }, +{ 0x0090, EXIF_FORMAT_STRING, -1, "Nikon.LightingType", "Lighting type",NULL }, +{ 0x0092, EXIF_FORMAT_SHORT, 1, "Nikon.HueAdjust", "Hue adjustment",NULL }, +/* { 0x0094, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Nikon.Saturation", "Saturation", NikonTag2Saturation }, */ +{ 0x0095, EXIF_FORMAT_STRING, -1, "Nikon.NoiseReduction", "Noise reduction", NULL }, +{ 0x00a7, EXIF_FORMAT_LONG_UNSIGNED, 1, "Nikon.ShutterCount", "Shutter release count", NULL }, +{ 0x00a9, EXIF_FORMAT_STRING, -1, "Nikon.ImageOptimization", "Image optimization", NULL }, +{ 0x00aa, EXIF_FORMAT_STRING, -1, "Nikon.Saturation", "Saturation", NULL }, +{ 0x00ab, EXIF_FORMAT_STRING, -1, "Nikon.DigitalVariProg", "Digital Vari-program", NULL }, EXIF_MARKER_LIST_END }; +static ExifTextList NikonAFPoint[]= { + { 0, "center" }, + { 1, "top" }, + { 2, "bottom" }, + { 3, "left" }, + { 4, "right" }, + EXIF_TEXT_LIST_END +}; + gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset, guint size, ExifByteOrder bo) { unsigned char *data; + ExifItem *item; if (offset + 8 + 4 >= size) return FALSE; @@ -368,16 +385,61 @@ gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset, { return FALSE; } - return TRUE; } - /* Nikon tag format 3 uses format 2 tags without "Nikon" and tiff header */ - if (exif_parse_IFD_table(exif, tiff, offset, size, - bo, 0, NikonExifMarkersList2) != 0) + else if (exif_parse_IFD_table(exif, tiff, offset, size, + bo, 0, NikonExifMarkersList2) != 0) { return FALSE; } - return FALSE; + item = exif_get_item(exif, "Nikon.AutoFocusArea"); + if (item && item->data_len == 4 * sizeof(guchar)) + { + static ExifMarker marker = { 0x0088, EXIF_FORMAT_STRING, -1, + "Nikon.AutoFocusPoint", "Auto focus point", NULL }; + guchar *array = item->data; + const gchar *text; + + text = exif_text_list_find_value(NikonAFPoint, (gint)array[1]); + if (text) + { + gint l; + + l = strlen(text) + 1; + item = exif_item_new(marker.format, marker.tag, l, &marker); + memcpy(item->data, text, l); + + exif->items = g_list_prepend(exif->items, item); + } + } + + item = exif_get_item(exif, "Nikon.ISOSpeed"); + if (item && item->data_len == 2 * 2) + { + static ExifMarker marker = { 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 1, + "ISOSpeedRatings", "ISO speed", NULL }; + ExifItem *shadow; + + shadow = exif_item_new(marker.format, marker.tag, 1, &marker); + memcpy(shadow->data, item->data + 2, 2); + + exif->items = g_list_prepend(exif->items, shadow); + } + + item = exif_get_item(exif, "Nikon.WhiteBalance"); + if (item && item->format == EXIF_FORMAT_STRING) + { + static ExifMarker marker = { 0x0005, EXIF_FORMAT_STRING, -1, + "LightSource", "Light source", NULL }; + ExifItem *shadow; + + shadow = exif_item_new(marker.format, marker.tag, item->data_len, &marker); + memcpy(shadow->data, item->data, item->data_len); + + exif->items = g_list_prepend(exif->items, shadow); + } + + return TRUE; } diff --git a/src/format_olympus.c b/src/format_olympus.c new file mode 100644 index 00000000..b0fa5720 --- /dev/null +++ b/src/format_olympus.c @@ -0,0 +1,266 @@ +/* + * GQView + * (C) 2005 John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include +#include +#include + +#include + +#include "intl.h" + +#include "format_olympus.h" +#include "format_raw.h" + +#include "exif.h" + + +/* + *----------------------------------------------------------------------------- + * EXIF Makernote for Olympus + *----------------------------------------------------------------------------- + */ + +static ExifTextList KonMinTagColorMode[]= { + { 0, "natural" }, + { 1, "black and white" }, + { 2, "vivid" }, + { 3, "solarization" }, + { 4, "Adobe RGB" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList KonMinTagQuality[]= { + { 0, "raw" }, + { 1, "super fine" }, + { 2, "find" }, + { 3, "standard" }, + { 4, "extra fine" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagJpegQuality[]= { + { 1, "standard" }, + { 2, "high" }, + { 3, "super high" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagMacro[]= { + { 0, "off" }, + { 1, "on" }, + { 2, "view" }, + { 3, "manual" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagFlashMode[]= { + { 0, "auto" }, + { 1, "red-eye reduction" }, + { 2, "fill" }, + { 3, "off" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagFocusMode[]= { + { 0, "auto" }, + { 1, "manual" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagSharpness[]= { + { 0, "normal" }, + { 1, "hard" }, + { 2, "soft" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusTagContrast[]= { + { 0, "hard" }, + { 1, "normal" }, + { 2, "soft" }, + EXIF_TEXT_LIST_END +}; + +#if 0 +static ExifTextList OlympusTag[]= { + { , "" }, + { , "" }, + EXIF_TEXT_LIST_END +}; +#endif + + +static ExifMarker OlympusExifMarkersList[] = { +{ 0x0001, EXIF_FORMAT_LONG_UNSIGNED, -1, "Konica/MinoltaSettings", "Konica / Minolta settings", NULL }, +{ 0x0003, EXIF_FORMAT_LONG_UNSIGNED, -1, "Konica/MinoltaSettings", "Konica / Minolta settings", NULL }, +{ 0x0040, EXIF_FORMAT_LONG_UNSIGNED, -1, "CompressedImageSize", "Compressed image size", NULL }, +{ 0x0081, EXIF_FORMAT_LONG_UNSIGNED, 1, "ThumbnailOffset", "Thumbnail offset", NULL }, +{ 0x0088, EXIF_FORMAT_LONG_UNSIGNED, 1, "ThumbnailOffset", "Thumbnail offset", NULL }, +{ 0x0089, EXIF_FORMAT_LONG_UNSIGNED, 1, "ThumbnailLength", "Thumbnail length", NULL }, +{ 0x0101, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Konica/Minolta.ColorMode", "Color mode", KonMinTagColorMode }, +{ 0x0102, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Konica/Minolta.Quality", "Quality", KonMinTagQuality }, +{ 0x0103, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Konica/Minolta.Quality", "Quality", KonMinTagQuality }, +{ 0x0200, EXIF_FORMAT_LONG_UNSIGNED, 3, "Olympus.SpecialMode", "Special mode", NULL }, +{ 0x0201, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.JpegQuality", "Jpeg quality", OlympusTagJpegQuality }, +{ 0x0202, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.Macro", "Macro", OlympusTagMacro }, +{ 0x0204, EXIF_FORMAT_RATIONAL_UNSIGNED, 1, "Olympus.DigitalZoom", "Digital zoom", NULL }, +{ 0x0207, EXIF_FORMAT_STRING, -1, "Olympus.Firmware", "Firmware version", NULL }, +{ 0x0208, EXIF_FORMAT_STRING, -1, "Olympus.PictureInfo", "Picture info", NULL }, +{ 0x0209, EXIF_FORMAT_UNDEFINED, -1, "Olympus.CameraID", "Camera ID", NULL }, +{ 0x020b, EXIF_FORMAT_LONG_UNSIGNED, 1, "Epson.ImageWidth", "Image width", NULL }, +{ 0x020c, EXIF_FORMAT_LONG_UNSIGNED, 1, "Epson.ImageHeight", "Image height", NULL }, +{ 0x020d, EXIF_FORMAT_STRING, -1, "Epson.Manufacturer", "Manufacturer", NULL }, +{ 0x0e00, EXIF_FORMAT_BYTE, -1, "Olympus.PrintImageMatching", "Print image matching", NULL }, +{ 0x1004, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.FlashMode", "Flash mode", OlympusTagFlashMode }, +{ 0x1006, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.Bracket", "Bracket", NULL }, +{ 0x100b, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.FocusMode", "Focus mode", OlympusTagFocusMode }, +{ 0x100c, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.FocusDistance", "Focus distance", NULL }, +{ 0x100d, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.Zoom", "Zoom", NULL }, +{ 0x1006, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.MacroFocus", "Macro focus", NULL }, +{ 0x100f, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.Sharpness", "Sharpness", OlympusTagSharpness }, +{ 0x1011, EXIF_FORMAT_SHORT_UNSIGNED, 9, "Olympus.ColorMatrix", "Color matrix", NULL }, +{ 0x1012, EXIF_FORMAT_SHORT_UNSIGNED, 4, "Olympus.BlackLevel", "Black level", NULL }, +{ 0x1015, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Olympus.WhiteBalance", "White balance", NULL }, +{ 0x1017, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Olympus.RedBias", "Red bias", NULL }, +{ 0x1018, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Olympus.BlueBias", "Blue bias", NULL }, +{ 0x101a, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.SerialNumber", "Serial number", NULL }, +{ 0x1023, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.FlashBias", "Flash bias", NULL }, +{ 0x1029, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.Contrast", "Contrast", OlympusTagContrast }, +{ 0x102a, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.SharpnessFactor", "Sharpness factor", NULL }, +{ 0x102b, EXIF_FORMAT_SHORT_UNSIGNED, 6, "Olympus.ColorControl", "Color control", NULL }, +{ 0x102c, EXIF_FORMAT_SHORT_UNSIGNED, 2, "Olympus.ValidBits", "Valid bits", NULL }, +{ 0x102d, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.CoringFilter", "Coring filter", NULL }, +{ 0x102e, EXIF_FORMAT_LONG_UNSIGNED, 1, "Olympus.FinalWidth", "Final width", NULL }, +{ 0x102f, EXIF_FORMAT_LONG_UNSIGNED, 1, "Olympus.FinalHeight", "Final height", NULL }, +{ 0x1034, EXIF_FORMAT_SHORT_UNSIGNED, 1, "Olympus.CompressionRatio", "Compression ratio", NULL }, +EXIF_MARKER_LIST_END +}; + +static ExifTextList OlympusShootingMode[]= { + { 0, "normal" }, + { 1, "unknown" }, + { 2, "fast" }, + { 3, "panorama" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusPanoramaDirection[]= { + { 1, "left to right" }, + { 2, "right to left" }, + { 3, "bottom to top" }, + { 4, "top to bottom" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusWB[]= { + { 1, "auto" }, + { 2, "manual" }, + { 3, "one-touch" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList OlympusWBColorTemp[]= { + { 2, "3000" }, + { 3, "3700" }, + { 4, "4000" }, + { 5, "4500" }, + { 6, "5500" }, + { 7, "6500" }, + { 8, "7500" }, + EXIF_TEXT_LIST_END +}; + +gint format_olympus_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder bo) +{ + unsigned char *data; + ExifItem *item; + + if (offset + 8 + 4 >= size) return FALSE; + + data = tiff + offset; + + /* Olympus tag format starts with "OLYMP\x00\x01" or "OLYMP\x00\x02", + * plus an unknown byte, + * followed by IFD data using Olympus tags. + */ + if (memcmp(data, "OLYMP\x00\x01", 7) != 0 && + memcmp(data, "OLYMP\x00\x02", 7) != 0) return FALSE; + + if (exif_parse_IFD_table(exif, tiff, offset + 8, size, + bo, 0, OlympusExifMarkersList) != 0) + { + return FALSE; + } + + item = exif_get_item(exif, "Olympus.SpecialMode"); + if (item && item->data_len == 3 * sizeof(guint32)) + { + static ExifMarker marker = { 0x0200, EXIF_FORMAT_STRING, -1, + "Olympus.ShootingMode", "Shooting mode", NULL }; + guint32 *array = item->data; + const gchar *mode; + const gchar *pdir = NULL; + gchar *text; + gint l; + + mode = exif_text_list_find_value(OlympusShootingMode, array[0]); + if (array[0] == 3) + { + pdir = exif_text_list_find_value(OlympusPanoramaDirection, array[2]); + } + + text = g_strdup_printf("%s%s%s, seq %d", (mode) ? mode : "unknown", + (pdir) ? " " : "", (pdir) ? pdir : "", + array[1] + 1); + l = strlen(text) + 1; + item = exif_item_new(marker.format, marker.tag, l, &marker); + memcpy(item->data, text, l); + g_free(text); + + exif->items = g_list_prepend(exif->items, item); + } + + item = exif_get_item(exif, "Olympus.WhiteBalance"); + if (item && item->data_len == 2 * sizeof(guint16)) + { + static ExifMarker marker = { 0x1015, EXIF_FORMAT_STRING, -1, + "Olympus.WhiteBalance", "White balance", NULL }; + guint16 *array = item->data; + const gchar *mode; + const gchar *color = NULL; + gchar *text; + gint l; + + mode = exif_text_list_find_value(OlympusWB, array[0]); + if (array[0] == 2) + { + color = exif_text_list_find_value(OlympusWBColorTemp, array[1]); + } + + text = g_strdup_printf("%s%s%s", (mode) ? mode : "unknown", + (color) ? " " : "", (color) ? color : ""); + l = strlen(text) + 1; + item = exif_item_new(marker.format, marker.tag, l, &marker); + memcpy(item->data, text, l); + g_free(text); + + exif->items = g_list_prepend(exif->items, item); + } + + return TRUE; +} + + diff --git a/src/format_olympus.h b/src/format_olympus.h new file mode 100644 index 00000000..7dac58c5 --- /dev/null +++ b/src/format_olympus.h @@ -0,0 +1,38 @@ +/* + * GQView + * (C) 2005 John Ellis + * + * This software is released under the GNU General Public License (GNU GPL). + * Please read the included file COPYING for more information. + * This software comes with no warranty of any kind, use at your own risk! + */ + +#ifndef __FORMAT_OLYMPUS_H +#define __FORMAT_OLYMPUS_H + + +#include "exif.h" + + +#if 0 +gint format_olympus_raw(unsigned char *data, const guint len, + guint *image_offset, guint *exif_offset); + + +#define FORMAT_RAW_OLYMPUS { "orf", \ + FORMAT_RAW_MATCH_MAGIC, 0, "IIRS", 4, \ + "Olympus raw", format_olympus_raw } +#endif + + +gint format_olympus_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder bo); + +#define FORMAT_EXIF_OLYMPUS { FORMAT_EXIF_MATCH_MAKERNOTE, "OLYMP\x00\x01", 7, \ + "Olympus", format_olympus_makernote }, \ + { FORMAT_EXIF_MATCH_MAKERNOTE, "OLYMP\x00\x02", 7, \ + "Olympus", format_olympus_makernote } + + +#endif + diff --git a/src/format_raw.c b/src/format_raw.c index 150f88c2..db2977d9 100644 --- a/src/format_raw.c +++ b/src/format_raw.c @@ -31,6 +31,7 @@ #include "format_canon.h" #include "format_fuji.h" #include "format_nikon.h" +#include "format_olympus.h" /* so that debugging is honored */ @@ -69,6 +70,7 @@ static FormatExifEntry format_exif_list[] = { FORMAT_EXIF_CANON, FORMAT_EXIF_FUJI, FORMAT_EXIF_NIKON, + FORMAT_EXIF_OLYMPUS, { 0, NULL, 0, NULL } }; -- 2.20.1