Refactored MakerNote detection code to put detection of each type
authorDan Fandrich <dan@coneharvesters.com>
Fri, 8 Oct 2010 04:20:04 +0000 (21:20 -0700)
committerDan Fandrich <dan@coneharvesters.com>
Fri, 8 Oct 2010 04:20:04 +0000 (21:20 -0700)
into the module handling that type

ChangeLog
libexif/canon/exif-mnote-data-canon.c
libexif/canon/exif-mnote-data-canon.h
libexif/exif-data.c
libexif/exif-tag.h
libexif/fuji/exif-mnote-data-fuji.c
libexif/fuji/exif-mnote-data-fuji.h
libexif/olympus/exif-mnote-data-olympus.c
libexif/olympus/exif-mnote-data-olympus.h
libexif/pentax/exif-mnote-data-pentax.c
libexif/pentax/exif-mnote-data-pentax.h

index 81f1110..574b6de 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-10-07  Dan Fandrich <dan@coneharvesters.com>
+
+       * Refactored MakerNote detection code to put detection of each type
+         into the module handling that type
+
+2010-09-23  Dan Fandrich <dan@coneharvesters.com>
+
+       * exif_entry_dump() now displays the correct tag name for GPS tags by
+         taking the IFD into account when looking up the name. Fixes
+         bug #3073307.
+
+2010-08-11  Dan Fandrich <dan@coneharvesters.com>
+
+       * Removed redundant sentence. Fixes Ubuntu bug #197306
+
+2010-07-23  Dan Fandrich <dan@coneharvesters.com>
+
+       * Canon EOS 5D Mark II writes Aperture values as invalid values
+         0x80000000/1 which makes pow() throw floating-point exceptions
+
 2010-06-16  Dan Fandrich <dan@coneharvesters.com>
 
        * po/da.po: Updated Danish translation by Joe Hansen
index bf49dff..eb53598 100644 (file)
@@ -346,6 +346,16 @@ exif_mnote_data_canon_get_description (ExifMnoteData *note, unsigned int i)
        return mnote_canon_tag_get_description (dc->entries[m].tag);
 }
 
+int
+exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e)
+{
+       char value[8];
+       ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
+       if (!em) 
+               return 0;
+       return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon");
+}
+
 ExifMnoteData *
 exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o)
 {
index f4d5129..2a1cc87 100644 (file)
@@ -43,6 +43,16 @@ struct _ExifMnoteDataCanon {
        ExifDataOption options;
 };
 
+/*! Detect if MakerNote is recognized as one handled by the Canon module.
+ * 
+ * \param[in] ed image #ExifData to identify as as a Canon type
+ * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but
+ *   duplicated here for convenience
+ * \return 0 if not recognized, nonzero if recognized. The specific nonzero 
+ *   value returned may identify a subtype unique within this module.
+ */
+int exif_mnote_data_canon_identify (const ExifData *ed, const ExifEntry *e);
+
 ExifMnoteData *exif_mnote_data_canon_new (ExifMem *mem, ExifDataOption o);
 
 #endif /* __EXIF_MNOTE_DATA_CANON_H__ */
index 388f8fe..965bb0e 100644 (file)
@@ -729,57 +729,6 @@ typedef enum {
        EXIF_DATA_TYPE_MAKER_NOTE_FUJI          = 6
 } ExifDataTypeMakerNote;
 
-static ExifDataTypeMakerNote
-exif_data_get_type_maker_note (ExifData *d)
-{
-       ExifEntry *e, *em;
-       char value[1024];
-
-       if (!d) 
-               return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
-       
-       e = exif_data_get_entry (d, EXIF_TAG_MAKER_NOTE);
-       if (!e) 
-               return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
-
-       /* Olympus & Nikon & Sanyo */
-       if ((e->size >= 8) && ( !memcmp (e->data, "OLYMP", 6) ||
-                               !memcmp (e->data, "OLYMPUS", 8) ||
-                               !memcmp (e->data, "SANYO", 6) ||
-                               !memcmp (e->data, "EPSON", 6) ||
-                               !memcmp (e->data, "Nikon", 6)))
-               return EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS;
-
-       em = exif_data_get_entry (d, EXIF_TAG_MAKE);
-       if (!em) 
-               return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
-
-       /* Canon */
-       if (!strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon"))
-               return EXIF_DATA_TYPE_MAKER_NOTE_CANON;
-
-       /* Pentax & some variant of Nikon */
-       if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) {
-               if (!strncasecmp (
-                           exif_entry_get_value (em, value, sizeof(value)),
-                           "Nikon", 5))
-                       return EXIF_DATA_TYPE_MAKER_NOTE_NIKON;
-               else
-                       return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;
-       }
-       if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) {
-               return EXIF_DATA_TYPE_MAKER_NOTE_PENTAX;
-       }
-       if ((e->size >= 8) && !memcmp (e->data, "QVC", 4)) {
-               return EXIF_DATA_TYPE_MAKER_NOTE_CASIO;
-       }
-       if ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8)) {
-               return EXIF_DATA_TYPE_MAKER_NOTE_FUJI;
-       }
-
-       return EXIF_DATA_TYPE_MAKER_NOTE_NONE;
-}
-
 /*! If MakerNote is recognized, load it.
  *
  * \param[in,out] data #ExifData
@@ -789,23 +738,32 @@ exif_data_get_type_maker_note (ExifData *d)
 static void
 interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds)
 {
-       switch (exif_data_get_type_maker_note (data)) {
-       case EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS:
-       case EXIF_DATA_TYPE_MAKER_NOTE_NIKON:
+       int mnoteid;
+       ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE);
+       if (!e)
+               return;
+       
+       if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) {
+               exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,
+                       "ExifData", "Olympus MakerNote variant type %d", mnoteid);
                data->priv->md = exif_mnote_data_olympus_new (data->priv->mem);
-               break;
-       case EXIF_DATA_TYPE_MAKER_NOTE_PENTAX:
-       case EXIF_DATA_TYPE_MAKER_NOTE_CASIO:
-               data->priv->md = exif_mnote_data_pentax_new (data->priv->mem);
-               break;
-       case EXIF_DATA_TYPE_MAKER_NOTE_CANON:
+
+       } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) {
+               exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,
+                       "ExifData", "Canon MakerNote variant type %d", mnoteid);
                data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options);
-               break;
-       case EXIF_DATA_TYPE_MAKER_NOTE_FUJI:
+
+       } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) {
+               exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,
+                       "ExifData", "Fuji MakerNote variant type %d", mnoteid);
                data->priv->md = exif_mnote_data_fuji_new (data->priv->mem);
-               break;
-       default:
-               break;
+
+       /* NOTE: Must do Pentax detection last because some of the
+        * heuristics are pretty general. */
+       } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) {
+               exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,
+                       "ExifData", "Pentax MakerNote variant type %d", mnoteid);
+               data->priv->md = exif_mnote_data_pentax_new (data->priv->mem);
        }
 
        /* 
index 5e5f43a..d8b8657 100644 (file)
@@ -202,7 +202,9 @@ typedef enum {
 /*! Return the tag ID given its unique textual name.
  *
  * \param[in] name tag name
- * \return tag ID
+ * \return tag ID, or 0 if tag not found
+ * \note The tag not found value cannot be distinguished from a legitimate
+ *   tag number 0.
  */
 ExifTag          exif_tag_from_name                (const char *name);
 
index 4d1503a..9514654 100644 (file)
@@ -314,6 +314,12 @@ exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
        if (n) ((ExifMnoteDataFuji *) n)->offset = o;
 }
 
+int
+exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
+{
+       return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
+}
+
 ExifMnoteData *
 exif_mnote_data_fuji_new (ExifMem *mem)
 {
index c2d07e6..2a7cd3e 100644 (file)
 #define __MNOTE_FUJI_CONTENT_H__
 
 #include <libexif/exif-mnote-data.h>
-
-typedef struct _ExifMnoteDataFuji        ExifMnoteDataFuji;
-
 #include <libexif/exif-mnote-data-priv.h>
+#include <libexif/exif-data.h>
 #include <libexif/fuji/mnote-fuji-entry.h>
 
+typedef struct _ExifMnoteDataFuji        ExifMnoteDataFuji;
+
 struct _ExifMnoteDataFuji {
        ExifMnoteData parent;
 
@@ -38,6 +38,16 @@ struct _ExifMnoteDataFuji {
        unsigned int offset;
 };
 
+/*! Detect if MakerNote is recognized as one handled by the Fuji module.
+ * 
+ * \param[in] ed image #ExifData to identify as as a Fuji type
+ * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but
+ *   duplicated here for convenience
+ * \return 0 if not recognized, nonzero if recognized. The specific nonzero 
+ *   value returned may identify a subtype unique within this module.
+ */
+int exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e);
+
 ExifMnoteData *exif_mnote_data_fuji_new (ExifMem *);
 
 #endif /* __MNOTE_FUJI_CONTENT_H__ */
index e8d9aef..3098348 100644 (file)
@@ -146,7 +146,7 @@ exif_mnote_data_olympus_save (ExifMnoteData *ne,
                datao += n->offset + 10;
                /* subtract the size here, so the increment in the next case will not harm us */
                *buf_size -= 8 + 2;
-               /* Fall through */
+               /* Fall through to nikonV2 handler */
        case nikonV2: 
                *buf_size += 8 + 2;
                *buf_size += 4; /* Next IFD pointer */
@@ -553,6 +553,49 @@ exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
        if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
 }
 
+int
+exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
+{
+       /* Olympus, Nikon, Sanyo, Epson */
+       if (e->size >= 8) {
+               /* Match the terminating NUL character, too */
+               if (!memcmp (e->data, "OLYMPUS", 8))
+                      return olympusV2;
+               else if (!memcmp (e->data, "OLYMP", 6))
+                      return olympusV1;
+               else if (!memcmp (e->data, "SANYO", 6))
+                      return sanyoV1;
+               else if (!memcmp (e->data, "EPSON", 6))
+                      return epsonV1;
+               else if (!memcmp (e->data, "Nikon", 6)) {
+                       switch (e->data[6]) {
+                               case 1:  return nikonV1;
+                               case 2:  return nikonV2;
+                               default: return 0; /* Unrecognized Nikon variant */
+                       }
+               }
+       }
+
+       /* Another variant of Nikon */
+       if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b)) {
+               char value[5];
+               ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
+
+               if (em) {
+                       const char *v = exif_entry_get_value (em, value, sizeof(value));
+                       if (v && (!strncmp (v, "Nikon", sizeof(value)) || 
+                                         !strncmp (v, "NIKON", sizeof(value)) ))
+                               /* When saved, this variant will be written out like the
+                                * alternative nikonV2 form above instead
+                                */
+                               return nikonV2;
+               }
+       }
+
+       return 0;
+}
+
+
 ExifMnoteData *
 exif_mnote_data_olympus_new (ExifMem *mem)
 {
index fc37ced..9622e3f 100644 (file)
@@ -24,6 +24,7 @@
 #include <libexif/exif-mnote-data-priv.h>
 #include <libexif/olympus/mnote-olympus-entry.h>
 #include <libexif/exif-byte-order.h>
+#include <libexif/exif-data.h>
 #include <libexif/exif-mem.h>
 
 enum OlympusVersion {
@@ -49,6 +50,16 @@ struct _ExifMnoteDataOlympus {
        enum OlympusVersion version;
 };
 
+/*! Detect if MakerNote is recognized as one handled by the Olympus module.
+ * 
+ * \param[in] ed image #ExifData to identify as as an Olympus type
+ * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but
+ *   duplicated here for convenience
+ * \return 0 if not recognized, nonzero if recognized. The specific nonzero 
+ *   value returned may identify a subtype unique within this module.
+ */
+int exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e);
+
 ExifMnoteData *exif_mnote_data_olympus_new (ExifMem *);
 
 #endif /* __MNOTE_OLYMPUS_CONTENT_H__ */
index fdb2e25..757bb72 100644 (file)
@@ -397,6 +397,29 @@ exif_mnote_data_pentax_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
        }
 }
 
+int
+exif_mnote_data_pentax_identify (const ExifData *ed, const ExifEntry *e)
+{
+       if ((e->size >= 8) && !memcmp (e->data, "AOC", 4)) {
+               if (((e->data[4] == 'I') && (e->data[5] == 'I')) ||
+                   ((e->data[4] == 'M') && (e->data[5] == 'M')))
+                       return pentaxV3;
+               else
+                       /* Uses Casio v2 tags */
+                       return pentaxV2;
+       }
+
+       if ((e->size >= 8) && !memcmp (e->data, "QVC", 4))
+               return casioV2;
+
+       /* This isn't a very robust test, so make sure it's done last */
+       /* Maybe we should additionally check for a make of Asahi or Pentax */
+       if ((e->size >= 2) && (e->data[0] == 0x00) && (e->data[1] == 0x1b))
+               return pentaxV1;
+
+       return 0;
+}
+
 ExifMnoteData *
 exif_mnote_data_pentax_new (ExifMem *mem)
 {
index dbf0c82..da9f79a 100644 (file)
@@ -25,6 +25,7 @@
 #include <libexif/exif-mnote-data.h>
 #include <libexif/exif-mnote-data-priv.h>
 #include <libexif/pentax/mnote-pentax-entry.h>
+#include <libexif/exif-data.h>
 #include <libexif/exif-mem.h>
 
 enum PentaxVersion {pentaxV1 = 1, pentaxV2 = 2, pentaxV3 = 3, casioV2 = 4 };
@@ -43,6 +44,16 @@ struct _ExifMnoteDataPentax {
        enum PentaxVersion version;
 };
 
+/*! Detect if MakerNote is recognized as one handled by the Pentax module.
+ * 
+ * \param[in] ed image #ExifData to identify as as a Pentax type
+ * \param[in] e #ExifEntry for EXIF_TAG_MAKER_NOTE, from within ed but
+ *   duplicated here for convenience
+ * \return 0 if not recognized, nonzero if recognized. The specific nonzero 
+ *   value returned may identify a subtype unique within this module.
+ */
+int exif_mnote_data_pentax_identify (const ExifData *ed, const ExifEntry *e);
+
 ExifMnoteData *exif_mnote_data_pentax_new (ExifMem *);
 
 #endif /* __EXIF_MNOTE_DATA_PENTAX_H__ */