+Sat Jun 4 22:24:00 2005 John Ellis <johne@verizon.net>
+
+ * 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 <johne@verizon.net>
* README: Update credits.
> 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?:
format_canon.h \
format_fuji.c \
format_fuji.h \
+ format_nikon.c \
+ format_nikon.h \
format_raw.c \
format_raw.h \
fullscreen.c \
#include "format_raw.h"
#include "ui_fileops.h"
-/* makernote parsers */
-#include "format_canon.h"
/*
*-----------------------------------------------------------------------------
*-----------------------------------------------------------------------------
*/
-#define BYTE_ORDER_INTEL 1
-#define BYTE_ORDER_MOTOROLA 2
-
-
#define MARKER_UNKNOWN 0x00
#define MARKER_SOI 0xD8
#define MARKER_APP1 0xE1
} 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);
/*
*-----------------------------------------------------------------------------
*-----------------------------------------------------------------------------
*/
-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;
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;
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;
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;
*-------------------------------------------------------------------
*/
-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;
}
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)
*-------------------------------------------------------------------
*/
-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;
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;
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:
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;
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:
}
}
-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.
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;
}
*/
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))
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;
}
}
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;
*-------------------------------------------------------------------
*/
-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))
{
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)
{
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)
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)
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);
}
}
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);
}
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 */
typedef struct _ExifRational ExifRational;
struct _ExifRational
{
- unsigned long int num;
- unsigned long int den;
+ guint32 num;
+ guint32 den;
};
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;
};
struct _ExifTextList
{
- int value;
- const char* description;
+ gint value;
+ const gchar* description;
};
#define EXIF_TEXT_LIST_END { -1, NULL }
typedef struct _ExifFormattedText ExifFormattedText;
struct _ExifFormattedText
{
- const char *key;
- const char *description;
+ const gchar *key;
+ const gchar *description;
};
/* 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
+
}
-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)
{
*-----------------------------------------------------------------------------
*/
-typedef struct _CanonTag CanonTag;
-struct _CanonTag {
- guint id;
- const gchar *description;
- ExifTextList *list;
-};
-
static ExifTextList CanonSet1MacroMode[] = {
{ 1, "macro" },
{ 2, "normal" },
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
};
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;
}
#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;
}
*
*/
-#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
#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;
}
+/*
+ *-----------------------------------------------------------------------------
+ * 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;
+}
+
* 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
--- /dev/null
+/*
+ * 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_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;
+}
+
--- /dev/null
+/*
+ * 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
+
#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++;
}
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)
{
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;
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;
}
+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);
+}
+
+
#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