예제 #1
0
static void
vips_exif_exif_entry( ExifEntry *entry, VipsExif *ve )
{
	const char *tag_name;
	char vips_name_txt[256];
	VipsBuf vips_name = VIPS_BUF_STATIC( vips_name_txt );

	if( !(tag_name = exif_tag_get_name( entry->tag )) )
		return;

	vips_buf_appendf( &vips_name, "exif-ifd%d-%s", 
		exif_entry_get_ifd( entry ), tag_name );

	/* Does this field exist on the image? If not, schedule it for
	 * removal.
	 */
	if( !vips_image_get_typeof( ve->image, vips_buf_all( &vips_name ) ) ) 
		ve->to_remove = g_slist_prepend( ve->to_remove, entry );

	/* Orientation is really set from the vips
	 * VIPS_META_ORIENTATION tag. If that's been deleted, we must delete
	 * any matching EXIF tags too.
	 */
	if( strcmp( tag_name, "Orientation" ) == 0 &&
		vips_image_get_typeof( ve->image, VIPS_META_ORIENTATION ) )
		ve->to_remove = g_slist_prepend( ve->to_remove, entry );
}
예제 #2
0
static void
vips_exif_set_int( ExifData *ed, 
	ExifEntry *entry, unsigned long component, void *data )
{
	int value = *((int *) data);

	ExifByteOrder bo;
	size_t sizeof_component;
	size_t offset = component;

	if( entry->components <= component ) {
		VIPS_DEBUG_MSG( "vips_exif_set_int: too few components\n" );
		return;
	}

	/* Wait until after the component check to make sure we cant get /0.
	 */
	bo = exif_data_get_byte_order( ed );
	sizeof_component = entry->size / entry->components;
	offset = component * sizeof_component;

	VIPS_DEBUG_MSG( "vips_exif_set_int: %s = %d\n",
		exif_tag_get_name( entry->tag ), value );

	if( entry->format == EXIF_FORMAT_SHORT ) 
		exif_set_short( entry->data + offset, bo, value );
	else if( entry->format == EXIF_FORMAT_SSHORT ) 
		exif_set_sshort( entry->data + offset, bo, value );
	else if( entry->format == EXIF_FORMAT_LONG ) 
		exif_set_long( entry->data + offset, bo, value );
	else if( entry->format == EXIF_FORMAT_SLONG ) 
		exif_set_slong( entry->data + offset, bo, value );
}
예제 #3
0
/* Does both signed and unsigned rationals from a double*.
 *
 * Don't change the exit entry if the value currently there is a good
 * approximation of the double we are trying to set.
 */
static void
vips_exif_set_double( ExifData *ed, 
	ExifEntry *entry, unsigned long component, void *data )
{
	double value = *((double *) data);

	ExifByteOrder bo;
	size_t sizeof_component;
	size_t offset;
	double old_value;

	if( entry->components <= component ) {
		VIPS_DEBUG_MSG( "vips_exif_set_double: "
			"too few components\n" );
		return;
	}

	/* Wait until after the component check to make sure we cant get /0.
	 */
	bo = exif_data_get_byte_order( ed );
	sizeof_component = entry->size / entry->components;
	offset = component * sizeof_component;

	VIPS_DEBUG_MSG( "vips_exif_set_double: %s = %g\n",
		exif_tag_get_name( entry->tag ), value );

	if( entry->format == EXIF_FORMAT_RATIONAL ) {
		ExifRational rv;

		rv = exif_get_rational( entry->data + offset, bo );
		old_value = (double) rv.numerator / rv.denominator;
		if( VIPS_FABS( old_value - value ) > 0.0001 ) {
			vips_exif_double_to_rational( value, &rv ); 

			VIPS_DEBUG_MSG( "vips_exif_set_double: %u / %u\n", 
				rv.numerator, 
				rv.denominator ); 

			exif_set_rational( entry->data + offset, bo, rv );
		}
	}
	else if( entry->format == EXIF_FORMAT_SRATIONAL ) {
		ExifSRational srv;

		srv = exif_get_srational( entry->data + offset, bo );
		old_value = (double) srv.numerator / srv.denominator;
		if( VIPS_FABS( old_value - value ) > 0.0001 ) {
			vips_exif_double_to_srational( value, &srv ); 

			VIPS_DEBUG_MSG( "vips_exif_set_double: %d / %d\n", 
				srv.numerator, srv.denominator ); 

			exif_set_srational( entry->data + offset, bo, srv );
		}
	}
}
예제 #4
0
/* Does both signed and unsigned rationals from a char*.
 */
static void
vips_exif_set_rational( ExifData *ed, 
	ExifEntry *entry, unsigned long component, void *data )
{
	char *value = (char *) data;

	ExifByteOrder bo;
	size_t sizeof_component;
	size_t offset;

	if( entry->components <= component ) {
		VIPS_DEBUG_MSG( "vips_exif_set_rational: "
			"too few components\n" );
		return;
	}

	/* Wait until after the component check to make sure we cant get /0.
	 */
	bo = exif_data_get_byte_order( ed );
	sizeof_component = entry->size / entry->components;
	offset = component * sizeof_component;

	VIPS_DEBUG_MSG( "vips_exif_set_rational: %s = \"%s\"\n",
		exif_tag_get_name( entry->tag ), value );

	if( entry->format == EXIF_FORMAT_RATIONAL ) {
		ExifRational rv;

		vips_exif_parse_rational( value, &rv ); 

		VIPS_DEBUG_MSG( "vips_exif_set_rational: %u / %u\n", 
			rv.numerator, 
			rv.denominator ); 

		exif_set_rational( entry->data + offset, bo, rv );
	}
	else if( entry->format == EXIF_FORMAT_SRATIONAL ) {
		ExifSRational srv;

		vips_exif_parse_srational( value, &srv ); 

		VIPS_DEBUG_MSG( "vips_exif_set_rational: %d / %d\n", 
			srv.numerator, srv.denominator ); 

		exif_set_srational( entry->data + offset, bo, srv );
	}
}
예제 #5
0
static void *
vips_exif_exif_remove( ExifEntry *entry, VipsExif *ve )
{
#ifdef DEBUG
{
	const char *tag_name;
	char vips_name_txt[256];
	VipsBuf vips_name = VIPS_BUF_STATIC( vips_name_txt );

	tag_name = exif_tag_get_name( entry->tag );
	vips_buf_appendf( &vips_name, "exif-ifd%d-%s", 
		exif_entry_get_ifd( entry ), tag_name );

	printf( "vips_exif_exif_remove: %s\n", vips_buf_all( &vips_name ) );
}
#endif /*DEBUG*/

	exif_content_remove_entry( ve->content, entry );

	return( NULL );
}
예제 #6
0
void
exif_content_add_entry (ExifContent *c, ExifEntry *entry)
{
	ExifEntry **entries;
	if (!c || !c->priv || !entry || entry->parent) return;

	
	if (exif_content_get_entry (c, entry->tag)) {
		exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
			"An attempt has been made to add "
			"the tag '%s' twice to an IFD. This is against "
			"specification.", exif_tag_get_name (entry->tag));
		return;
	}

	entries = exif_mem_realloc (c->priv->mem,
		c->entries, sizeof (ExifEntry*) * (c->count + 1));
	if (!entries) return;
	entry->parent = c;
	entries[c->count++] = entry;
	c->entries = entries;
	exif_entry_ref (entry);
}
예제 #7
0
static char *
exifdata_get_tag_name_utf8 (ExifTag tag)
{
    return exif_string_to_utf8 (exif_tag_get_name (tag));
}
예제 #8
0
static void
metadataparse_exif_content_foreach_entry_func (ExifEntry * entry,
    void *user_data)
{
  MEUserData *meudata = (MEUserData *) user_data;
  GType type = G_TYPE_NONE;
  ExifByteOrder byte_order;
  const gchar *tag;

  /* We need the byte order */
  if (!entry || !entry->parent || !entry->parent->parent)
    return;

  tag = metadataparse_exif_get_tag_from_exif (entry->tag, &type);
  byte_order = exif_data_get_byte_order (entry->parent->parent);

  if (metadataparse_handle_unit_tags (entry, meudata, byte_order))
    goto done;

  if (!tag)
    goto done;

  if (type == GST_TYPE_FRACTION) {
    gint numerator = 0;
    gint denominator = 1;

    switch (entry->format) {
      case EXIF_FORMAT_SRATIONAL:
      {
        ExifSRational v_srat;

        v_srat = exif_get_srational (entry->data, byte_order);
        if (v_srat.denominator) {
          numerator = (gint) v_srat.numerator;
          denominator = (gint) v_srat.denominator;
        }
      }
        break;
      case EXIF_FORMAT_RATIONAL:
      {
        ExifRational v_rat;

        v_rat = exif_get_rational (entry->data, byte_order);
        if (v_rat.denominator) {
          numerator = (gint) v_rat.numerator;
          denominator = (gint) v_rat.denominator;
        }
        if (meudata->resolution_unit == 3) {
          /* converts from cm to inches */
          if (entry->tag == EXIF_TAG_X_RESOLUTION
              || entry->tag == EXIF_TAG_Y_RESOLUTION) {
            numerator *= 2;
            denominator *= 5;
          }
        }
      }
        break;
      default:
        GST_ERROR ("Unexpected Tag Type");
        goto done;
        break;
    }
    gst_tag_list_add (meudata->taglist, meudata->mode, tag, numerator,
        denominator, NULL);

  } else if (type == GST_TYPE_BUFFER) {
    GstBuffer *buf = gst_buffer_new_and_alloc (entry->components);

    memcpy (GST_BUFFER_DATA (buf), entry->data, entry->components);
    gst_tag_list_add (meudata->taglist, meudata->mode, tag, buf, NULL);
    gst_buffer_unref (buf);
  } else {
    switch (type) {
      case G_TYPE_STRING:
      {
        char buf[2048];
        const gchar *str = exif_entry_get_value (entry, buf, sizeof (buf));
        GString *value = NULL;

        if (entry->tag == EXIF_TAG_DATE_TIME_DIGITIZED
            || entry->tag == EXIF_TAG_DATE_TIME
            || entry->tag == EXIF_TAG_DATE_TIME_ORIGINAL) {
          value = g_string_new_len (str, 20);
          /* 20 is enough memory to hold "YYYY-MM-DDTHH:MM:SS" */

          if (metadataparse_exif_convert_to_datetime (value)) {
            str = value->str;
          } else {
            GST_ERROR ("Unexpected date & time format for %s", tag);
            str = NULL;
          }

        }
        if (str)
          gst_tag_list_add (meudata->taglist, meudata->mode, tag, str, NULL);
        if (value)
          g_string_free (value, TRUE);
      }
        break;
      case G_TYPE_INT:
        /* fall through */
      case G_TYPE_UINT:
      {
        gint value;

        switch (entry->format) {
          case EXIF_FORMAT_SHORT:
            value = exif_get_short (entry->data, byte_order);
            break;
          case EXIF_FORMAT_LONG:
            value = exif_get_long (entry->data, byte_order);
            break;
          default:
            GST_ERROR ("Unexpected Exif Tag Type (%s - %s)",
                tag, exif_format_get_name (entry->format));
            goto done;
            break;
        }
        if (entry->tag == EXIF_TAG_CONTRAST ||
            entry->tag == EXIF_TAG_SATURATION) {
          switch (value) {
            case 0:
              break;
            case 1:
              value = -67;      /* -100-34 /2 */
              break;
            case 2:
              value = 67;       /* 100+34 /2 */
              break;
            default:
              GST_ERROR ("Unexpected value");
              break;
          }
        }
        gst_tag_list_add (meudata->taglist, meudata->mode, tag, value, NULL);
      }
        break;
      case G_TYPE_DOUBLE:
      {
        gdouble value = 0.0;

        if (entry->tag == EXIF_TAG_GPS_LATITUDE
            || entry->tag == EXIF_TAG_GPS_LONGITUDE) {
          ExifRational *rt = (ExifRational *) entry->data;

          /* DDD - degrees */
          value = (gdouble) rt->numerator / (gdouble) rt->denominator;
          GST_DEBUG ("deg: %lu / %lu", (gulong) rt->numerator,
              (gulong) rt->denominator);
          rt++;

          /* MM - minutes and SS - seconds */
          GST_DEBUG ("min: %lu / %lu", (gulong) rt->numerator,
              (gulong) rt->denominator);
          value += (gdouble) rt->numerator / ((gdouble) rt->denominator * 60.0);
          rt++;
          GST_DEBUG ("sec: %lu / %lu", (gulong) rt->numerator,
              (gulong) rt->denominator);
          value +=
              (gdouble) rt->numerator / ((gdouble) rt->denominator * 3600.0);

          /* apply sign */
          if (entry->tag == EXIF_TAG_GPS_LATITUDE) {
            if (((meudata->latitude_ref == 'S') && (value > 0.0)) ||
                ((meudata->latitude_ref == 'N') && (value < 0.0))) {
              value = -value;
            }
          } else {
            if (((meudata->longitude_ref == 'W') && (value > 0.0)) ||
                ((meudata->longitude_ref == 'E') && (value < 0.0))) {
              value = -value;
            }
          }
          GST_DEBUG ("long/lat : %lf", value);
        }
        if (entry->tag == EXIF_TAG_GPS_ALTITUDE) {
          ExifRational v_rat = exif_get_rational (entry->data, byte_order);
          value = (gdouble) v_rat.numerator / (gdouble) v_rat.denominator;
          if (((meudata->altitude_ref == 1) && (value > 0.0)) ||
              ((meudata->altitude_ref == 0) && (value < 0.0))) {
            value = -value;
          }
          GST_DEBUG ("altitude = %lf", value);
        }
        gst_tag_list_add (meudata->taglist, meudata->mode, tag, value, NULL);
      }
        break;
      default:
        break;
    }
  }


done:
  {
#ifndef GST_DISABLE_GST_DEBUG
    char buf[2048];
    GST_LOG ("\n    Entry %p: %s (%s)\n"
        "      Size, Comps: %d, %d\n"
        "      Value: %s\n"
        "      Title: %s\n"
        "      Description: %s\n",
        entry,
        exif_tag_get_name (entry->tag),
        exif_format_get_name (entry->format),
        entry->size,
        (int) (entry->components),
        exif_entry_get_value (entry, buf, sizeof (buf)),
        exif_tag_get_title (entry->tag), exif_tag_get_description (entry->tag));
#endif
  }
  return;

}
void FileSystemScanner::readEXIF(File* file)
{
    static QString EXIFIFD_NAME_EXIF = exif_ifd_get_name(EXIF_IFD_EXIF);

    int maxDataLength = 255;
    char* charData = new char[maxDataLength];

    ExifData* exifData = exif_data_new_from_file(file->fileInfo()->absFilePath().ascii());
//    exif_data_dump(exifData);

    for (int i = 0; i < EXIF_IFD_COUNT; i++) {
        ExifContent* content = exifData->ifd[i];

        QString group = QString(exif_ifd_get_name((ExifIfd) i));
        if (group == EXIFIFD_NAME_EXIF) {

            for (unsigned int e = 0; e < content->count; e++) {
                ExifEntry* entry = content->entries[e];

                ExifTag exifTagType = entry->tag;
                QString title = QString(exif_tag_get_title(entry->tag));
                QString name = QString(exif_tag_get_name(entry->tag));

                exif_entry_get_value(entry, charData, maxDataLength);
                QString data = QString(charData);

                QString description = QString(exif_tag_get_description(entry->tag));
//                tracer->sdebug(__func__) << "    - " << title << " / " << name << " = " << data << " (" << description << ")" << endl;

                // get the exif tagnode title and the tagnode representing this tag from the engine
                TagNode* exifTagNodeTitle = m_engine->exifTagNodeTitle();
                TagNode* exifTagNodeEntry = exifTagNodeTitle->child(title);

                switch (exifTagType) {
                    case EXIF_TAG_DATE_TIME_ORIGINAL:
                    case EXIF_TAG_DATE_TIME_DIGITIZED: {
                        QDateTime dateTime = readExifDateTime(data);
                        TagNodeDateTime* exifTagNodeEntryDateTime = dynamic_cast<TagNodeDateTime*>(exifTagNodeEntry);
                        if (exifTagNodeEntryDateTime == 0) {
                            // tagnode for this EXIF entry does not exist --> create it
                            exifTagNodeEntryDateTime = dynamic_cast<TagNodeDateTime*>(m_engine->createTag(exifTagNodeTitle, TagNode::TYPE_DATETIME, title, description, QString::null));
                            exifTagNodeEntryDateTime->setReadonly(true);
                        }
                        if (dateTime.isValid()) {
                            // create new assoc
                            new FileTagNodeAssocDateTime(file, exifTagNodeEntryDateTime, dateTime);
                        }

                        break;
                    }
                    default: {
                        TagNodeString* exifTagNodeEntryString = dynamic_cast<TagNodeString*>(exifTagNodeEntry);
                        if (exifTagNodeEntryString == 0) {
                            // tagnode for this EXIF entry does not exist --> create it
                            exifTagNodeEntryString = dynamic_cast<TagNodeString*>(m_engine->createTag(exifTagNodeTitle, TagNode::TYPE_STRING, title, description, QString::null));
                            exifTagNodeEntryString->setReadonly(true);
                        }
                        // create new assoc
                        new FileTagNodeAssocString(file, exifTagNodeEntryString, data);
                    }
                }
            }
        }
    }

    exif_data_free(exifData);
    delete charData;
}
/*! Load data for an IFD.
 *
 * \param[in,out] data #ExifData
 * \param[in] ifd IFD to load
 * \param[in] d pointer to buffer containing raw IFD data
 * \param[in] ds size of raw data in buffer at \c d
 * \param[in] offset offset into buffer at \c d at which IFD starts
 * \param[in] recursion_depth number of times this function has been
 * recursively called without returning
 */
static void
exif_data_load_data_content (ExifData *data, ExifIfd ifd,
			     const unsigned char *d,
			     unsigned int ds, unsigned int offset, unsigned int recursion_depth)
{
	ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
	ExifShort n;
	ExifEntry *entry;
	unsigned int i;
	ExifTag tag;

	if (!data || !data->priv) 
		return;

	/* check for valid ExifIfd enum range */
	if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT))
	  return;

	if (recursion_depth > 30) {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
			  "Deep recursion detected!");
		return;
	}

	/* Read the number of entries */
	if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) {
		exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData",
			  "Tag data past end of buffer (%u > %u)", offset+2, ds);
		return;
	}
	n = exif_get_short (d + offset, data->priv->order);
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
	          "Loading %hu entries...", n);
	offset += 2;

	/* Check if we have enough data. */
	if (offset + 12 * n > ds) {
		n = (ds - offset) / 12;
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
				  "Short data; only loading %hu entries...", n);
	}

	for (i = 0; i < n; i++) {

		tag = exif_get_short (d + offset + 12 * i, data->priv->order);
		switch (tag) {
		case EXIF_TAG_EXIF_IFD_POINTER:
		case EXIF_TAG_GPS_INFO_IFD_POINTER:
		case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
		case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
		case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
			o = exif_get_long (d + offset + 12 * i + 8,
					   data->priv->order);
			/* FIXME: IFD_POINTER tags aren't marked as being in a
			 * specific IFD, so exif_tag_get_name_in_ifd won't work
			 */
			exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
				  "Sub-IFD entry 0x%x ('%s') at %u.", tag,
				  exif_tag_get_name(tag), o);
			switch (tag) {
			case EXIF_TAG_EXIF_IFD_POINTER:
				CHECK_REC (EXIF_IFD_EXIF);
				exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_GPS_INFO_IFD_POINTER:
				CHECK_REC (EXIF_IFD_GPS);
				exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
				CHECK_REC (EXIF_IFD_INTEROPERABILITY);
				exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1);
				break;
			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
				thumbnail_offset = o;
				if (thumbnail_offset && thumbnail_length)
					exif_data_load_data_thumbnail (data, d,
								       ds, thumbnail_offset,
								       thumbnail_length);
				break;
			case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
				thumbnail_length = o;
				if (thumbnail_offset && thumbnail_length)
					exif_data_load_data_thumbnail (data, d,
								       ds, thumbnail_offset,
								       thumbnail_length);
				break;
			default:
				return;
			}
			break;
		default:

			/*
			 * If we don't know the tag, don't fail. It could be that new 
			 * versions of the standard have defined additional tags. Note that
			 * 0 is a valid tag in the GPS IFD.
			 */
			if (!exif_tag_get_name_in_ifd (tag, ifd)) {

				/*
				 * Special case: Tag and format 0. That's against specification
				 * (at least up to 2.2). But Photoshop writes it anyways.
				 */
				if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) {
					exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
						  "Skipping empty entry at position %u in '%s'.", i, 
						  exif_ifd_get_name (ifd));
					break;
				}
				exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
					  "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag "
					  "to <*****@*****.**>.", tag, i,
					  exif_ifd_get_name (ifd));
				if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS)
					break;
			}
			entry = exif_entry_new_mem (data->priv->mem);
			if (exif_data_load_data_entry (data, entry, d, ds,
						   offset + 12 * i))
				exif_content_add_entry (data->ifd[ifd], entry);
			exif_entry_unref (entry);
			break;
		}
	}
}
static int
exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
			   const unsigned char *d,
			   unsigned int size, unsigned int offset)
{
	unsigned int s, doff;

	entry->tag        = exif_get_short (d + offset + 0, data->priv->order);
	entry->format     = exif_get_short (d + offset + 2, data->priv->order);
	entry->components = exif_get_long  (d + offset + 4, data->priv->order);

	/* FIXME: should use exif_tag_get_name_in_ifd here but entry->parent 
	 * has not been set yet
	 */
	exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
		  "Loading entry 0x%x ('%s')...", entry->tag,
		  exif_tag_get_name (entry->tag));

	/* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff } 
	 *   -> { 0x000000000 .. 0x7fffffff8 } */
	s = exif_format_get_size(entry->format) * entry->components;
	if ((s < entry->components) || (s == 0)){
		return 0;
	}

	/*
	 * Size? If bigger than 4 bytes, the actual data is not
	 * in the entry but somewhere else (offset).
	 */
	if (s > 4)
		doff = exif_get_long (d + offset + 8, data->priv->order);
	else
		doff = offset + 8;

	/* Sanity checks */
	if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) {
		exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
				  "Tag data past end of buffer (%u > %u)", doff+s, size);	
		return 0;
	}

	entry->data = exif_data_alloc (data, s);
	if (entry->data) {
		entry->size = s;
		memcpy (entry->data, d + doff, s);
	} else {
		/* FIXME: What do our callers do if (entry->data == NULL)? */
		EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", s);
	}

	/* If this is the MakerNote, remember the offset */
	if (entry->tag == EXIF_TAG_MAKER_NOTE) {
		if (!entry->data) {
			exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
					  "MakerNote found with empty data");	
		} else if (entry->size > 6) {
			exif_log (data->priv->log,
					       EXIF_LOG_CODE_DEBUG, "ExifData",
					       "MakerNote found (%02x %02x %02x %02x "
					       "%02x %02x %02x...).",
					       entry->data[0], entry->data[1], entry->data[2],
					       entry->data[3], entry->data[4], entry->data[5],
					       entry->data[6]);
		}
		data->priv->offset_mnote = doff;
	}
	return 1;
}