From 6098d133266cfb7e2874c08866800f04012562a8 Mon Sep 17 00:00:00 2001 From: John Ellis Date: Sun, 5 Jun 2005 02:48:54 +0000 Subject: [PATCH] Sat Jun 4 22:24:00 2005 John Ellis * exif.[ch]: Use glib provided data types and byte order functions for consistency with rest of application. Made several more functions available in the header. Use MakerNote parsing from format_raw.c. * format_canon.[ch]: Changes to match exif.h and format_raw.h. * format_fuji.[ch]: Add support for Fuji EXIF MakerNote. * format_nikon.[ch]: New files, add support for Nikon EXIF MakerNote. * format_raw.[ch]: Add EXIF MakerNote parser functions to gather all camera formats here (similar to existing raw format list). * src/Makefile.am: Add format_nikon.[ch]. ##### Note: GQview CVS on sourceforge is not always up to date, please use ##### ##### an offical release when making enhancements and translation updates. ##### --- ChangeLog | 12 +++ TODO | 2 +- src/Makefile.am | 2 + src/exif.c | 162 +++++++++++++++-------------- src/exif.h | 56 ++++++---- src/format_canon.c | 62 +++++------- src/format_canon.h | 18 ++-- src/format_fuji.c | 133 +++++++++++++++++++++++- src/format_fuji.h | 20 +++- src/format_nikon.c | 248 +++++++++++++++++++++++++++++++++++++++++++++ src/format_nikon.h | 25 +++++ src/format_raw.c | 90 +++++++++++++--- src/format_raw.h | 16 ++- 13 files changed, 679 insertions(+), 167 deletions(-) create mode 100644 src/format_nikon.c create mode 100644 src/format_nikon.h diff --git a/ChangeLog b/ChangeLog index 8c804c6c..bbe6630e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Sat Jun 4 22:24:00 2005 John Ellis + + * exif.[ch]: Use glib provided data types and byte order functions for + consistency with rest of application. Made several more functions + available in the header. Use MakerNote parsing from format_raw.c. + * format_canon.[ch]: Changes to match exif.h and format_raw.h. + * format_fuji.[ch]: Add support for Fuji EXIF MakerNote. + * format_nikon.[ch]: New files, add support for Nikon EXIF MakerNote. + * format_raw.[ch]: Add EXIF MakerNote parser functions to gather all + camera formats here (similar to existing raw format list). + * src/Makefile.am: Add format_nikon.[ch]. + Sat Jun 4 04:02:04 2005 John Ellis * README: Update credits. diff --git a/TODO b/TODO index d9955982..c752b742 100644 --- a/TODO +++ b/TODO @@ -88,7 +88,7 @@ Minor (non blockers): > collection window > search window - > clean up exif.c to be portable (don't assume sizeof(short)==2 and sizeof(long)==4) +d> clean up exif.c to be portable (don't assume sizeof(short)==2 and sizeof(long)==4) Wishlist?: diff --git a/src/Makefile.am b/src/Makefile.am index a1722f43..555b3b14 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,6 +88,8 @@ gqview_SOURCES = \ format_canon.h \ format_fuji.c \ format_fuji.h \ + format_nikon.c \ + format_nikon.h \ format_raw.c \ format_raw.h \ fullscreen.c \ diff --git a/src/exif.c b/src/exif.c index 485083d3..9eef4e90 100644 --- a/src/exif.c +++ b/src/exif.c @@ -73,8 +73,6 @@ #include "format_raw.h" #include "ui_fileops.h" -/* makernote parsers */ -#include "format_canon.h" /* *----------------------------------------------------------------------------- @@ -436,10 +434,6 @@ ExifFormattedText ExifFormattedList[] = { *----------------------------------------------------------------------------- */ -#define BYTE_ORDER_INTEL 1 -#define BYTE_ORDER_MOTOROLA 2 - - #define MARKER_UNKNOWN 0x00 #define MARKER_SOI 0xD8 #define MARKER_APP1 0xE1 @@ -461,7 +455,7 @@ typedef struct __attribute__((packed)) { } IFDEntry; -static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list); +static const ExifMarker *exif_marker_from_tag(guint16 tag, const ExifMarker *list); /* *----------------------------------------------------------------------------- @@ -469,8 +463,8 @@ static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *li *----------------------------------------------------------------------------- */ -ExifItem *exif_item_new(ExifFormatType format, unsigned int tag, - unsigned int elements, const ExifMarker *marker) +ExifItem *exif_item_new(ExifFormatType format, guint tag, + guint elements, const ExifMarker *marker) { ExifItem *item; @@ -495,10 +489,10 @@ ExifItem *exif_item_new(ExifFormatType format, unsigned int tag, item->data_len = sizeof(char) * elements; break; case EXIF_FORMAT_SHORT_UNSIGNED: - item->data_len = sizeof(unsigned short int) * elements; + item->data_len = sizeof(guint16) * elements; break; case EXIF_FORMAT_LONG_UNSIGNED: - item->data_len = sizeof(unsigned long int) * elements; + item->data_len = sizeof(guint32) * elements; break; case EXIF_FORMAT_RATIONAL_UNSIGNED: item->data_len = sizeof(ExifRational) * elements; @@ -510,10 +504,10 @@ ExifItem *exif_item_new(ExifFormatType format, unsigned int tag, item->data_len = sizeof(char) * elements; break; case EXIF_FORMAT_SHORT: - item->data_len = sizeof(short int) * elements; + item->data_len = sizeof(gint16) * elements; break; case EXIF_FORMAT_LONG: - item->data_len = sizeof(long int) * elements; + item->data_len = sizeof(gint32) * elements; break; case EXIF_FORMAT_RATIONAL: item->data_len = sizeof(ExifRational) * elements; @@ -596,7 +590,7 @@ static GString *string_append_raw_bytes(GString *string, gpointer data, gint ne) return string; } -static gchar *text_list_find_value(ExifTextList *list, gint value) +static gchar *text_list_find_value(ExifTextList *list, guint value) { gchar *result = NULL; gint i; @@ -618,45 +612,42 @@ static gchar *text_list_find_value(ExifTextList *list, gint value) *------------------------------------------------------------------- */ -static uint16_t get_int16(unsigned char *f, int bo) +guint16 exif_byte_get_int16(unsigned char *f, ExifByteOrder bo) { - if (bo == BYTE_ORDER_INTEL) - return *f + (*(f+1)<<8); + if (bo == EXIF_BYTE_ORDER_INTEL) + return GUINT16_FROM_LE(*(guint16*)f); else - return ((*f)<<8) + *(f+1); + return GUINT16_FROM_BE(*(guint16*)f); } -#if 0 -/* not used ? */ -static uint32_t get_int32(unsigned char *f, int bo) +guint32 exif_byte_get_int32(unsigned char *f, ExifByteOrder bo) { - if (bo == BYTE_ORDER_INTEL) - return get_int16(f, BYTE_ORDER_INTEL) + (get_int16(f+2, BYTE_ORDER_INTEL)<<16); + if (bo == EXIF_BYTE_ORDER_INTEL) + return GUINT32_FROM_LE(*(guint32*)f); else - return (get_int16(f, BYTE_ORDER_MOTOROLA)<<16) + get_int16(f+2, BYTE_ORDER_MOTOROLA); + return GUINT32_FROM_BE(*(guint32*)f); } -#endif -static uint16_t swab_int16(uint16_t n, int bo) +guint16 exif_byte_swab_int16(guint16 n, ExifByteOrder bo) { -#if BYTE_ORDER == LITTLE_ENDIAN - if (bo == BYTE_ORDER_MOTOROLA) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + if (bo == EXIF_BYTE_ORDER_MOTOROLA) #else - if (bo == BYTE_ORDER_INTEL) + if (bo == EXIF_BYTE_ORDER_INTEL) #endif - return n>>8 | n<<8 ; + return GUINT16_SWAP_LE_BE(n); else return n; } -static uint32_t swab_int32(uint32_t n, int bo) +guint32 exif_byte_swab_int32(guint32 n, ExifByteOrder bo) { -#if BYTE_ORDER == LITTLE_ENDIAN - if (bo == BYTE_ORDER_MOTOROLA) +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + if (bo == EXIF_BYTE_ORDER_MOTOROLA) #else - if (bo == BYTE_ORDER_INTEL) + if (bo == EXIF_BYTE_ORDER_INTEL) #endif - return n<<24 | n>>24 | (n & 0xFF0000)>>8 | (n & 0xFF00)<<8; + return GUINT32_SWAP_LE_BE(n); else return n; } @@ -670,7 +661,7 @@ static uint32_t swab_int32(uint32_t n, int bo) static int get_marker_size(unsigned char *f) { /* Size is always in Motorola byte order */ - return get_int16(f+2, BYTE_ORDER_MOTOROLA); + return exif_byte_get_int16(f+2, EXIF_BYTE_ORDER_MOTOROLA); } static int goto_next_marker(unsigned char **f, int *size, int *marker) @@ -713,9 +704,9 @@ static int goto_next_marker(unsigned char **f, int *size, int *marker) *------------------------------------------------------------------- */ -static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list) +static const ExifMarker *exif_marker_from_tag(guint16 tag, const ExifMarker *list) { - int i = 0; + gint i = 0; if (!list) return NULL; @@ -727,18 +718,19 @@ static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *li return (list[i].tag == 0 ? NULL : &list[i]); } -static void rational_from_data(ExifRational *r, void *src, int byte_order) +static void rational_from_data(ExifRational *r, void *src, ExifByteOrder byte_order) { - r->num = swab_int32(*(uint32_t*)src, byte_order); - r->den = swab_int32(*(uint32_t*)(src + sizeof(uint32_t)), byte_order); + r->num = exif_byte_swab_int32(*(guint32*)src, byte_order); + r->den = exif_byte_swab_int32(*(guint32*)(src + sizeof(guint32)), byte_order); } -void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_format, int byte_order) +void exif_item_copy_data(ExifItem *item, void *src, guint len, + ExifFormatType src_format, ExifByteOrder byte_order) { - int bs; - int ne; + gint bs; + gint ne; gpointer dest; - int i; + gint i; bs = ExifFormatList[item->format].size; ne = item->elements; @@ -768,7 +760,7 @@ void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_ case EXIF_FORMAT_SHORT: for (i = 0; i < ne; i++) { - ((short *)dest)[i] = swab_int16(*(uint16_t*)(src + i * bs), byte_order); + ((guint16 *)dest)[i] = exif_byte_swab_int16(*(guint16*)(src + i * bs), byte_order); } break; case EXIF_FORMAT_LONG_UNSIGNED: @@ -782,14 +774,16 @@ void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_ ss = ExifFormatList[src_format].size; for (i = 0; i < ne; i++) { - ((long *)dest)[i] = (long)swab_int16(*(uint16_t*)(src + i * ss), byte_order); + ((gint32 *)dest)[i] = + (gint32)exif_byte_swab_int16(*(guint16*)(src + i * ss), byte_order); } } else { for (i = 0; i < ne; i++) { - ((long *)dest)[i] = swab_int32(*(uint32_t*)(src + i * bs), byte_order); + ((gint32 *)dest)[i] = + exif_byte_swab_int32(*(guint32*)(src + i * bs), byte_order); } } break; @@ -803,7 +797,7 @@ void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_ case EXIF_FORMAT_FLOAT: for (i = 0; i < ne; i++) { - ((float *)dest)[i] = swab_int32(*(uint32_t*)(src + i * bs), byte_order); + ((float *)dest)[i] = exif_byte_swab_int32(*(guint32*)(src + i * bs), byte_order); } break; case EXIF_FORMAT_DOUBLE: @@ -818,21 +812,21 @@ void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_ } } -static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset, - int size, int byte_order, - const ExifMarker *list) +static gint exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order, + const ExifMarker *list) { IFDEntry *ent = (IFDEntry*)(tiff+offset); - uint32_t swabed_data; + guint32 swabed_data; void *data; - int data_len; + guint data_len; const ExifMarker *marker; ExifItem *item; - ent->tag = swab_int16(ent->tag, byte_order); - ent->format = swab_int16(ent->format, byte_order); - ent->nb = swab_int32(ent->nb, byte_order); - swabed_data = swab_int32(ent->data, byte_order); + ent->tag = exif_byte_swab_int16(ent->tag, byte_order); + ent->format = exif_byte_swab_int16(ent->format, byte_order); + ent->nb = exif_byte_swab_int32(ent->nb, byte_order); + swabed_data = exif_byte_swab_int32(ent->data, byte_order); /* Check tag type. If it does not match, either the format is wrong, * either it is a unknown tag; so it is not really an error. @@ -866,12 +860,14 @@ static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset, if (ent->format <= EXIF_FORMAT_DOUBLE) { printf("warning: exif tag %s format mismatch, found %s exif spec requests %s\n", - marker->key, ExifFormatList[ent->format].short_name, ExifFormatList[marker->format].short_name); + marker->key, ExifFormatList[ent->format].short_name, + ExifFormatList[marker->format].short_name); } else { printf("warning: exif tag %s format mismatch, found unknown id %d exif spec requests %d (%s)\n", - marker->key, ent->format, marker->format, ExifFormatList[marker->format].short_name); + marker->key, ent->format, marker->format, + ExifFormatList[marker->format].short_name); } return 0; } @@ -881,7 +877,8 @@ static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset, */ if (marker->components > 0 && marker->components != ent->nb) { - printf("warning: exif tag %s has %d elements, exif spec requests %d\n", marker->key, ent->nb, marker->components); + printf("warning: exif tag %s has %d elements, exif spec requests %d\n", + marker->key, ent->nb, marker->components); } data_len = ExifFormatList[marker->format].size * ent->nb; if (data_len > sizeof(ent->data)) @@ -910,7 +907,7 @@ static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset, exif_parse_IFD_table(exif, tiff, swabed_data, size, byte_order, list); break; case TAG_EXIFMAKERNOTE: - format_exif_makernote_canon_parse(exif, tiff, swabed_data, size, byte_order); + format_exif_makernote_parse(exif, tiff, swabed_data, size, byte_order); break; } } @@ -918,17 +915,17 @@ static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset, return 0; } -int exif_parse_IFD_table(ExifData *exif, - unsigned char *tiff, int offset, - int size, int byte_order, - const ExifMarker *list) +gint exif_parse_IFD_table(ExifData *exif, + unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order, + const ExifMarker *list) { - int i, nb_entries; + gint i, nb_entries; /* We should be able to read number of entries in IFD0) */ if (size < offset+2) return -1; - nb_entries = get_int16(tiff+offset, byte_order); + nb_entries = exif_byte_get_int16(tiff+offset, byte_order); /* Entries and next IFD offset must be readable */ if (size < offset+nb_entries*12+4) return -1; @@ -947,9 +944,10 @@ int exif_parse_IFD_table(ExifData *exif, *------------------------------------------------------------------- */ -static int parse_TIFF(ExifData *exif, unsigned char *tiff, int size) +gint exif_parse_TIFF(ExifData *exif, unsigned char *tiff, guint size, ExifMarker *list) { - int byte_order, offset=0; + ExifByteOrder byte_order; + guint offset=0; if (size < sizeof(TIFFHeader)) { @@ -958,30 +956,30 @@ static int parse_TIFF(ExifData *exif, unsigned char *tiff, int size) if (strncmp(((TIFFHeader*)tiff)->byte_order, "II", 2) == 0) { - byte_order = BYTE_ORDER_INTEL; + byte_order = EXIF_BYTE_ORDER_INTEL; } else if (strncmp(((TIFFHeader*)tiff)->byte_order, "MM", 2) == 0) { - byte_order = BYTE_ORDER_MOTOROLA; + byte_order = EXIF_BYTE_ORDER_MOTOROLA; } else { return -1; } - if (swab_int16(((TIFFHeader*)tiff)->magic, byte_order) != 0x002A) + if (exif_byte_swab_int16(((TIFFHeader*)tiff)->magic, byte_order) != 0x002A) { return -1; } - offset = swab_int32(((TIFFHeader*)tiff)->IFD_offset, byte_order); + offset = exif_byte_swab_int32(((TIFFHeader*)tiff)->IFD_offset, byte_order); - return exif_parse_IFD_table(exif, tiff, offset, size, byte_order, ExifKnownMarkersList); + return exif_parse_IFD_table(exif, tiff, offset, size, byte_order, list); } -static int parse_JPEG(ExifData *exif, unsigned char *f, int size) +static gint exif_parse_JPEG(ExifData *exif, unsigned char *f, guint size, ExifMarker *list) { - int marker, marker_size; + guint marker, marker_size; if (size<2 || *f!=0xFF || *(f+1)!=MARKER_SOI) { @@ -1007,7 +1005,7 @@ static int parse_JPEG(ExifData *exif, unsigned char *f, int size) return -2; } - return parse_TIFF(exif, f+10, marker_size-6); + return exif_parse_TIFF(exif, f+10, marker_size-6, list); } static gint map_file(const gchar *path, void **mapping, int *size) @@ -1090,9 +1088,9 @@ ExifData *exif_read(const gchar *path) exif = g_new0(ExifData, 1); exif->items = NULL; - if ((res = parse_JPEG(exif, (unsigned char *)f, size)) == -2) + if ((res = exif_parse_JPEG(exif, (unsigned char *)f, size, ExifKnownMarkersList)) == -2) { - res = parse_TIFF(exif, (unsigned char *)f, size); + res = exif_parse_TIFF(exif, (unsigned char *)f, size, ExifKnownMarkersList); } if (res != 0) @@ -1101,7 +1099,7 @@ ExifData *exif_read(const gchar *path) if (format_raw_img_exif_offsets(f, size, NULL, &offset)) { - res = parse_TIFF(exif, (unsigned char*)f + offset, size - offset); + res = exif_parse_TIFF(exif, (unsigned char*)f + offset, size - offset, ExifKnownMarkersList); } } @@ -1180,7 +1178,7 @@ gchar *exif_item_get_data_as_text(ExifItem *item) val = (unsigned char)(((signed char *)data)[0]); } - result = text_list_find_value(marker->list, (unsigned short)val); + result = text_list_find_value(marker->list, (guint)val); string = g_string_append(string, result); g_free(result); } diff --git a/src/exif.h b/src/exif.h index f13828ff..f11ea10e 100644 --- a/src/exif.h +++ b/src/exif.h @@ -49,13 +49,18 @@ typedef enum { EXIF_FORMAT_DOUBLE = 12 } ExifFormatType; +typedef enum { + EXIF_BYTE_ORDER_INTEL, + EXIF_BYTE_ORDER_MOTOROLA +} ExifByteOrder; + typedef struct _ExifFormatAttrib ExifFormatAttrib; struct _ExifFormatAttrib { ExifFormatType type; - int size; - const char *short_name; - const char *description; + guint size; + const gchar *short_name; + const gchar *description; }; /* the list of known tag data formats */ @@ -77,8 +82,8 @@ struct _ExifData typedef struct _ExifRational ExifRational; struct _ExifRational { - unsigned long int num; - unsigned long int den; + guint32 num; + guint32 den; }; @@ -89,20 +94,20 @@ typedef struct _ExifTextList ExifTextList; struct _ExifItem { ExifFormatType format; - int tag; + guint tag; const ExifMarker *marker; - int elements; + guint elements; gpointer data; - int data_len; + guint data_len; }; struct _ExifMarker { - int tag; + guint tag; ExifFormatType format; - int components; - char *key; - char *description; + gint components; + gchar *key; + gchar *description; ExifTextList *list; }; @@ -110,8 +115,8 @@ struct _ExifMarker struct _ExifTextList { - int value; - const char* description; + gint value; + const gchar* description; }; #define EXIF_TEXT_LIST_END { -1, NULL } @@ -120,8 +125,8 @@ struct _ExifTextList typedef struct _ExifFormattedText ExifFormattedText; struct _ExifFormattedText { - const char *key; - const char *description; + const gchar *key; + const gchar *description; }; @@ -195,15 +200,24 @@ void exif_write_data_list(ExifData *exif, FILE *f, gint human_readable_list); /* These funcs for use by makernote parsers only */ -ExifItem *exif_item_new(ExifFormatType format, unsigned int tag, - unsigned int elements, const ExifMarker *marker); -void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatType src_format, int byte_order); + +guint16 exif_byte_get_int16(unsigned char *f, ExifByteOrder bo); +guint32 exif_byte_get_int32(unsigned char *f, ExifByteOrder bo); +guint16 exif_byte_swab_int16(guint16 n, ExifByteOrder bo); +guint32 exif_byte_swab_int32(guint32 n, ExifByteOrder bo); + +ExifItem *exif_item_new(ExifFormatType format, guint tag, + guint elements, const ExifMarker *marker); +void exif_item_copy_data(ExifItem *item, void *src, guint len, + ExifFormatType src_format, ExifByteOrder byte_order); gint exif_parse_IFD_table(ExifData *exif, - unsigned char *tiff, int offset, - int size, int byte_order, + unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order, const ExifMarker *list); +gint exif_parse_TIFF(ExifData *exif, unsigned char *tiff, guint size, ExifMarker *list); #endif + diff --git a/src/format_canon.c b/src/format_canon.c index 03f1926f..bdc632a7 100644 --- a/src/format_canon.c +++ b/src/format_canon.c @@ -251,8 +251,8 @@ return_only: } -gint format_raw_test_canon(const void *data, const guint len, - guint *image_offset, guint *exif_offset) +gint format_canon_raw(const void *data, const guint len, + guint *image_offset, guint *exif_offset) { @@ -478,13 +478,6 @@ return_only: *----------------------------------------------------------------------------- */ -typedef struct _CanonTag CanonTag; -struct _CanonTag { - guint id; - const gchar *description; - ExifTextList *list; -}; - static ExifTextList CanonSet1MacroMode[] = { { 1, "macro" }, { 2, "normal" }, @@ -728,21 +721,27 @@ static ExifTextList CanonCustomShutterCurtainSync[] = { EXIF_TEXT_LIST_END }; -static CanonTag CanonCustom[] = { - { 1, "Noise reduction", CanonCustomEnable }, -/* { 2, "Shutter/Auto Exposure Button Function", CanonCustomBTNShutter }, */ - { 3, "Mirror lockup", CanonCustomEnable }, - { 4, "Tv/Av and exposure level", CanonCustomExposureLevel }, - { 5, "AF assist light", CanonCustomEnableInvert }, - { 6, "Shutter speed in Av mode", CanonCustomAVShutterSpeed }, -/* { 7, "Auto-Exposure bracketting sequence/auto cancellation", CanonCustom }, */ - { 8, "Shutter sync", CanonCustomShutterCurtainSync }, -/* { 9, "AF button function", CanonCustom }, */ - { 10, "Fill flash auto reduction", CanonCustomEnableInvert }, -/* { 11, "Menu button function", CanonCustom }, */ -/* { 12, "Set button function", CanonCustom }, */ - { 13, "Sensor cleaning", CanonCustomEnable }, - { 0, NULL, NULL } +static ExifMarker CanonCustom[] = { +{ 1, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.NoiseReduction", "Noise reduction", CanonCustomEnable }, +/*{ 2, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.BtnFuncShutter", + "Shutter/Auto exposure button function",CanonCustomBTNShutter }, */ +{ 3, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.MirrorLockup", "Mirror lockup", CanonCustomEnable }, +{ 4, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.TvAvExposureLevel", + "Tv/Av and exposure level", CanonCustomExposureLevel }, +{ 5, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.AFAssistLight", "AF assist light", CanonCustomEnableInvert }, +{ 6, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.AvShutterSpeed", + "Shutter speed in Av mode", CanonCustomAVShutterSpeed }, +/*{ 7, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.AutoBracket", + "Auto-Exposure bracketting sequence/auto cancellation", CanonCustom }, */ +{ 8, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ShutterSync", "Shutter sync", CanonCustomShutterCurtainSync }, +/* { 9, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.BtnFuncAF", "AF button function", CanonCustom }, */ +{ 10, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FillFlashReduction", + "Fill flash auto reduction", CanonCustomEnableInvert }, +/*{ 11, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.BtnFuncMenu", + "Menu button function", CanonCustom }, */ +/*{ 12, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.BtnFuncSet", "Set button function", CanonCustom }, */ +{ 13, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SensorCleaning", "Sensor cleaning", CanonCustomEnable }, +EXIF_MARKER_LIST_END }; #endif @@ -760,7 +759,7 @@ static ExifMarker CanonExifMarkersList[] = { }; static void canon_mknote_parse_settings(ExifData *exif, - guint16 *data, guint32 len, int byte_order, + guint16 *data, guint32 len, ExifByteOrder byte_order, ExifMarker *list) { gint i; @@ -825,19 +824,12 @@ static void canon_mknote_parse_convert(ExifData *exif) } #endif -gint format_exif_makernote_canon_parse(ExifData *exif, unsigned char *tiff, int offset, - int size, int byte_order) +gint format_canon_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order) { ExifItem *item; - gchar *text; - gint found; - - text = exif_get_data_as_text(exif, "Make"); - found = (text && strncasecmp(text, "Canon", 5) == 0); - g_free(text); - if (!found || - exif_parse_IFD_table(exif, tiff, offset, size, byte_order, CanonExifMarkersList) != 0) + if (exif_parse_IFD_table(exif, tiff, offset, size, byte_order, CanonExifMarkersList) != 0) { return FALSE; } diff --git a/src/format_canon.h b/src/format_canon.h index 61eaef24..987de1ed 100644 --- a/src/format_canon.h +++ b/src/format_canon.h @@ -15,23 +15,25 @@ * */ -#ifndef __FORMAT_RAW_CANON_H -#define __FORMAT_RAW_CANON_H +#ifndef __FORMAT_CANON_H +#define __FORMAT_CANON_H #include "exif.h" -gint format_raw_test_canon(const void *data, const guint len, - guint *image_offset, guint *exif_offset); +gint format_canon_raw(const void *data, const guint len, + guint *image_offset, guint *exif_offset); -#define FORMAT_RAW_CANON { "II", 2, "Canon crw format", format_raw_test_canon }, \ - { "\x49\x49\x2a\00", 4, "Canon cr2 format", format_raw_test_canon } +#define FORMAT_RAW_CANON { "II", 2, "Canon crw format", format_canon_raw }, \ + { "\x49\x49\x2a\00", 4, "Canon cr2 format", format_canon_raw } -gint format_exif_makernote_canon_parse(ExifData *exif, unsigned char *tiff, int offset, - int size, int byte_order); +gint format_canon_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order); + +#define FORMAT_EXIF_CANON { FORMAT_EXIF_MATCH_MAKE, "Canon", 5, format_canon_makernote } #endif diff --git a/src/format_fuji.c b/src/format_fuji.c index 5395f117..f2d73c0f 100644 --- a/src/format_fuji.c +++ b/src/format_fuji.c @@ -26,9 +26,11 @@ #include "format_fuji.h" #include "format_raw.h" +#include "exif.h" -gint format_raw_test_fuji(const void *data, const guint len, - guint *image_offset, guint *exif_offset) + +gint format_fuji_raw(const void *data, const guint len, + guint *image_offset, guint *exif_offset) { guint io; guint eo; @@ -57,3 +59,130 @@ gint format_raw_test_fuji(const void *data, const guint len, } +/* + *----------------------------------------------------------------------------- + * EXIF Makernote for Fujifilm + *----------------------------------------------------------------------------- + */ + +static ExifTextList FujiTagSharpness[] = { + { 1, "soft" }, + { 2, "soft" }, + { 3, "normal" }, + { 4, "hard" }, + { 5, "hard" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagWhiteBalance[]= { + { 0, "auto" }, + { 256, "daylight" }, + { 512, "cloudy" }, + { 768, "daylight color-fluorescence" }, + { 769, "daywhite color-fluorescence" }, + { 770, "white-fluorescence" }, + { 1024, "incandescent" }, + { 3840, "custom" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagColorTone[]= { + { 0, "normal" }, + { 256, "high" }, + { 512, "low" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagFlashMode[]= { + { 0, "auto" }, + { 1, "on" }, + { 2, "off" }, + { 3, "red-eye reduction" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagOffOn[]= { + { 0, "off" }, + { 1, "on" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagFocusMode[]= { + { 0, "auto" }, + { 1, "manual" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagPictureMode[]= { + { 0, "auto" }, + { 1, "portrait" }, + { 2, "landscape" }, + { 4, "sports" }, + { 5, "night" }, + { 6, "program AE" }, + { 256, "aperture priority AE" }, + { 512, "shutter priority AE" }, + { 768, "manual" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList FujiTagNoYes[]= { + { 0, "no" }, + { 1, "yes" }, + EXIF_TEXT_LIST_END +}; + +#if 0 +static ExifTextList FujiTag[]= { + { , "" }, + { , "" }, + EXIF_TEXT_LIST_END +}; +#endif + + +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", + "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 }, +EXIF_MARKER_LIST_END +}; + + + +gint format_fuji_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order) +{ + unsigned char *data; + guint ifdstart; + + if (offset + 8 + 4 >= size) return FALSE; + + data = tiff + offset; + if (memcmp(data, "FUJIFILM", 8) != 0) return FALSE; + + ifdstart = exif_byte_get_int32(data + 8, EXIF_BYTE_ORDER_INTEL); + if (offset + ifdstart >= size) return FALSE; + + if (exif_parse_IFD_table(exif, tiff + offset, ifdstart, size - offset, + EXIF_BYTE_ORDER_INTEL, FujiExifMarkersList) != 0) + { + return FALSE; + } + + return TRUE; +} + diff --git a/src/format_fuji.h b/src/format_fuji.h index d4c7e4aa..467a6898 100644 --- a/src/format_fuji.h +++ b/src/format_fuji.h @@ -10,15 +10,25 @@ * This software comes with no warranty of any kind, use at your own risk! */ -#ifndef __FORMAT_RAW_FUJI_H -#define __FORMAT_RAW_FUJI_H +#ifndef __FORMAT_FUJI_H +#define __FORMAT_FUJI_H -gint format_raw_test_fuji(const void *data, const guint len, - guint *image_offset, guint *exif_offset); +#include "exif.h" -#define FORMAT_RAW_FUJI { "FUJIFILM", 8, "Fuji raw format", format_raw_test_fuji } +gint format_fuji_raw(const void *data, const guint len, + guint *image_offset, guint *exif_offset); + + +#define FORMAT_RAW_FUJI { "FUJIFILM", 8, "Fuji raw format", format_fuji_raw } + + +gint format_fuji_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order); + +#define FORMAT_EXIF_FUJI { FORMAT_EXIF_MATCH_MAKERNOTE, "FUJIFILM", 8, format_fuji_makernote } + #endif diff --git a/src/format_nikon.c b/src/format_nikon.c new file mode 100644 index 00000000..60ec3cc2 --- /dev/null +++ b/src/format_nikon.c @@ -0,0 +1,248 @@ +/* + * 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_nikon.h" + +#include "exif.h" + + +/* + *----------------------------------------------------------------------------- + * EXIF Makernote for Nikon + *----------------------------------------------------------------------------- + */ + +static ExifTextList NikonTagQuality[]= { + { 1, "VGA basic" }, + { 2, "VGA normal" }, + { 3, "VGA fine" }, + { 4, "SXGA basic" }, + { 5, "SXGA normal" }, + { 6, "SXGA fine" }, + { 7, "XGA basic (?)" }, + { 8, "XGA normal (?)" }, + { 9, "XGA fine (?)" }, + { 10, "UXGA basic" }, + { 11, "UXGA normal" }, + { 12, "UXGA fine" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTagColorMode[]= { + { 1, "color" }, + { 2, "monochrome" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTagImgAdjust[]= { + { 0, "normal" }, + { 1, "bright+" }, + { 2, "bright-" }, + { 3, "contrast+" }, + { 4, "contrast-" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTagISOSensitivity[]= { + { 0, "80" }, + { 2, "160" }, + { 4, "320" }, + { 5, "100" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTagWhiteBalance[]= { + { 0, "auto" }, + { 1, "preset" }, + { 2, "daylight" }, + { 3, "incandescent" }, + { 4, "fluorescence" }, + { 5, "cloudy" }, + { 6, "speedlight" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTagConverter[]= { + { 0, "none" }, + { 1, "Fisheye" }, + EXIF_TEXT_LIST_END +}; + +#if 0 +static ExifTextList NikonTag[]= { + { , "" }, + { , "" }, + EXIF_TEXT_LIST_END +}; +#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", + "Image adjustment", NikonTagImgAdjust }, +{ 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.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 }, +EXIF_MARKER_LIST_END +}; + +static ExifTextList NikonTag2FlashComp[]= { + { 0x06, "+1.0 EV" }, + { 0x04, "+0.7 EV" }, + { 0x03, "+0.5 EV" }, + { 0x02, "+0.3 EV" }, + { 0x00, "0.0 EV" }, + { 0xfe, "-0.3 EV" }, + { 0xfd, "-0.5 EV" }, + { 0xfc, "-0.7 EV" }, + { 0xfa, "-1.0 EV" }, + { 0xf8, "-1.3 EV" }, + { 0xf7, "-1.5 EV" }, + { 0xf6, "-1.7 EV" }, + { 0xf4, "-2.0 EV" }, + { 0xf2, "-2.3 EV" }, + { 0xf1, "-2.5 EV" }, + { 0xf0, "-2.7 EV" }, + { 0xee, "-3.0 EV" }, + EXIF_TEXT_LIST_END +}; + +static ExifTextList NikonTag2FlashUsed[]= { + { 0, "no" }, + { 9, "yes" }, + EXIF_TEXT_LIST_END +}; + +#if 0 +static ExifTextList NikonTagi2Saturation[]= { + { -3, "black and white" }, + { -2, "-2" }, + { -1, "-1" }, + { 0, "normal" }, + { 1, "+1" }, + { 2, "+2" }, + EXIF_TEXT_LIST_END +}; +#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", + "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", + "Flash compensation", NikonTag2FlashComp }, +{ 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2, "MkN.Nikon.ISOSpeedRequest", + "ISO speed requested", NULL }, +{ 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4, "MkN.Nikon.CornerCoord", + "Corner coordinates", NULL }, +{ 0x0018, EXIF_FORMAT_UNDEFINED, 4, "MkN.Nikon.FlashBracketCompensation", + "Flash bracket compensation", NikonTag2FlashComp }, +{ 0x0019, EXIF_FORMAT_RATIONAL, 1, "MkN.Nikon.AEBracketCompensation", + "AE bracket compensation", NULL }, +{ 0x0080, EXIF_FORMAT_STRING, -1, "MkN.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", + "Lens min/max focal length and aperture", NULL }, +{ 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.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 }, +EXIF_MARKER_LIST_END +}; + + +gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order) +{ + unsigned char *data; + + if (offset + 8 + 4 >= size) return FALSE; + + data = tiff + offset; + if (memcmp(data, "Nikon\x00\x01\x00", 8) == 0) + { + if (exif_parse_IFD_table(exif, tiff, offset + 8, size, + byte_order, NikonExifMarkersList1) != 0) + { + return FALSE; + } + return TRUE; + } + + if (memcmp(data, "Nikon\x00\x02\x00\x00\x00", 10) == 0 || + memcmp(data, "Nikon\x00\x02\x10\x00\x00", 10) == 0) + { + guint tiff_header; + + tiff_header = offset + 10; + if (exif_parse_TIFF(exif, tiff + tiff_header, size - tiff_header, + NikonExifMarkersList2) != 0) + { + return FALSE; + } + return TRUE; + } + + /* fixme: support E990 and D1 */ + if (exif_parse_IFD_table(exif, tiff, offset, size, + byte_order, NikonExifMarkersList2) != 0) + { + return FALSE; + } + + return FALSE; +} + diff --git a/src/format_nikon.h b/src/format_nikon.h new file mode 100644 index 00000000..1988750d --- /dev/null +++ b/src/format_nikon.h @@ -0,0 +1,25 @@ +/* + * 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_NIKON_H +#define __FORMAT_NIKON_H + + +#include "exif.h" + + +gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order); + +#define FORMAT_EXIF_NIKON { FORMAT_EXIF_MATCH_MAKERNOTE, "Nikon\x00", 6, format_nikon_makernote }, \ + { FORMAT_EXIF_MATCH_MAKE, "NIKON", 5, format_nikon_makernote } + + +#endif + diff --git a/src/format_raw.c b/src/format_raw.c index ce62c55b..86c6dd99 100644 --- a/src/format_raw.c +++ b/src/format_raw.c @@ -30,35 +30,51 @@ #include "format_canon.h" #include "format_fuji.h" +#include "format_nikon.h" -typedef struct _FormatEntry FormatEntry; -struct _FormatEntry { +typedef struct _FormatRawEntry FormatRawEntry; +struct _FormatRawEntry { const void *header_pattern; const guint header_length; const gchar *description; FormatRawParseFunc func_parse; }; - -static FormatEntry format_list[] = { +static FormatRawEntry format_raw_list[] = { FORMAT_RAW_CANON, FORMAT_RAW_FUJI, { NULL, 0, NULL, NULL } }; -static FormatEntry *format_raw_find(const void *data, const guint len) +typedef struct _FormatExifEntry FormatExifEntry; +struct _FormatExifEntry { + FormatExifMatchType header_type; + const void *header_pattern; + const guint header_length; + FormatExifParseFunc func_parse; +}; + +static FormatExifEntry format_exif_list[] = { + FORMAT_EXIF_CANON, + FORMAT_EXIF_FUJI, + FORMAT_EXIF_NIKON, + { 0, NULL, 0, NULL } +}; + + +static FormatRawEntry *format_raw_find(const void *data, const guint len) { gint n; n = 0; - while (format_list[n].header_pattern) + while (format_raw_list[n].header_pattern) { - if (format_list[n].header_length <= len && - memcmp(data, format_list[n].header_pattern, format_list[n].header_length) == 0) + if (format_raw_list[n].header_length <= len && + memcmp(data, format_raw_list[n].header_pattern, format_raw_list[n].header_length) == 0) { - return &format_list[n]; + return &format_raw_list[n]; } n++; } @@ -66,7 +82,7 @@ static FormatEntry *format_raw_find(const void *data, const guint len) return NULL; } -static gint format_raw_parse(FormatEntry *entry, +static gint format_raw_parse(FormatRawEntry *entry, const void *data, const guint len, guint *image_offset, guint *exif_offset) { @@ -94,7 +110,7 @@ static gint format_raw_parse(FormatEntry *entry, gint format_raw_img_exif_offsets(const void *data, const guint len, guint *image_offset, guint *exif_offset) { - FormatEntry *entry; + FormatRawEntry *entry; if (!data || len < 1) return FALSE; @@ -109,7 +125,7 @@ gint format_raw_img_exif_offsets(const void *data, const guint len, gint format_raw_img_exif_offsets_fd(int fd, const void *header_data, const guint header_len, guint *image_offset, guint *exif_offset) { - FormatEntry *entry; + FormatRawEntry *entry; void *map_data = NULL; size_t map_len = 0; struct stat st; @@ -157,3 +173,53 @@ gint format_raw_img_exif_offsets_fd(int fd, const void *header_data, const guint } +static FormatExifEntry *format_exif_makernote_find(ExifData *exif, unsigned char *tiff, + guint offset, guint size) +{ + ExifItem *make; + gint n; + + make = exif_get_item(exif, "Make"); + + n = 0; + while (format_exif_list[n].header_pattern) + { + switch (format_exif_list[n].header_type) + { + case FORMAT_EXIF_MATCH_MAKERNOTE: + if (format_exif_list[n].header_length + offset < size && + memcmp(tiff + offset, format_exif_list[n].header_pattern, + format_exif_list[n].header_length) == 0) + { + return &format_exif_list[n]; + } + break; + case FORMAT_EXIF_MATCH_MAKE: + if (make && + make->data_len >= format_exif_list[n].header_length && + memcmp(make->data, format_exif_list[n].header_pattern, + format_exif_list[n].header_length) == 0) + { + return &format_exif_list[n]; + } + break; + } + n++; + } + + return FALSE; +} + +gint format_exif_makernote_parse(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order) +{ + FormatExifEntry *entry; + + entry = format_exif_makernote_find(exif, tiff, offset, size); + + if (!entry || !entry->func_parse) return FALSE; + + return entry->func_parse(exif, tiff, offset, size, byte_order); +} + + diff --git a/src/format_raw.h b/src/format_raw.h index 2c1609c6..5c6c963e 100644 --- a/src/format_raw.h +++ b/src/format_raw.h @@ -14,15 +14,29 @@ #define __FORMAT_RAW_H +#include "exif.h" + + typedef gint (* FormatRawParseFunc)(const void *data, const guint len, guint *image_offset, guint *exif_offset); - gint format_raw_img_exif_offsets(const void *data, const guint len, guint *image_offset, guint *exif_offset); gint format_raw_img_exif_offsets_fd(int fd, const void *header_data, const guint header_len, guint *image_offset, guint *exif_offset); +typedef enum { + FORMAT_EXIF_MATCH_MAKE, + FORMAT_EXIF_MATCH_MAKERNOTE +} FormatExifMatchType; + +typedef gint (* FormatExifParseFunc)(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order); + +gint format_exif_makernote_parse(ExifData *exif, unsigned char *tiff, guint offset, + guint size, ExifByteOrder byte_order); + + #endif -- 2.20.1