Mercurial > geeqie
diff src/format_olympus.c @ 57:a8c9992320f4
Fri Jun 10 20:57:42 2005 John Ellis <johne@verizon.net>
* 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].
author | gqview |
---|---|
date | Sat, 11 Jun 2005 01:09:30 +0000 |
parents | |
children | df73b94154e4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/format_olympus.c Sat Jun 11 01:09:30 2005 +0000 @@ -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 <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <glib.h> + +#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; +} + +