Fri Jun 3 01:49:20 2005 John Ellis <johne@verizon.net>
authorJohn Ellis <johne@verizon.net>
Fri, 3 Jun 2005 06:07:02 +0000 (06:07 +0000)
committerJohn Ellis <johne@verizon.net>
Fri, 3 Jun 2005 06:07:02 +0000 (06:07 +0000)
        * exif.[ch]: Export several parsing functions for use by the exif
        makernote parsers, and add hook for MakerNote data parsing.
        * format_canon.[ch]: Add Canon EXIF MakerNote support.
        * format_raw.c: Fix warning printf grammar.

##### Note: GQview CVS on sourceforge is not always up to date, please use #####
##### an offical release when making enhancements and translation updates. #####

ChangeLog
src/exif.c
src/exif.h
src/format_canon.c
src/format_canon.h
src/format_raw.c

index 3cd5f15..6be1ac6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Jun  3 01:49:20 2005  John Ellis  <johne@verizon.net>
+
+       * exif.[ch]: Export several parsing functions for use by the exif
+       makernote parsers, and add hook for MakerNote data parsing.
+       * format_canon.[ch]: Add Canon EXIF MakerNote support.
+       * format_raw.c: Fix warning printf grammar.
+
 Thu May 26 22:14:53 2005  John Ellis  <johne@verizon.net>
 
        * format_raw.c (format_raw_parse): Use unsigned int to match arguments.
index ff229f4..485083d 100644 (file)
@@ -73,6 +73,8 @@
 #include "format_raw.h"
 #include "ui_fileops.h"
 
+/* makernote parsers */
+#include "format_canon.h"
 
 /*
  *-----------------------------------------------------------------------------
@@ -99,6 +101,7 @@ ExifFormatAttrib ExifFormatList[] = {
 
 /* tags that are special, or need special treatment */
 #define TAG_EXIFOFFSET          0x8769
+#define TAG_EXIFMAKERNOTE      0x927c
 
 
 /*
@@ -107,8 +110,6 @@ ExifFormatAttrib ExifFormatList[] = {
  *-----------------------------------------------------------------------------
  */
 
-#define EXIF_TEXT_LIST_END { -1, NULL }
-
 static ExifTextList ExifOrientationList[] = {
        { EXIF_ORIENTATION_UNKNOWN,     N_("unknown") },
        { EXIF_ORIENTATION_TOP_LEFT,    N_("top left") },
@@ -393,8 +394,7 @@ ExifMarker ExifKnownMarkersList[] = {
 { 0x9215, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,    "ExposureIndex",        NULL, NULL },
 { 0x9216, EXIF_FORMAT_BYTE_UNSIGNED, 4,                "TIFF/EPStandardID",    NULL, NULL },
 
-       /* end is marked by 0 tag */
-{ 0x0000, EXIF_FORMAT_UNKNOWN, 0, NULL, NULL, NULL }
+EXIF_MARKER_LIST_END
 };
 
 ExifMarker ExifUnknownMarkersList[] = {
@@ -461,9 +461,7 @@ typedef struct __attribute__((packed)) {
 } IFDEntry;
 
 
-static ExifMarker *exif_marker_from_tag(uint16_t tag);
-static int parse_IFD_table(ExifData *exif, unsigned char *tiff, int offset,
-                          int size, int byte_order);
+static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list);
 
 /*
  *-----------------------------------------------------------------------------
@@ -471,7 +469,8 @@ static int parse_IFD_table(ExifData *exif, unsigned char *tiff, int offset,
  *-----------------------------------------------------------------------------
  */
 
-static ExifItem *exif_item_new(ExifFormatType format, unsigned int tag, unsigned int elements, ExifMarker *marker)
+ExifItem *exif_item_new(ExifFormatType format, unsigned int tag,
+                       unsigned int elements, const ExifMarker *marker)
 {
        ExifItem *item;
 
@@ -714,17 +713,18 @@ static int goto_next_marker(unsigned char **f, int *size, int *marker)
  *-------------------------------------------------------------------
  */
 
-static ExifMarker *exif_marker_from_tag(uint16_t tag)
+static const ExifMarker *exif_marker_from_tag(uint16_t tag, const ExifMarker *list)
 {
-       static int len = sizeof(ExifKnownMarkersList)/sizeof(ExifMarker) - 1;
        int i = 0;
 
-       while (i < len && ExifKnownMarkersList[i].tag != tag)
+       if (!list) return NULL;
+
+       while (list[i].tag != 0 && list[i].tag != tag)
                {
                i++;
                }
 
-       return (i >= len ? NULL : &ExifKnownMarkersList[i]);
+       return (list[i].tag == 0 ? NULL : &list[i]);
 }
 
 static void rational_from_data(ExifRational *r, void *src, int byte_order)
@@ -733,7 +733,7 @@ static void rational_from_data(ExifRational *r, void *src, int byte_order)
        r->den = swab_int32(*(uint32_t*)(src + sizeof(uint32_t)), byte_order);
 }
 
-static 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, int len, ExifFormatType src_format, int byte_order)
 {
        int bs;
        int ne;
@@ -818,14 +818,15 @@ static void exif_item_copy_data(ExifItem *item, void *src, int len, ExifFormatTy
                }
 }
 
-static int parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset,
-                          int size, int byte_order)
+static int exif_parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset,
+                               int size, int byte_order,
+                               const ExifMarker *list)
 {
        IFDEntry *ent = (IFDEntry*)(tiff+offset);
        uint32_t swabed_data;
        void *data;
        int data_len;
-       ExifMarker *marker;
+       const ExifMarker *marker;
        ExifItem *item;
 
        ent->tag = swab_int16(ent->tag, byte_order);
@@ -836,7 +837,7 @@ static int parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset,
        /* 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.
         */
-       marker = exif_marker_from_tag(ent->tag);
+       marker = exif_marker_from_tag(ent->tag, list);
        if (!marker)
                {
                if (ent->format > EXIF_FORMAT_DOUBLE)
@@ -901,16 +902,26 @@ static int parse_IFD_entry(ExifData *exif, unsigned char *tiff, int offset,
        exif_item_copy_data(item, data, data_len, ent->format, byte_order);
        exif->items = g_list_prepend(exif->items, item);
 
-       if (item->tag == TAG_EXIFOFFSET)
+       if (list == ExifKnownMarkersList)
                {
-               parse_IFD_table(exif, tiff, swabed_data, size, byte_order);
+               switch (item->tag)
+                       {
+                       case TAG_EXIFOFFSET:
+                               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);
+                               break;
+                       }
                }
 
        return 0;
 }
 
-static int parse_IFD_table(ExifData *exif, unsigned char *tiff, int offset,
-                          int size, int byte_order)
+int exif_parse_IFD_table(ExifData *exif,
+                        unsigned char *tiff, int offset,
+                        int size, int byte_order,
+                        const ExifMarker *list)
 {
        int i, nb_entries;
 
@@ -924,7 +935,7 @@ static int parse_IFD_table(ExifData *exif, unsigned char *tiff, int offset,
 
        for (i=0; i<nb_entries; ++i)
                {
-               parse_IFD_entry(exif, tiff, offset+2+i*sizeof(IFDEntry), size, byte_order);
+               exif_parse_IFD_entry(exif, tiff, offset+2+i*sizeof(IFDEntry), size, byte_order, list);
                }
 
        return 0;
@@ -965,7 +976,7 @@ static int parse_TIFF(ExifData *exif, unsigned char *tiff, int size)
 
        offset = swab_int32(((TIFFHeader*)tiff)->IFD_offset, byte_order);
 
-       return parse_IFD_table(exif, tiff, offset, size, byte_order);
+       return exif_parse_IFD_table(exif, tiff, offset, size, byte_order, ExifKnownMarkersList);
 }
 
 static int parse_JPEG(ExifData *exif, unsigned char *f, int size)
@@ -1132,7 +1143,7 @@ ExifItem *exif_get_item(ExifData *exif, const gchar *key)
 
 gchar *exif_item_get_data_as_text(ExifItem *item)
 {
-       ExifMarker *marker;
+       const ExifMarker *marker;
        gpointer data;
        GString *string;
        gchar *text;
index 5298dd3..f13828f 100644 (file)
@@ -90,7 +90,7 @@ struct _ExifItem
 {
        ExifFormatType format;
        int tag;
-       ExifMarker *marker;
+       const ExifMarker *marker;
        int elements;
        gpointer data;
        int data_len;
@@ -106,12 +106,16 @@ struct _ExifMarker
        ExifTextList    *list;
 };
 
+#define EXIF_MARKER_LIST_END { 0x0000, EXIF_FORMAT_UNKNOWN, 0, NULL, NULL, NULL }
+
 struct _ExifTextList
 {
        int value;
        const char* description;
 };
 
+#define EXIF_TEXT_LIST_END { -1, NULL }
+
 
 typedef struct _ExifFormattedText ExifFormattedText;
 struct _ExifFormattedText
@@ -188,4 +192,18 @@ const gchar *exif_get_description_by_key(const gchar *key);
 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);
+
+gint exif_parse_IFD_table(ExifData *exif,
+                         unsigned char *tiff, int offset,
+                         int size, int byte_order,
+                         const ExifMarker *list);
+
+
+
 #endif
index f6ff838..1749257 100644 (file)
@@ -31,6 +31,8 @@
 #include "format_canon.h"
 #include "format_raw.h"
 
+#include "exif.h"
+
 
 #if 0
   #define CANON_DEBUG
@@ -470,4 +472,390 @@ return_only:
 
 }
 
+/*
+ *-----------------------------------------------------------------------------
+ * EXIF Makernote for Canon
+ *-----------------------------------------------------------------------------
+ */
+
+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 ExifTextList CanonSet1Quality[] = {
+       { 2,    "normal" },
+       { 3,    "fine" },
+       { 5,    "superfine" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1FlashMode[] = {
+       { 0,    "flash not fired" },
+       { 1,    "auto" },
+       { 2,    "on" },
+       { 3,    "red eye reduction" },
+       { 4,    "slow synchro" },
+       { 5,    "auto with red eye reduction" },
+       { 6,    "on with red eye reduction" },
+       { 16,   "external flash" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1DriveMode[] = {
+       { 0,    "single or timer" },
+       { 1,    "continuous" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1FocusMode[] = {
+       { 0,    "one-shot" },
+       { 1,    "AI servo" },
+       { 2,    "AI focus" },
+       { 3,    "manual" },
+       { 4,    "single" },
+       { 5,    "continuous" },
+       { 6,    "manual" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1ImageSize[] = {
+       { 0,    "large" },
+       { 1,    "medium" },
+       { 2,    "small" },
+       /* where (or) does Medium 1/2 fit in here ? */
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1ShootingMode[] = {
+       { 0,    "auto" },
+       { 1,    "manual" },
+       { 2,    "landscape" },
+       { 3,    "fast shutter" },
+       { 4,    "slow shutter" },
+       { 5,    "night" },
+       { 6,    "black and white" },
+       { 7,    "sepia" },
+       { 8,    "portrait" },
+       { 9,    "sports" },
+       { 10,   "macro" },
+       { 11,   "panoramic focus" },
+       EXIF_TEXT_LIST_END
+};
+
+/* Don't think this is interpreted correctly/completely, A60 at 2.5x Digital sets value of 3 */
+static ExifTextList CanonSet1DigitalZoom[] = {
+       { 0,    "none" },
+       { 1,    "2x" },
+       { 2,    "4x" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1ConSatSharp[] = {
+       { 0,    "normal" },
+       { 1,    "high" },
+       { 65535,"low" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1ISOSpeed[] = {
+/*     { 0,    "not set/see EXIF tag" }, */
+       { 15,   "auto" },
+       { 16,   "50" },
+       { 17,   "100" },
+       { 18,   "200" },
+       { 19,   "400" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1MeteringMode[] = {
+       { 3,    "evaluative" },
+       { 4,    "partial" },
+       { 5,    "center-weighted" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1FocusType[] = {
+       { 0,    "manual" },
+       { 1,    "auto" },
+       { 3,    "macro" },
+       { 8,    "locked" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1AutoFocusPoint[] = {
+       { 12288,        "manual focus" },
+       { 12289,        "auto" },
+       { 12290,        "right" },
+       { 12291,        "center" },
+       { 12292,        "left" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1ExposureMode[] = {
+       { 0,    "auto" },
+       { 1,    "program" },
+       { 2,    "Tv priority" },
+       { 3,    "Av priority" },
+       { 4,    "manual" },
+       { 5,    "A-DEP" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1FlashFired[] = {
+       { 0,    "no" },
+       { 1,    "yes" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet1FocusCont[] = {
+       { 0,    "no (single)" },
+       { 1,    "yes" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifMarker CanonSet1[] = {
+/* 0 is length of array in bytes (2 x array size) */
+{ 1,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.MacroMode",   "Macro mode",           CanonSet1MacroMode },
+{ 2,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SelfTimer",   "Self timer (10ths of second)", NULL },
+{ 3,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Quality",     "Quality",              CanonSet1Quality },
+{ 4,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashMode",   "Flash mode",           CanonSet1FlashMode },
+{ 5,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.DriveMode",   "Drive mode",           CanonSet1DriveMode },
+{ 7,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocusMode",   "Focus mode",           CanonSet1FocusMode },
+{ 10,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ImageSize",   "Image size",           CanonSet1ImageSize },
+{ 11,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ShootingMode","Shooting mode",        CanonSet1ShootingMode },
+ { 11, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ExposureProgram",       "ExposureProgram",      CanonSet1ShootingMode },
+{ 12,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.DigitalZoom", "Digital zoom",         CanonSet1DigitalZoom },
+{ 13,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Contrast",    "Contrast",             CanonSet1ConSatSharp },
+{ 14,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Saturation",  "Saturation",           CanonSet1ConSatSharp },
+{ 15,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Sharpness",   "Sharpness",            CanonSet1ConSatSharp },
+{ 16,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ISOSpeed",    "ISO speed",            CanonSet1ISOSpeed },
+ { 16, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ISOSpeedRatings",       "ISO speed",            CanonSet1ISOSpeed },
+{ 17,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.MeteringMode","Metering mode",        CanonSet1MeteringMode },
+{ 18,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocusType",   "Focus type",           CanonSet1FocusType },
+{ 19,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.AutoFocus",   "AutoFocus point",      CanonSet1AutoFocusPoint },
+{ 20,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ExposureMode","Exposure mode",        CanonSet1ExposureMode },
+ { 20, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ExposureMode",          "Exposure mode",        CanonSet1ExposureMode },
+{ 23,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthLong","Long focal length", NULL },
+{ 24,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthShort","Short focal length", NULL },
+{ 25,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthUnits","Focal units per mm", NULL },
+{ 28,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashFired",  "Flash fired",          CanonSet1FlashFired },
+{ 29,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashDetails","Flash details",        NULL },
+{ 32,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ContinuousFocus","Continuous focus",  CanonSet1FocusCont },
+EXIF_MARKER_LIST_END
+};
+
+static ExifTextList CanonSet2WhiteBalance[] = {
+       { 0,    "auto" },
+       { 1,    "sunny" },
+       { 2,    "cloudy" },
+       { 3,    "tungsten" },
+       { 4,    "flourescent" },
+       { 5,    "flash" },
+       { 6,    "custom" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonSet2FlashBias[] = {
+       { 0x0000,       "0" },
+       { 0x000c,       "0.33" },
+       { 0x0010,       "0.5" },
+       { 0x0014,       "0.67" },
+       { 0x0020,       "1" },
+       { 0x002c,       "1.33" },
+       { 0x0030,       "1.5" },
+       { 0x0034,       "1.67" },
+       { 0x0040,       "2" },
+       { 0xffc0,       "-2" },
+       { 0xffcc,       "-1.67" },
+       { 0xffd0,       "-1.5" },
+       { 0xffd4,       "-1.33" },
+       { 0xffe0,       "-1" },
+       { 0xffec,       "-0.67" },
+       { 0xfff0,       "-0.5" },
+       { 0xfff4,       "-0.33" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifMarker CanonSet2[] = {
+/* 0 is length of array in bytes (2 x array size) */
+{ 7,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.WhiteBalance","White balance",        CanonSet2WhiteBalance },
+ { 7,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "LightSource",           "White balance",        CanonSet2WhiteBalance },
+{ 9,   EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SequenceNumber","Sequence number",    NULL },
+{ 15,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashBias",   "Flash bias",           CanonSet2FlashBias },
+/* distance needs more than just this (metric) value */
+{ 19,  EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SubjectDistance",     "Subject Distance", NULL },
+EXIF_MARKER_LIST_END
+};
+
+#if 0
+
+static ExifTextList CanonCustomEnable[] = {
+       { 0,    "off" },
+       { 1,    "on" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonCustomEnableInvert[] = {
+       { 0,    "on" },
+       { 1,    "off" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonCustomExposureLevel[] = {
+       { 0,    "1/2 stop" },
+       { 1,    "1/3 stop" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonCustomAVShutterSpeed[] = {
+       { 0,    "auto" },
+       { 1,    "1/200 (fixed)" },
+       EXIF_TEXT_LIST_END
+};
+
+static ExifTextList CanonCustomShutterCurtainSync[] = {
+       { 0,    "1st" },
+       { 1,    "2nd" },
+       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 }
+};
+
+#endif
+
+static ExifMarker CanonExifMarkersList[] = {
+       { 1,    EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.Settings1",          NULL, NULL },
+       { 4,    EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.Settings2",          NULL, NULL },
+       { 6,    EXIF_FORMAT_STRING, -1,         "MkN.Canon.ImageType",          "Image type", NULL },
+       { 7,    EXIF_FORMAT_STRING, -1,         "MkN.Canon.FirmwareVersion",    "Firmware version", NULL },
+       { 8,    EXIF_FORMAT_LONG_UNSIGNED, 1,   "MkN.Canon.ImageNumber",        "Image number", NULL },
+       { 9,    EXIF_FORMAT_STRING, -1,         "MkN.Canon.OwnerName",          "Owner name", NULL },
+       { 12,   EXIF_FORMAT_BYTE_UNSIGNED, -1,  "MkN.Canon.SerialNumber",       "Camera serial number", NULL },
+       { 15,   EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.CustomFunctions",    NULL, NULL },
+       EXIF_MARKER_LIST_END
+};
+
+static void canon_mknote_parse_settings(ExifData *exif,
+                                       guint16 *data, guint32 len, int byte_order,
+                                       ExifMarker *list)
+{
+       gint i;
+
+       i = 0;
+       while (list[i].tag != 0)
+               {
+               if (list[i].tag < len)
+                       {
+                       ExifItem *item;
+
+                       item = exif_item_new(EXIF_FORMAT_SHORT_UNSIGNED, list[i].tag, 1, &list[i]);
+                       exif_item_copy_data(item, &data[list[i].tag], 1, EXIF_FORMAT_SHORT_UNSIGNED, byte_order);
+                       exif->items = g_list_prepend(exif->items, item);
+                       }
+
+               i++;
+               }
+}
+
+#if 0
+static void canon_mknote_parse_convert(ExifData *exif)
+{
+       gint value;
+
+       /* seems we need more than only this value for distance */
+       if (exif_get_integer(exif, "MkN.Canon.SubjectDistance", &value))
+               {
+               static ExifMarker marker= { 0x9206, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,
+                                           "SubjectDistance", "Subject distance", NULL };
+               ExifItem *item;
+               ExifRational *rational;
+
+               item = exif_item_new(marker.format, marker.tag, 1, &marker);
+               rational = item->data;
+               rational->num = value;
+               rational->den = 100;
+
+               exif->items = g_list_prepend(exif->items, item);
+               }
+
+       /* Serial Number untested */
+       if (exif_get_integer(exif, "MkN.Canon.SerialNumber", &value))
+               {
+               static ExifMarker marker= { 12, EXIF_FORMAT_STRING, -1,
+                                           "SerialNumber", "Camera serial number", NULL };
+               ExifItem *item;
+               gchar *text;
+               gint l;
+
+               text = g_strdup_printf("%04X%05d", value & 0xff00 >> 8, value & 0x00ff);
+               l = strlen(text);
+               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);
+               }
+}
+#endif
+
+gint format_exif_makernote_canon_parse(ExifData *exif, unsigned char *tiff, int offset,
+                                      int size, int 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)
+               {
+               return FALSE;
+               }
+
+       item = exif_get_item(exif, "MkN.Canon.Settings1");
+       if (item)
+               {
+               canon_mknote_parse_settings(exif, item->data, item->data_len, byte_order, CanonSet1);
+               }
+
+       item = exif_get_item(exif, "MkN.Canon.Settings2");
+       if (item)
+               {
+               canon_mknote_parse_settings(exif, item->data, item->data_len, byte_order, CanonSet2);
+               }
+
+#if 0
+       canon_mknote_parse_convert(exif);
+#endif
+
+       return TRUE;
+}
+
 
index ffbdd26..61eaef2 100644 (file)
@@ -19,6 +19,9 @@
 #define __FORMAT_RAW_CANON_H
 
 
+#include "exif.h"
+
+
 gint format_raw_test_canon(const void *data, const guint len,
                           guint *image_offset, guint *exif_offset);
 
@@ -27,5 +30,9 @@ gint format_raw_test_canon(const void *data, const guint len,
                         { "\x49\x49\x2a\00", 4, "Canon cr2 format", format_raw_test_canon }
 
 
+gint format_exif_makernote_canon_parse(ExifData *exif, unsigned char *tiff, int offset,
+                                      int size, int byte_order);
+
+
 #endif
 
index 4b03545..ce62c55 100644 (file)
@@ -130,7 +130,7 @@ gint format_raw_img_exif_offsets_fd(int fd, const void *header_data, const guint
        map_data = mmap(0, map_len, PROT_READ, MAP_PRIVATE, fd, 0);
        if (map_data == MAP_FAILED)
                {
-               printf("Failed to mmap of file %d\n", fd);
+               printf("Failed to mmap file %d\n", fd);
                return FALSE;
                }