Пример #1
0
static void entry_getdata_aux (lua_State *L, ExifEntry *entry, unsigned int n) {
  ExifFormat format = entry->format;
  size_t formatsize = (size_t)exif_format_get_size(format);
  const unsigned char *ptr = entry->data+formatsize*n;
  ExifByteOrder order = exif_data_get_byte_order(entry->parent->parent);

  switch (format) {
  case EXIF_FORMAT_BYTE: lua_pushinteger(L, (ExifByte)*ptr); break;
  case EXIF_FORMAT_SBYTE: lua_pushinteger(L, (ExifSByte)*ptr); break;
  case EXIF_FORMAT_SHORT: lua_pushinteger(L, exif_get_short(ptr, order)); break;
  case EXIF_FORMAT_SSHORT: lua_pushinteger(L, exif_get_sshort(ptr, order)); break;
  case EXIF_FORMAT_LONG: lua_pushnumber(L, exif_get_long(ptr, order)); break;
  case EXIF_FORMAT_SLONG: lua_pushinteger(L, exif_get_slong(ptr, order)); break;
  case EXIF_FORMAT_RATIONAL: {
      ExifRational rat = exif_get_rational(ptr, order);
      pushrational(L, rat.numerator, rat.denominator);
      break;
    }
  case EXIF_FORMAT_SRATIONAL: {
      ExifSRational rat = exif_get_srational(ptr, order);
      pushrational(L, rat.numerator, rat.denominator);
      break;
    }
  case EXIF_FORMAT_ASCII: lua_pushinteger(L, *ptr); break;
  default:
    lua_pushnil(L);
    break;
  }
}
Пример #2
0
static gboolean
parse_exif_gps_coordinate (ExifEntry *entry,
			   gdouble *co,
			   ExifByteOrder byte_order)
{
	gsize val_size;
	ExifRational val;
	gdouble hour = 0, min = 0, sec = 0;

	if (G_UNLIKELY (!MAP_EXIF_ENTRY_IS_GPS_RATIONAL (entry)))
		return FALSE;

	val_size = exif_format_get_size (EXIF_FORMAT_RATIONAL);

	val = exif_get_rational (entry->data, byte_order);
	if (val.denominator != 0)
		hour = (gdouble) val.numerator /
		       (gdouble) val.denominator;

	val = exif_get_rational (entry->data + val_size, byte_order);
	if (val.denominator != 0)
		min = (gdouble) val.numerator /
		      (gdouble) val.denominator;

	val = exif_get_rational (entry->data + (2 * val_size), byte_order);
	if (val.denominator != 0)
		sec = (gdouble) val.numerator /
		      (gdouble) val.denominator;

	if (G_LIKELY (co != NULL)) {
		*co = hour + (min / 60.0) + (sec / 3600.0);
	}

	return TRUE;
}
Пример #3
0
static struct LatLon get_latlon ( ExifData *ed )
{
	struct LatLon ll = { 0.0, 0.0 };
	const struct LatLon ll0 = { 0.0, 0.0 };

	gchar str[128];
	ExifEntry *ee;
	//
	// Lat & Long is necessary to form a waypoint.
	//
	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE);
	if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		return ll0;

	ll.lat = Rational2Double ( ee->data,
							   exif_format_get_size(ee->format),
							   exif_data_get_byte_order(ed) );

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE_REF);
	if ( ee ) {
		exif_entry_get_value ( ee, str, 128 );
		if ( str[0] == 'S' )
			ll.lat = -ll.lat;
	}

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE);
	if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		return ll0;

	ll.lon = Rational2Double ( ee->data,
							   exif_format_get_size(ee->format),
							   exif_data_get_byte_order(ed) );

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE_REF);
	if ( ee ) {
		exif_entry_get_value ( ee, str, 128 );
		if ( str[0] == 'W' )
			ll.lon = -ll.lon;
	}

	return ll;
}
Пример #4
0
static void
exif_mnote_data_canon_save (ExifMnoteData *ne, 
	unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
	unsigned int i, o, s, doff;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number
	 * of entries.
	 */
	*buf_size = 2 + n->count * 12 + 4;
	*buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
	if (!*buf) return;

	/* Save the number of entries */
	exif_set_short (*buf, n->order, (ExifShort) n->count);
	
	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = 2 + i * 12;
		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 4) {
			*buf_size += s;

			/* Ensure even offsets. Set padding bytes to 0. */
			if (s & 1) *buf_size += 1;
			*buf = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * *buf_size);
			if (!*buf) return;
			doff = *buf_size - s;
			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
			exif_set_long (*buf + o, n->order, n->offset + doff);
		} else
			doff = o;

		/*
		 * Write the data. Fill unneeded bytes with 0. Do not
		 * crash if data is NULL.
		 */
		if (!n->entries[i].data) memset (*buf + doff, 0, s);
		else memcpy (*buf + doff, n->entries[i].data, s);
		if (s < 4) memset (*buf + doff + s, 0, (4 - s));
	}
}
void exif_entry_set_gps_coord(ExifData * pEdata, ExifIfd eEifd, ExifTag eEtag,
    ExifRational r1, ExifRational r2, ExifRational r3)
{
    ExifEntry *pE;
    ExifByteOrder eO;

    pE = exif_entry_new ();
    exif_content_add_entry (pEdata->ifd[eEifd], pE);
    exif_entry_gps_initialize(pE, eEtag);
    eO = exif_data_get_byte_order (pE->parent->parent);
    if (pE->data) {
        exif_set_rational (pE->data, eO, r1);
        exif_set_rational (pE->data + exif_format_get_size (pE->format), eO, r2);
        exif_set_rational (pE->data + 2 * exif_format_get_size (pE->format), eO, 
        r3);
    } else {
        printf ("ERROR: unallocated e->data Tag %d\n", eEtag);
    }
    exif_entry_fix (pE);
    exif_entry_unref (pE);
}
Пример #6
0
static ExifEntry* allocateEntry(int tag,
                                ExifFormat format,
                                unsigned int numComponents) {
    ExifMem* mem = exif_mem_new_default();
    ExifEntry* entry = exif_entry_new_mem(mem);

    unsigned int size = numComponents * exif_format_get_size(format);
    entry->data = reinterpret_cast<unsigned char*>(exif_mem_alloc(mem, size));
    entry->size = size;
    entry->tag = static_cast<ExifTag>(tag);
    entry->components = numComponents;
    entry->format = format;

    exif_mem_unref(mem);
    return entry;
}
Пример #7
0
static void
exif_mnote_data_canon_load (ExifMnoteData *ne,
	const unsigned char *buf, unsigned int buf_size)
{
	ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
	ExifShort c;
	unsigned int i, o, s;

	if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return;

	/* Read the number of entries and remove old ones. */
	c = exif_get_short (buf + 6 + n->offset, n->order);
	exif_mnote_data_canon_clear (n);

	/* Parse the entries */
	for (i = 0; i < c; i++) {
		o = 6 + 2 + n->offset + 12 * i;
	  if (o + 8 > buf_size) return;

		n->count = i + 1;
		n->entries = exif_mem_realloc (ne->mem, n->entries,
				sizeof (MnoteCanonEntry) * (i+1));
		memset (&n->entries[i], 0, sizeof (MnoteCanonEntry));
	  n->entries[i].tag        = exif_get_short (buf + o, n->order);
	  n->entries[i].format     = exif_get_short (buf + o + 2, n->order);
	  n->entries[i].components = exif_get_long (buf + o + 4, n->order);
	  n->entries[i].order      = n->order;

	  /*
	   * Size? If bigger than 4 bytes, the actual data is not
	   * in the entry but somewhere else (offset).
	   */
	  s = exif_format_get_size (n->entries[i].format) * n->entries[i].components;
		if (!s) return;
		o += 8;
		if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
		if (o + s > buf_size) return;

		/* Sanity check */
		n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s);
		if (!n->entries[i].data) return;
		n->entries[i].size = s;
		memcpy (n->entries[i].data, buf + o, s);
	}
}
Пример #8
0
void write_sgeo_app2(JPEGSection *section, ExifData *exif)
{
	int size_sgeo_bytes = 10;
	unsigned int i = 0;
	unsigned int s = 0;
	unsigned int next_data = 0;
	ExifEntry *entry = NULL;
	ExifContent *sgeo_content = NULL;
	unsigned char *d = NULL;

	sgeo_content = exif->ifd[EXIF_IFD_SGEO];
	size_sgeo_bytes += sgeo_content->count * 12;
	for (i = 0; i < sgeo_content->count; i++)
	{
		entry = sgeo_content->entries[i];
		if (entry != NULL)
		{
			s = exif_format_get_size(entry->format) * entry->components;
			if (s > 4)
				size_sgeo_bytes += s;
				//s += 12;// +tag size
			//else
			//	s = 12;
		}
	}

	section->content._generic.data = (unsigned char* )calloc((size_t)size_sgeo_bytes, 1);
	if (section->content._generic.data == NULL)
		return;

	section->marker = JPEG_MARKER_APP2;
	section->content._generic.size = size_sgeo_bytes;

	d = section->content._generic.data;
	memcpy(d, "FPXR\0\0\0\0", 8);
	d = d + 8;

	write_content_binary(d, sgeo_content, exif->priv->order,
		8 + // "FPXR\0\0\0\0"
		2); // size APP2
}
Пример #9
0
ExifEntry *create_tag_in_content(ExifContent *content, ExifTag tag, size_t len, ExifFormat exifFormat)
{
	void *buf;
	ExifEntry *entry;
	size_t size;
	
	/* Create a memory allocator to manage this ExifEntry */
	ExifMem *mem = exif_mem_new_default();
	if (!mem) return NULL;
	
	/* Create a new ExifEntry using our allocator */
	entry = exif_entry_new_mem (mem);
	if (entry)
	{
		/* Allocate memory to use for holding the tag data */
		size = len * exif_format_get_size(exifFormat);
		
		buf = exif_mem_alloc(mem, size);
		if (buf)
		{
			/* Fill in the entry */
			entry->data = (unsigned char*)buf;
			entry->size = size;
			entry->tag = tag;
			entry->components = len;
			entry->format = exifFormat;

			/* Attach the ExifEntry to an IFD */
			exif_content_add_entry (content, entry);
		}
		
		exif_entry_unref(entry);
	}

	exif_mem_unref(mem);

	return entry;
}
Пример #10
0
static bool createEntry(ExifData* exifData,
                        ExifIfd ifd,
                        int tag,
                        const float (&values)[N],
                        float denominator = 1000.0) {
    removeExistingEntry(exifData, ifd, tag);
    ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
    ExifEntry* entry = allocateEntry(tag, EXIF_FORMAT_RATIONAL, N);
    exif_content_add_entry(exifData->ifd[ifd], entry);
    unsigned int rationalSize = exif_format_get_size(EXIF_FORMAT_RATIONAL);
    for (size_t i = 0; i < N; ++i) {
        ExifRational rational = {
            static_cast<uint32_t>(values[i] * denominator),
            static_cast<uint32_t>(denominator)
        };

        exif_set_rational(&entry->data[i * rationalSize], byteOrder, rational);
    }

    // Unref entry after changing owner to the ExifData struct
    exif_entry_unref(entry);
    return true;
}
Пример #11
0
void write_content_binary(unsigned char *data, ExifContent *content, ExifByteOrder order, unsigned int offset)
{
	unsigned int i = 0;
	unsigned int next_data = 0;
	ExifEntry *entry = NULL;
	unsigned int s = 0;
	unsigned char *d = data;

	exif_set_short(d, order, content->count);
	d += 2;
	next_data = 2 + offset + content->count * 12;// + 2;
	for (i = 0; i < content->count; i++)
	{
		entry = content->entries[i];
		if (entry != NULL)
		{
			exif_set_short(d + 0x00, order, entry->tag);
			exif_set_short(d + 0x02, order, entry->format);
			exif_set_long (d + 0x04, order, entry->components);
			s = exif_format_get_size(entry->format) * entry->components;
			if (s > 4)
			{
				exif_set_long (d + 0x08, order, next_data + 2*0);// начало смещения данных после APP2 (2 байта)
				memcpy(data + next_data - offset, entry->data, s);
				next_data += s;
			}
			else
			{
				if (entry->tag == SGEO_TAG_VERSIONID)
					write_sgeo_version(d + 0x08, order);
				else
					memcpy(d + 0x08, entry->data, s);
			}
			d = d + 0x0c;
		}
	}
}
Пример #12
0
static void
exif_mnote_data_olympus_load (ExifMnoteData *en,
			      const unsigned char *buf, unsigned int buf_size)
{
	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
	ExifShort c;
	unsigned int i, s, o, o2 = 0, datao = 6, base = 0;

	if (!n || !buf) return;

	/* Start of interesting data */
	o2 = 6 + n->offset;

	/*
	 * Olympus headers start with "OLYMP" and need to have at least
	 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
	 * number of entries, and 12 for one entry.
	 *
	 * Nikon headers start with "Nikon" (6 bytes including '\0'),
	 * version number (1 or 2).
	 *
	 * Version 1 continues with 0, 1, 0, number_of_tags,
	 * or just with number_of_tags (models D1H, D1X...).
	 *
	 * Version 2 continues with an unknown byte (0 or 10),
	 * two unknown bytes (0), "MM" or "II", another byte 0 and
	 * lastly 0x2A.
	 */
	if (buf_size - n->offset < 22) return;
	if (!memcmp (buf + o2, "OLYMP", 6)) {
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Olympus maker note v1...");

		/* The number of entries is at position 8. */
		n->version = olympusV1;
		if (buf[o2 + 6] == 1)
			n->order = EXIF_BYTE_ORDER_INTEL;
		else if (buf[o2 + 6 + 1] == 1)
			n->order = EXIF_BYTE_ORDER_MOTOROLA;
		o2 += 8;

	} else if (!memcmp (buf + o2, "OLYMPUS", 8)) {
		/* Olympus S760, S770 */
		datao = o2;
		o2 += 8;
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
			buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);

		if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
			n->order = EXIF_BYTE_ORDER_INTEL;
		else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
			n->order = EXIF_BYTE_ORDER_MOTOROLA;

		/* The number of entries is at position 8+4. */
		n->version = olympusV2;
		o2 += 4;

	} else if (!memcmp (buf + o2, "Nikon", 6)) {
		o2 += 6;
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Nikon maker note (0x%02x, %02x, %02x, "
			"%02x, %02x, %02x, %02x, %02x)...",
			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
		/* The first byte is the version. */
		if (o2 >= buf_size) return;
		n->version = buf[o2];
		o2 += 1;

		/* Skip an unknown byte (00 or 0A). */
		o2 += 1;

		switch (n->version) {
		case nikonV1:

			base = MNOTE_NIKON1_TAG_BASE;
			break;

		case nikonV2:

			/* Skip 2 unknown bytes (00 00). */
			o2 += 2;

			/*
			 * Byte order. From here the data offset
			 * gets calculated.
			 */
			datao = o2;
			if (o2 >= buf_size) return;
			if (!strncmp ((char *)&buf[o2], "II", 2))
				n->order = EXIF_BYTE_ORDER_INTEL;
			else if (!strncmp ((char *)&buf[o2], "MM", 2))
				n->order = EXIF_BYTE_ORDER_MOTOROLA;
			else {
				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
					"ExifMnoteDatalympus", "Unknown "
					"byte order '%c%c'", buf[o2],
					buf[o2 + 1]);
				return;
			}
			o2 += 2;

			/* Skip 2 unknown bytes (00 2A). */
			o2 += 2;

			/* Go to where the number of entries is. */
			if (o2 >= buf_size) return;
			o2 = datao + exif_get_long (buf + o2, n->order);
			break;

		default:
			exif_log (en->log, EXIF_LOG_CODE_DEBUG,
				"ExifMnoteDataOlympus", "Unknown version "
				"number %i.", n->version);
			return;
		}
	} else if (!memcmp (buf + o2, "\0\x1b", 2)) {
		n->version = nikonV2;
	} else {
		return;
	}

	/* Number of entries */
	if (o2 >= buf_size) return;
	c = exif_get_short (buf + o2, n->order);
	o2 += 2;

	/* Read the number of entries and remove old ones. */
	exif_mnote_data_olympus_clear (n);

	n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
	if (!n->entries) return;

	/* Parse the entries */
	for (i = 0; i < c; i++) {
	    o = o2 + 12 * i;
	    if (o + 12 > buf_size) return;

	    n->count = i + 1;
	    n->entries[i].tag        = exif_get_short (buf + o, n->order) + base;
	    n->entries[i].format     = exif_get_short (buf + o + 2, n->order);
	    n->entries[i].components = exif_get_long (buf + o + 4, n->order);
	    n->entries[i].order      = n->order;

	    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
		      "Loading entry 0x%x ('%s')...", n->entries[i].tag,
		      mnote_olympus_tag_get_name (n->entries[i].tag));

	    /*
	     * Size? If bigger than 4 bytes, the actual data is not
	     * in the entry but somewhere else (offset).
	     */
	    s = exif_format_get_size (n->entries[i].format) *
		   			 n->entries[i].components;
	    if (!s) continue;
	    o += 8;
	    if (s > 4) o = exif_get_long (buf + o, n->order) + datao;
	    if (o + s > buf_size) continue;

	    /* Sanity check */
	    n->entries[i].data = exif_mem_alloc (en->mem, s);
	    if (!n->entries[i].data) continue;
	    n->entries[i].size = s;
	    memcpy (n->entries[i].data, buf + o, s);
	}
}
static void
exif_mnote_data_pentax_load (ExifMnoteData *en,
		const unsigned char *buf, unsigned int buf_size)
{
	ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en;
	unsigned int i, o, s, datao = 6 + n->offset, base = 0;
	ExifShort c;

	/* Number of entries */
	if (buf_size < datao + (4 + 2) + 2) return;
	if (!memcmp(buf + datao, "AOC", 4)) {
		if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) {
			n->version = pentaxV3;
			n->order = EXIF_BYTE_ORDER_INTEL;
		} else if ((buf[datao + 4] == 'M') && (buf[datao + 5] == 'M')) {
			n->version = pentaxV3;
			n->order = EXIF_BYTE_ORDER_MOTOROLA;
		} else {
			/* Uses Casio v2 tags */
			n->version = pentaxV2;
		}
		datao += 4 + 2;
		base = MNOTE_PENTAX2_TAG_BASE;
	} if (!memcmp(buf + datao, "QVC", 4)) {
		n->version = casioV2;
		base = MNOTE_CASIO2_TAG_BASE;
		datao += 4 + 2;
	} else {
		n->version = pentaxV1;
	}
	c = exif_get_short (buf + datao, n->order);
	n->entries = (MnotePentaxEntry *)exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c);
	if (!n->entries) return;

	for (i = 0; i < c; i++) {
		o = datao + 2 + 12 * i;
		if (o + 8 > buf_size) return;

		n->count = i + 1;
		n->entries[i].tag        = exif_get_short (buf + o + 0, n->order) + base;
		n->entries[i].format     = exif_get_short (buf + o + 2, n->order);
		n->entries[i].components = exif_get_long  (buf + o + 4, n->order);
		n->entries[i].order      = n->order;

		/*
		 * Size? If bigger than 4 bytes, the actual data is not
		 * in the entry but somewhere else (offset).
		 */
		s = exif_format_get_size (n->entries[i].format) *
                                      n->entries[i].components;
		if (!s) return;
		o += 8;
		if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
		if (o + s > buf_size) return;
                                                                                
		/* Sanity check */
		n->entries[i].data = (unsigned char *)exif_mem_alloc (en->mem, s);
		if (!n->entries[i].data) return;
		n->entries[i].size = s;
		memcpy (n->entries[i].data, buf + o, s);
        }
}
/** 
 * @brief save the MnoteData from ne to buf
 * 
 * @param ne extract the data from this structure 
 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
 * @param buf_size the final size of the buffer
 */
static void
exif_mnote_data_pentax_save (ExifMnoteData *ne,
		unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) ne;
	size_t i,
	   base = 0,		/* internal MakerNote tag number offset */
	   o2 = 4 + 2;  	/* offset to first tag entry, past header */
        size_t datao = n->offset; /* this MakerNote style uses offsets
        			  based on main IFD, not makernote IFD */

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for header, the number of entries, entries,
	 * and next IFD pointer
	 */
	*buf_size = o2 + 2 + n->count * 12 + 4;
	switch (n->version) {
	case casioV2:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}
		/* Write the magic header */
		strcpy ((char *)*buf, "QVC");
		exif_set_short (*buf + 4, n->order, (ExifShort) 0);

		break;

	case pentaxV3:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}

		/* Write the magic header */
		strcpy ((char *)*buf, "AOC");
		exif_set_short (*buf + 4, n->order, (ExifShort) (
			(n->order == EXIF_BYTE_ORDER_INTEL) ?
			('I' << 8) | 'I' :
			('M' << 8) | 'M'));
		break;

	case pentaxV2:
		base = MNOTE_PENTAX2_TAG_BASE;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}

		/* Write the magic header */
		strcpy ((char *)*buf, "AOC");
		exif_set_short (*buf + 4, n->order, (ExifShort) 0);
		break;

	case pentaxV1:
		/* It looks like this format doesn't have a magic header as
		 * such, just has a fixed number of entries equal to 0x001b */
		*buf_size -= 6;
		o2 -= 6;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
			return;
		}
		break;

	default:
		/* internal error */
		return;
	}

	/* Write the number of entries. */
	exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
	o2 += 2;

	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		size_t doff;	/* offset to current data portion of tag */
		size_t s;
		unsigned char *t;
		size_t o = o2 + i * 12;   /* current offset into output buffer */
		exif_set_short (*buf + o + 0, n->order,
				(ExifShort) (n->entries[i].tag - base));
		exif_set_short (*buf + o + 2, n->order,
				(ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			size_t ts = *buf_size + s;
			doff = *buf_size;
			t = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * ts);
			if (!t) {
				EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts);
				return;
			}
			*buf = t;
			*buf_size = ts;
			exif_set_long (*buf + o, n->order, datao + doff);
		} else
			doff = o;

		/* Write the data. */
		if (n->entries[i].data) {
			memcpy (*buf + doff, n->entries[i].data, s);
		} else {
			/* Most certainly damaged input file */
			memset (*buf + doff, 0, s);
		}
	}

	/* Sanity check the buffer size */
	if (*buf_size < (o2 + n->count * 12 + 4)) {
		exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataPentax",
			"Buffer overflow");
	}

	/* Reset next IFD pointer */
	exif_set_long (*buf + o2 + n->count * 12, n->order, 0);
}
static void
exif_mnote_data_pentax_load (ExifMnoteData *en,
		const unsigned char *buf, unsigned int buf_size)
{
	ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en;
	size_t i, tcount, o, datao, base = 0;
	ExifShort c;

	if (!n || !buf || !buf_size) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifMnoteDataPentax", "Short MakerNote");
		return;
	}
	datao = 6 + n->offset;
	if ((datao + 8 < datao) || (datao + 8 < 8) || (datao + 8 > buf_size)) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifMnoteDataPentax", "Short MakerNote");
		return;
	}

	/* Detect variant of Pentax/Casio MakerNote found */
	if (!memcmp(buf + datao, "AOC", 4)) {
		if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) {
			n->version = pentaxV3;
			n->order = EXIF_BYTE_ORDER_INTEL;
		} else if ((buf[datao + 4] == 'M') && (buf[datao + 5] == 'M')) {
			n->version = pentaxV3;
			n->order = EXIF_BYTE_ORDER_MOTOROLA;
		} else {
			/* Uses Casio v2 tags */
			n->version = pentaxV2;
		}
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax",
			"Parsing Pentax maker note v%d...", (int)n->version);
		datao += 4 + 2;
		base = MNOTE_PENTAX2_TAG_BASE;
	} else if (!memcmp(buf + datao, "QVC", 4)) {
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax",
			"Parsing Casio maker note v2...");
		n->version = casioV2;
		base = MNOTE_CASIO2_TAG_BASE;
		datao += 4 + 2;
	} else {
		/* probably assert(!memcmp(buf + datao, "\x00\x1b", 2)) */
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataPentax",
			"Parsing Pentax maker note v1...");
		n->version = pentaxV1;
	}

	/* Read the number of tags */
	c = exif_get_short (buf + datao, n->order);
	datao += 2;

	/* Remove any old entries */
	exif_mnote_data_pentax_clear (n);

	/* Reserve enough space for all the possible MakerNote tags */
	n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c);
	if (!n->entries) {
		EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", sizeof (MnotePentaxEntry) * c);
		return;
	}

	/* Parse all c entries, storing ones that are successfully parsed */
	tcount = 0;
	for (i = c, o = datao; i; --i, o += 12) {
		size_t s;
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifMnoteDataPentax", "Short MakerNote");
			break;
		}

		n->entries[tcount].tag        = exif_get_short (buf + o + 0, n->order) + base;
		n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
		n->entries[tcount].components = exif_get_long  (buf + o + 4, n->order);
		n->entries[tcount].order      = n->order;

		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnotePentax",
			  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
			  mnote_pentax_tag_get_name (n->entries[tcount].tag));

		/*
		 * Size? If bigger than 4 bytes, the actual data is not
		 * in the entry but somewhere else (offset).
		 */
		s = exif_format_get_size (n->entries[tcount].format) *
                                      n->entries[tcount].components;
		n->entries[tcount].size = s;
		if (s) {
			size_t dataofs = o + 8;
			if (s > 4)
				/* The data in this case is merely a pointer */
			   	dataofs = exif_get_long (buf + dataofs, n->order) + 6;
			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
				(dataofs + s > buf_size)) {
				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
						  "ExifMnoteDataPentax", "Tag data past end "
					  "of buffer (%u > %u)", dataofs + s, buf_size);
				continue;
			}

			n->entries[tcount].data = exif_mem_alloc (en->mem, s);
			if (!n->entries[tcount].data) {
				EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", s);
				continue;
			}
			memcpy (n->entries[tcount].data, buf + dataofs, s);
		}

		/* Tag was successfully parsed */
		++tcount;
	}
	/* Store the count of successfully parsed tags */
	n->count = tcount;
}
Пример #16
0
void generateEncryptData(unsigned char **data, unsigned int *size, SGeoTagsEncrypt *collection, ExifByteOrder order)
{
	unsigned int i = 0;
	unsigned int s = 0;
	unsigned int next_data = 0;
	ExifEntry *entry = NULL;
	ExifContent *content = NULL;
	unsigned char *d = NULL, n;
	ExifData *exif = NULL;
	int size_sgeo_bytes = 0;
	ExifIfd ifd = EXIF_IFD_ENCRYPT;

	srand((unsigned int)time(NULL));

	*data = NULL;
	*size = 0;

	exif = exif_data_new_mem (exif_mem_new_default());
	exif->priv->order = order;
	content = exif->ifd[EXIF_IFD_ENCRYPT];

	// VersionID
	exif_mem_write(content, SGEO_TAG_ENCRYPT_VERSION, EXIF_FORMAT_BYTE, collection->VersionID, sizeof(collection->VersionID), NULL);
	// FileName
	write_unicode_string_to_exif(content, SGEO_TAG_ENCRYPT_FILE_NAME, collection->FileName);
	// FileSize
	exif_long_write(content, SGEO_TAG_ENCRYPT_FILE_SIZE, &collection->FileSize, order, NULL);
	// DateTimeOriginal
	exif_mem_write(content, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, collection->DateTimeOriginal, sizeof(collection->DateTimeOriginal), &collection->ExistDateTimeOriginal);
	// Longitude
	exif_srational_write(content, SGEO_TAG_LONGITUDE, &collection->Longitude, order, &collection->ExistLongitude);
	// LongAccuracy
	exif_rational_write(content, SGEO_TAG_LONGACCURACY, &collection->LongitudeAccuracy, order, &collection->ExistLongitudeAccuracy);
	// Latitude
	exif_srational_write(content, SGEO_TAG_LATITUDE, &collection->Latitude, order, &collection->ExistLatitude);
	// LatAccuracy
	exif_rational_write(content, SGEO_TAG_LATACCURACY, &collection->LatitudeAccuracy, order, &collection->ExistLatitudeAccuracy);
	// Altitude
	exif_srational_write(content, SGEO_TAG_ALTITUDE, &collection->Altitude, order, &collection->ExistAltitude);
	// AltAccuracy
	exif_rational_write(content, SGEO_TAG_ALTACCURACY, &collection->AltitudeAccuracy, order, &collection->ExistAltitudeAccuracy);
	// Azimuth
	exif_srational_write(content, SGEO_TAG_AZIMUTH, &collection->Azimuth, order, &collection->ExistAzimuth);
	// AzimuthAccuracy
	exif_rational_write(content, SGEO_TAG_AZIMUTHACCURACY, &collection->AzimuthAccuracy, order, &collection->ExistAzimuthAccuracy);
	// Pitch
	exif_srational_write(content, SGEO_TAG_PITCH, &collection->Pitch, order, &collection->ExistPitch);
	// PitchAccuracy
	exif_rational_write(content, SGEO_TAG_PITCHACCURACY, &collection->PitchAccuracy, order, &collection->ExistPitchAccuracy);
	// Roll
	exif_srational_write(content, SGEO_TAG_ROLL, &collection->Roll, order, &collection->ExistRoll);
	// RollAccuracy
	exif_rational_write(content, SGEO_TAG_ROLLACCURACY, &collection->RollAccuracy, order, &collection->ExistRollAccuracy);
	// HViewAngle
	exif_rational_write(content, SGEO_TAG_HVIEWANGLE, &collection->HViewAngle, order, &collection->ExistHViewAngle);
	// HViewAngleAccuracy
	exif_rational_write(content, SGEO_TAG_HVIEWANGLEACCURACY, &collection->HViewAngleAccuracy, order, &collection->ExistHViewAngleAccuracy);
	// VViewAngle
	exif_rational_write(content, SGEO_TAG_VVIEWANGLE, &collection->VViewAngle, order, &collection->ExistVViewAngle);
	// VViewAngleAccuracy
	exif_rational_write(content, SGEO_TAG_VVIEWANGLEACCURACY, &collection->VViewAngleAccuracy, order, &collection->ExistVViewAngleAccuracy);
	// SatCount
	exif_mem_write(content, SGEO_TAG_SATCOUNT, EXIF_FORMAT_BYTE, &collection->SatCount, sizeof(collection->SatCount), NULL);
	// global time
	exif_mem_write(content, SGEO_TAG_GLOBAL_TIME, EXIF_FORMAT_BYTE, collection->GlobalTime, sizeof(collection->GlobalTime), NULL);

	// GNSSType
	exif_long_write(content, SGEO_TAG_GNSS_TYPE, &collection->GNSSType, order, NULL);

	// DeviceName
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_NAME, collection->DeviceName);
	// DeviceIMEI
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_IMEI, collection->DeviceIMEI);
	// DeviceNumber
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_NUMBER, collection->DeviceNumber);
	// DeviceOS
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_OS, collection->DeviceOS);
	// DeviceOSVersion
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_OS_VERSION, collection->DeviceOSVersion);
	// DeviceVersion
	write_unicode_string_to_exif(content, SGEO_TAG_DEVICE_VERSION, collection->DeviceVersion);
	// DeviceDateTimeMeasure
	exif_mem_write(content, SGEO_TAG_DEVICE_DATE_TIME_MEASURE, EXIF_FORMAT_BYTE, collection->DeviceDateTimeMeasure, sizeof(collection->DeviceDateTimeMeasure), NULL);

	// ProgramVersion
	write_unicode_string_to_exif(content, SGEO_TAG_PROGRAM_VERSION, collection->ProgramVersion);
	// ProgramName
	write_unicode_string_to_exif(content, SGEO_TAG_PROGRAM_NAME, collection->ProgramName);
	// ProgramUserName
	write_unicode_string_to_exif(content, SGEO_TAG_PROGRAM_USER_NAME, collection->ProgramUserName);
	
	size_sgeo_bytes = 2 + content->count * 12;
	for (i = 0; i < content->count; i++)
	{
		entry = content->entries[i];
		if (entry != NULL)
		{
			s = exif_format_get_size(entry->format) * entry->components;
			if (s > 4)
				size_sgeo_bytes += s;
			//	s += 12;// +tag size
			//else
			//	s = 12;
		}
	}
	if (size_sgeo_bytes > 0)
	{
		*data = (unsigned char* )calloc((size_t)size_sgeo_bytes, 1);
		if (*data != NULL)
		{
			write_content_binary(*data, content, order, 0);
			s = 0;
			if (size_sgeo_bytes < 1024)
				s = 1024 - size_sgeo_bytes;
			s += 2390;// white noice
			*size = size_sgeo_bytes + s;
			*data = (unsigned char* )realloc(*data, (size_t)(size_sgeo_bytes + s));
			n = rand() % 255;
			for (i = 0; i < s; i++)
			{
				n = GaloisLfsr(n);
				(*data)[size_sgeo_bytes + i] = n;
			}
		}
	}
	exif_data_unref(exif);
}
static void
exif_mnote_data_canon_save (ExifMnoteData *ne,
                            unsigned char **buf, unsigned int *buf_size)
{
    ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
    size_t i, o, s, doff;
    unsigned char *t;
    size_t ts;

    if (!n || !buf || !buf_size) return;

    /*
     * Allocate enough memory for all entries and the number
     * of entries.
     */
    *buf_size = 2 + n->count * 12 + 4;
    *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
    if (!*buf) {
        EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size);
        return;
    }

    /* Save the number of entries */
    exif_set_short (*buf, n->order, (ExifShort) n->count);

    /* Save each entry */
    for (i = 0; i < n->count; i++) {
        o = 2 + i * 12;
        exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
        exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
        exif_set_long  (*buf + o + 4, n->order,
                        n->entries[i].components);
        o += 8;
        s = exif_format_get_size (n->entries[i].format) *
            n->entries[i].components;
        if (s > 65536) {
            /* Corrupt data: EXIF data size is limited to the
             * maximum size of a JPEG segment (64 kb).
             */
            continue;
        }
        if (s > 4) {
            ts = *buf_size + s;

            /* Ensure even offsets. Set padding bytes to 0. */
            if (s & 1) ts += 1;
            t = exif_mem_realloc (ne->mem, *buf,
                                  sizeof (char) * ts);
            if (!t) {
                EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts);
                return;
            }
            *buf = t;
            *buf_size = ts;
            doff = *buf_size - s;
            if (s & 1) {
                doff--;
                *(*buf + *buf_size - 1) = '\0';
            }
            exif_set_long (*buf + o, n->order, n->offset + doff);
        } else
            doff = o;

        /*
         * Write the data. Fill unneeded bytes with 0. Do not
         * crash if data is NULL.
         */
        if (!n->entries[i].data) memset (*buf + doff, 0, s);
        else memcpy (*buf + doff, n->entries[i].data, s);
        if (s < 4) memset (*buf + doff + s, 0, (4 - s));
    }
}
Пример #18
0
static void
exif_mnote_data_olympus_load (ExifMnoteData *en,
			      const unsigned char *buf, unsigned int buf_size)
{
	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
	ExifShort c;
	size_t i, tcount, o, o2, datao = 6, base = 0;

	if (!n || !buf || !buf_size) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifMnoteDataOlympus", "Short MakerNote");
		return;
	}
	o2 = 6 + n->offset; /* Start of interesting data */
	if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifMnoteDataOlympus", "Short MakerNote");
		return;
	}

	/*
	 * Olympus headers start with "OLYMP" and need to have at least
	 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
	 * number of entries, and 12 for one entry.
	 *
	 * Sanyo format is identical and uses identical tags except that
	 * header starts with "SANYO".
	 *
	 * Epson format is identical and uses identical tags except that
	 * header starts with "EPSON".
	 *
	 * Nikon headers start with "Nikon" (6 bytes including '\0'), 
	 * version number (1 or 2).
	 * 
	 * Version 1 continues with 0, 1, 0, number_of_tags,
	 * or just with number_of_tags (models D1H, D1X...).
	 * 
	 * Version 2 continues with an unknown byte (0 or 10),
	 * two unknown bytes (0), "MM" or "II", another byte 0 and 
	 * lastly 0x2A.
	 */
	if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6) ||
	    !memcmp (buf + o2, "EPSON", 6)) {
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Olympus/Sanyo/Epson maker note v1...");

		/* The number of entries is at position 8. */
		if (!memcmp (buf + o2, "SANYO", 6))
			n->version = sanyoV1;
		else if (!memcmp (buf + o2, "EPSON", 6))
			n->version = epsonV1;
		else
			n->version = olympusV1;
		if (buf[o2 + 6] == 1)
			n->order = EXIF_BYTE_ORDER_INTEL;
		else if (buf[o2 + 6 + 1] == 1)
			n->order = EXIF_BYTE_ORDER_MOTOROLA;
		o2 += 8;
		if (o2 + 2 > buf_size) return;
		c = exif_get_short (buf + o2, n->order);
		if ((!(c & 0xFF)) && (c > 0x500)) {
			if (n->order == EXIF_BYTE_ORDER_INTEL) {
				n->order = EXIF_BYTE_ORDER_MOTOROLA;
			} else {
				n->order = EXIF_BYTE_ORDER_INTEL;
			}
		}

	} else if (!memcmp (buf + o2, "OLYMPUS", 8)) {
		/* Olympus S760, S770 */
		datao = o2;
		o2 += 8;
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
			buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);

		if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
			n->order = EXIF_BYTE_ORDER_INTEL;
		else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
			n->order = EXIF_BYTE_ORDER_MOTOROLA;

		/* The number of entries is at position 8+4. */
		n->version = olympusV2;
		o2 += 4;

	} else if (!memcmp (buf + o2, "Nikon", 6)) {
		o2 += 6;
		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
			"Parsing Nikon maker note (0x%02x, %02x, %02x, "
			"%02x, %02x, %02x, %02x, %02x)...",
			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], 
			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
		/* The first byte is the version. */
		if (o2 >= buf_size) return;
		n->version = buf[o2];
		o2 += 1;

		/* Skip an unknown byte (00 or 0A). */
		o2 += 1;

		switch (n->version) {
		case nikonV1:

			base = MNOTE_NIKON1_TAG_BASE;
			/* Fix endianness, if needed */
			if (o2 + 2 > buf_size) return;
			c = exif_get_short (buf + o2, n->order);
			if ((!(c & 0xFF)) && (c > 0x500)) {
				if (n->order == EXIF_BYTE_ORDER_INTEL) {
					n->order = EXIF_BYTE_ORDER_MOTOROLA;
				} else {
					n->order = EXIF_BYTE_ORDER_INTEL;
				}
			}
			break;

		case nikonV2:

			/* Skip 2 unknown bytes (00 00). */
			o2 += 2;

			/*
			 * Byte order. From here the data offset
			 * gets calculated.
			 */
			datao = o2;
			if (o2 >= buf_size) return;
			if (!strncmp ((char *)&buf[o2], "II", 2))
				n->order = EXIF_BYTE_ORDER_INTEL;
			else if (!strncmp ((char *)&buf[o2], "MM", 2))
				n->order = EXIF_BYTE_ORDER_MOTOROLA;
			else {
				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
					"ExifMnoteDatalympus", "Unknown "
					"byte order '%c%c'", buf[o2],
					buf[o2 + 1]);
				return;
			}
			o2 += 2;

			/* Skip 2 unknown bytes (00 2A). */
			o2 += 2;

			/* Go to where the number of entries is. */
			if (o2 + 4 > buf_size) return;
			o2 = datao + exif_get_long (buf + o2, n->order);
			break;

		default:
			exif_log (en->log, EXIF_LOG_CODE_DEBUG,
				"ExifMnoteDataOlympus", "Unknown version "
				"number %i.", n->version);
			return;
		}
	} else if (!memcmp (buf + o2, "\0\x1b", 2)) {
		n->version = nikonV2;
		/* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
		n->order = EXIF_BYTE_ORDER_MOTOROLA;
	} else {
		return;
	}

	/* Sanity check the offset */
	if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
			  "ExifMnoteOlympus", "Short MakerNote");
		return;
	}

	/* Read the number of tags */
	c = exif_get_short (buf + o2, n->order);
	o2 += 2;

	/* Remove any old entries */
	exif_mnote_data_olympus_clear (n);

	/* Reserve enough space for all the possible MakerNote tags */
	n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
	if (!n->entries) {
		EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
		return;
	}

	/* Parse all c entries, storing ones that are successfully parsed */
	tcount = 0;
	for (i = c, o = o2; i; --i, o += 12) {
		size_t s;
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifMnoteOlympus", "Short MakerNote");
			break;
		}

	    n->entries[tcount].tag        = exif_get_short (buf + o, n->order) + base;
	    n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
	    n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
	    n->entries[tcount].order      = n->order;

	    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
		      "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
		      mnote_olympus_tag_get_name (n->entries[tcount].tag));
/*	    exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
			    "0x%x %d %ld*(%d)",
		    n->entries[tcount].tag,
		    n->entries[tcount].format,
		    n->entries[tcount].components,
		    (int)exif_format_get_size(n->entries[tcount].format)); */

	    /*
	     * Size? If bigger than 4 bytes, the actual data is not
	     * in the entry but somewhere else (offset).
	     */
	    s = exif_format_get_size (n->entries[tcount].format) *
		   			 n->entries[tcount].components;
		n->entries[tcount].size = s;
		if (s) {
			size_t dataofs = o + 8;
			if (s > 4) {
				/* The data in this case is merely a pointer */
				dataofs = exif_get_long (buf + dataofs, n->order) + datao;
#ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
				/* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
				 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
				 * tag in its MakerNote. The offset is actually the absolute
				 * position in the file instead of the position within the IFD.
				 */
			    if (dataofs + s > buf_size && n->version == sanyoV1) {
					/* fix pointer */
					dataofs -= datao + 6;
					exif_log (en->log, EXIF_LOG_CODE_DEBUG,
						  "ExifMnoteOlympus",
						  "Inconsistent thumbnail tag offset; attempting to recover");
			    }
#endif
			}
			if ((dataofs + s < dataofs) || (dataofs + s < s) || 
			    (dataofs + s > buf_size)) {
				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
					  "ExifMnoteOlympus",
					  "Tag data past end of buffer (%u > %u)",
					  dataofs + s, buf_size);
				continue;
			}

			n->entries[tcount].data = exif_mem_alloc (en->mem, s);
			if (!n->entries[tcount].data) {
				EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
				continue;
			}
			memcpy (n->entries[tcount].data, buf + dataofs, s);
		}

		/* Tag was successfully parsed */
		++tcount;
	}
	/* Store the count of successfully parsed tags */
	n->count = tcount;
}
static void
exif_mnote_data_canon_load (ExifMnoteData *ne,
                            const unsigned char *buf, unsigned int buf_size)
{
    ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
    ExifShort c;
    size_t i, tcount, o, datao;

    if (!n || !buf || !buf_size) {
        exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
                  "ExifMnoteCanon", "Short MakerNote");
        return;
    }
    datao = 6 + n->offset;
    if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
        exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
                  "ExifMnoteCanon", "Short MakerNote");
        return;
    }

    /* Read the number of tags */
    c = exif_get_short (buf + datao, n->order);
    datao += 2;

    /* Remove any old entries */
    exif_mnote_data_canon_clear (n);

    /* Reserve enough space for all the possible MakerNote tags */
    n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c);
    if (!n->entries) {
        EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c);
        return;
    }

    /* Parse the entries */
    tcount = 0;
    for (i = c, o = datao; i; --i, o += 12) {
        size_t s;
        if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
            exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
                      "ExifMnoteCanon", "Short MakerNote");
            break;
        }

        n->entries[tcount].tag        = exif_get_short (buf + o, n->order);
        n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
        n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
        n->entries[tcount].order      = n->order;

        exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon",
                  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
                  mnote_canon_tag_get_name (n->entries[tcount].tag));

        /*
         * Size? If bigger than 4 bytes, the actual data is not
         * in the entry but somewhere else (offset).
         */
        s = exif_format_get_size (n->entries[tcount].format) *
            n->entries[tcount].components;
        n->entries[tcount].size = s;
        if (!s) {
            exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
                      "ExifMnoteCanon",
                      "Invalid zero-length tag size");
            continue;

        } else {
            size_t dataofs = o + 8;
            if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6;
            if ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) {
                exif_log (ne->log, EXIF_LOG_CODE_DEBUG,
                          "ExifMnoteCanon",
                          "Tag data past end of buffer (%u > %u)",
                          dataofs + s, buf_size);
                continue;
            }

            n->entries[tcount].data = exif_mem_alloc (ne->mem, s);
            if (!n->entries[tcount].data) {
                EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s);
                continue;
            }
            memcpy (n->entries[tcount].data, buf + dataofs, s);
        }

        /* Tag was successfully parsed */
        ++tcount;
    }
    /* Store the count of successfully parsed tags */
    n->count = tcount;
}
Пример #20
0
void imFileFormatJPEG::iReadExifAttrib(unsigned char* data, int data_length, imAttribTable* attrib_table)
{
  ExifData* exif = exif_data_new_from_data(data, data_length);
  if (!exif)
    return;

  void* value = NULL;
  int c, value_size = 0;

  ExifByteOrder byte_order = exif_data_get_byte_order(exif);

  for (int ifd = 0; ifd < EXIF_IFD_COUNT; ifd++)
  {
    if (ifd == EXIF_IFD_1 || ifd == EXIF_IFD_INTEROPERABILITY) // Skip thumbnail and interoperability
      continue;

    ExifContent *content = exif->ifd[ifd];

    if (content && content->count) 
    {
      for (int j = 0; j < (int)content->count; j++) 
      {
        ExifEntry *entry = content->entries[j];
        int type = 0;

        const char* name = exif_tag_get_name_in_ifd(entry->tag, (ExifIfd)ifd);
        if (!name)
          continue;

        if (value_size < (int)entry->size)
        {
          value = realloc(value, entry->size);
          value_size = entry->size;
        }

        int format_size = exif_format_get_size(entry->format);

        if (entry->tag == EXIF_TAG_RESOLUTION_UNIT)
        {
          int res_unit = (int)exif_get_short (entry->data, byte_order);

          if (res_unit == 2)
            attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPI");
          else if (res_unit == 3)
            attrib_table->Set("ResolutionUnit", IM_BYTE, -1, "DPC");

          continue;
        }

        switch (entry->format) 
        {
        case EXIF_FORMAT_UNDEFINED:
        case EXIF_FORMAT_ASCII:
        case EXIF_FORMAT_SBYTE:
        case EXIF_FORMAT_BYTE:
          {
            type = IM_BYTE;
            imbyte *bvalue = (imbyte*)value;
            for (c = 0; c < (int)entry->components; c++) 
              bvalue[c] = entry->data[c];
          }
          break;
        case EXIF_FORMAT_SSHORT:
          {
            type = IM_SHORT;
            short *svalue = (short*)value;
            for (c = 0; c < (int)entry->components; c++) 
              svalue[c] = exif_get_short(entry->data + format_size * c, byte_order);
          }
          break;
        case EXIF_FORMAT_SHORT:
          {
            type = IM_USHORT;
            imushort *usvalue = (imushort*)value;
            for (c = 0; c < (int)entry->components; c++) 
              usvalue[c] = exif_get_short(entry->data + format_size * c, byte_order);
          }
          break;
        case EXIF_FORMAT_LONG:
          {
            type = IM_INT;
            int *ivalue = (int*)value;
            for (c = 0; c < (int)entry->components; c++) 
              ivalue[c] = (int)exif_get_long(entry->data + format_size * c, byte_order);
          }
          break;
        case EXIF_FORMAT_SLONG:
          {
            type = IM_INT;
            int *ivalue = (int*)value;
            for (c = 0; c < (int)entry->components; c++) 
              ivalue[c] = (int)exif_get_slong(entry->data + format_size * c, byte_order);
          }
          break;
        case EXIF_FORMAT_RATIONAL:
          {
            ExifRational v_rat;
            type = IM_FLOAT;
            float *fvalue = (float*)value;
            for (c = 0; c < (int)entry->components; c++) 
            {
              v_rat = exif_get_rational(entry->data + format_size * c, byte_order);
              fvalue[c] = (float)v_rat.numerator / (float)v_rat.denominator;
            }
          }
          break;
        case EXIF_FORMAT_SRATIONAL:
          {
            ExifSRational v_srat;
            type = IM_FLOAT;
            float *fvalue = (float*)value;
            for (c = 0; c < (int)entry->components; c++) 
            {
              v_srat = exif_get_srational(entry->data + format_size * c, byte_order);
              fvalue[c] = (float)v_srat.numerator / (float)v_srat.denominator;
            }
          }
          break;
        case EXIF_FORMAT_FLOAT:  // defined but unsupported in libEXIF
        case EXIF_FORMAT_DOUBLE: // defined but unsupported in libEXIF
          break;
        }

        attrib_table->Set(name, type, entry->components, value);
      }
    }
  }

  if (value) free(value);

  exif_data_free(exif);
}
Пример #21
0
LocImageContainer ImageProcessor::process (QString filename)
{
	QImage image (m_data);

	if (!image.isNull()) {
		image = image.scaled(720, 500, Qt::KeepAspectRatioByExpanding);
	}

	LocImageContainer locImageContainer(image);

	locImageContainer.setAltitude(3000.00);

	//get exif data
	ExifData *ed = exif_data_new_from_file (filename.toLocal8Bit().constData());

	if (!ed) {
		locImageContainer.setLocationAvailable(false);
		locImageContainer.setExifDataAvailable(false);

		return locImageContainer;
	}

	locImageContainer.setExifDataAvailable(true);

	//save temp
	char value[256]={0,};

	// Retrieve make
	QString make;
	ExifEntry *ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
	if (!ee) {
		make = "";
	} else {
		exif_entry_get_value(ee, value, sizeof(value));
		locImageContainer.setMake (QString(value));
	}

	// Retrieve model
	ee = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
	if (!ee) {
		locImageContainer.setCameraModel ("");
	} else {
		exif_entry_get_value(ee, value, sizeof(value));
		locImageContainer.setCameraModel ("Taken with the "+QString(value));
	}

	// Retrieve time
	ee = exif_content_get_entry(ed->ifd[EXIF_IFD_EXIF], EXIF_TAG_DATE_TIME_ORIGINAL);
	if (!ee) {
		locImageContainer.setDateTaken ("");
	} else {
		exif_entry_get_value(ee, value, sizeof(value));
		QString dateTime(value);

		QDateTime dateTaken = QDateTime::fromString (dateTime, "yyyy:MM:dd HH:mm:ss");
		locImageContainer.setDateTaken (dateTaken.toString("'on 'dddd d, MMMM yyyy 'at' HH:mm"));
	}

	// Retrieve LATITUDE
	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE);
	if (!ee) {
		locImageContainer.setLocationAvailable(false);
		locImageContainer.setLatitude(-9999.99);
	} else {
		if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		{
			double lat = Rational2Double ( ee->data,
					exif_format_get_size(ee->format),
					exif_data_get_byte_order(ed) );

			ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LATITUDE_REF);
			if ( ee ) {
				exif_entry_get_value ( ee, value, 128 );
				if ( value[0] == 'S' )
					lat = -lat;
			}

			locImageContainer.setLocationAvailable(true);
			locImageContainer.setLatitude (lat);
		}
	}

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE);
	if (!ee) {
		locImageContainer.setLocationAvailable(false);
		locImageContainer.setLongitude(-9999.99);
	} else {
		if ( ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		{
			double lon = Rational2Double ( ee->data,
					exif_format_get_size(ee->format),
					exif_data_get_byte_order(ed) );

			ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], (ExifTag)EXIF_TAG_GPS_LONGITUDE_REF);
			if ( ee ) {
				exif_entry_get_value ( ee, value, 128 );
				if ( value[0] == 'W' )
					lon = -lon;
			}

			locImageContainer.setLocationAvailable(true);
			locImageContainer.setLongitude (lon);
		}
	}

	exif_data_free(ed);

	return locImageContainer;
}
Пример #22
0
static const char *
eog_exif_entry_get_value (ExifEntry    *e,
			  char         *buf,
			  guint         n_buf)
{
	ExifByteOrder bo;

	/* For now we only want to reformat some GPS values */
	if (G_LIKELY (exif_entry_get_ifd (e) != EXIF_IFD_GPS))
		return exif_entry_get_value (e, buf, n_buf);

	bo = exif_data_get_byte_order (e->parent->parent);

	/* Cast to number to avoid warnings about values not in enumeration */
	switch ((guint16) e->tag) {
		case EXIF_TAG_GPS_LATITUDE:
		case EXIF_TAG_GPS_LONGITUDE:
		{
			gsize rational_size;
			ExifRational r;
			gfloat h = 0., m = 0.;


			rational_size = exif_format_get_size (EXIF_FORMAT_RATIONAL);
			if (G_UNLIKELY (e->components != 3 ||
			    e->format != EXIF_FORMAT_RATIONAL))
				return exif_entry_get_value (e, buf, n_buf);

			r = exif_get_rational (e->data, bo);
			if (r.denominator != 0)
				h = (gfloat)r.numerator / r.denominator;

			r = exif_get_rational (e->data + rational_size, bo);
			if (r.denominator != 0)
				m = (gfloat)r.numerator / (gfloat)r.denominator;

			r = exif_get_rational (e->data + (2 * rational_size),
					       bo);
			if (r.numerator != 0 && r.denominator != 0) {
				gfloat s;

				s = (gfloat)r.numerator / (gfloat)r.denominator;
				g_snprintf (buf, n_buf,
					    "%.0f° %.0f' %.2f\"",
					    h, m, s);
			} else {
				g_snprintf (buf, n_buf,
					    "%.0f° %.2f'",
					    h, m);
			}

			break;
		}
		case EXIF_TAG_GPS_LATITUDE_REF:
		case EXIF_TAG_GPS_LONGITUDE_REF:
		{
			if (G_UNLIKELY (e->components != 2 ||
			    e->format != EXIF_FORMAT_ASCII))
				return exif_entry_get_value (e, buf, n_buf);

			switch (e->data[0]) {
			case 'N':
				g_snprintf (buf, n_buf, "%s", _("North"));
				break;
			case 'E':
				g_snprintf (buf, n_buf, "%s", _("East"));
				break;
			case 'W':
				g_snprintf (buf, n_buf, "%s", _("West"));
				break;
			case 'S':
				g_snprintf (buf, n_buf, "%s", _("South"));
				break;
			default:
				return exif_entry_get_value (e, buf, n_buf);
				break;
			}
			break;
		}
		default:
			return exif_entry_get_value (e, buf, n_buf);
			break;
	}

	return buf;
}
Пример #23
0
static void
metadatamux_exif_for_each_tag_in_list (const GstTagList * list,
    const gchar * tag, gpointer user_data)
{
  ExifData *ed = (ExifData *) user_data;
  ExifTag exif_tag;
  GType type = G_TYPE_INVALID;
  ExifEntry *entry = NULL;
  ExifIfd ifd = EXIF_IFD_COUNT;
  const ExifByteOrder byte_order = exif_data_get_byte_order (ed);

  exif_tag = metadatamux_exif_get_exif_from_tag (tag, &type, &ifd);

  if (!exif_tag)
    goto done;

  entry = exif_data_get_entry (ed, exif_tag);

  if (entry)
    exif_entry_ref (entry);
  else {
    entry = exif_entry_new ();
    exif_content_add_entry (ed->ifd[ifd], entry);
    exif_entry_initialize (entry, exif_tag);
  }

  if (entry->data == NULL) {
    if (entry->tag == EXIF_TAG_GPS_ALTITUDE) {
      entry->format = EXIF_FORMAT_RATIONAL;
      entry->components = 1;
      entry->size = exif_format_get_size (entry->format) * entry->components;
      entry->data = g_malloc (entry->size);
    } else if (entry->tag == EXIF_TAG_GPS_LATITUDE
        || entry->tag == EXIF_TAG_GPS_LONGITUDE) {
      entry->format = EXIF_FORMAT_RATIONAL;
      entry->components = 3;
      entry->size = exif_format_get_size (entry->format) * entry->components;
      entry->data = g_malloc (entry->size);
    }
  }

  if (type == GST_TYPE_FRACTION) {
    const GValue *gvalue = gst_tag_list_get_value_index (list, tag, 0);
    gint numerator = gst_value_get_fraction_numerator (gvalue);
    gint denominator = gst_value_get_fraction_denominator (gvalue);

    switch (entry->format) {
      case EXIF_FORMAT_SRATIONAL:
      {
        ExifSRational sr = { numerator, denominator };

        exif_set_srational (entry->data, byte_order, sr);
      }
        break;
      case EXIF_FORMAT_RATIONAL:
      {
        ExifRational r;

        if (entry->tag == EXIF_TAG_X_RESOLUTION ||
            entry->tag == EXIF_TAG_Y_RESOLUTION) {
          ExifEntry *unit_entry = NULL;

          unit_entry = exif_data_get_entry (ed, EXIF_TAG_RESOLUTION_UNIT);

          if (unit_entry) {
            ExifShort vsh = exif_get_short (unit_entry->data, byte_order);

            if (vsh != 2)       /* inches */
              exif_set_short (unit_entry->data, byte_order, 2);
          }
        }
        r.numerator = numerator;
        r.denominator = denominator;
        if (numerator < 0)
          r.numerator = -numerator;
        if (denominator < 0)
          r.denominator = -denominator;
        exif_set_rational (entry->data, byte_order, r);
      }
        break;
      default:
        break;
    }
  } else if (type == GST_TYPE_BUFFER) {
    const GValue *val = NULL;
    GstBuffer *buf;

    val = gst_tag_list_get_value_index (list, tag, 0);
    buf = gst_value_get_buffer (val);
    entry->components = GST_BUFFER_SIZE (buf);
    entry->size = GST_BUFFER_SIZE (buf);
    entry->data = g_malloc (entry->size);
    memcpy (entry->data, GST_BUFFER_DATA (buf), entry->size);
  } else {
    switch (type) {
      case G_TYPE_STRING:
      {
        gchar *value = NULL;

        if (gst_tag_list_get_string (list, tag, &value)) {
          if (entry->tag == EXIF_TAG_DATE_TIME_DIGITIZED
              || entry->tag == EXIF_TAG_DATE_TIME
              || entry->tag == EXIF_TAG_DATE_TIME_ORIGINAL) {
            GString *datetime = g_string_new_len (value,
                20);            /* enough memory to hold "YYYY:MM:DD HH:MM:SS" */

            if (metadatamux_exif_convert_from_datetime (datetime)) {
            } else {
              GST_ERROR ("Unexpected date & time format for %s", tag);
            }
            g_free (value);
            value = datetime->str;
            g_string_free (datetime, FALSE);
          } else if (value) {
            entry->components = strlen (value) + 1;
            entry->size =
                exif_format_get_size (entry->format) * entry->components;
            entry->data = (guint8 *) value;
            value = NULL;
          }
        }
      }
        break;
      case G_TYPE_UINT:
      case G_TYPE_INT:
      {
        gint value;
        ExifShort v_short;

        if (G_TYPE_UINT == type) {
          gst_tag_list_get_uint (list, tag, (guint *) & value);
        } else {
          gst_tag_list_get_int (list, tag, &value);
        }

        switch (entry->format) {
          case EXIF_FORMAT_SHORT:
            if (entry->tag == EXIF_TAG_CONTRAST
                || entry->tag == EXIF_TAG_SATURATION) {
              if (value < -33)
                value = 1;      /* low */
              else if (value < 34)
                value = 0;      /* normal */
              else
                value = 2;      /* high */
            }
            v_short = value;
            exif_set_short (entry->data, byte_order, v_short);
            break;
          case EXIF_FORMAT_LONG:
            exif_set_long (entry->data, byte_order, value);
            break;
          default:
            break;
        }

      }
        break;
      case G_TYPE_DOUBLE:
      {
        gdouble value;

        gst_tag_list_get_double (list, tag, &value);
        if (entry->tag == EXIF_TAG_GPS_LATITUDE
            || entry->tag == EXIF_TAG_GPS_LONGITUDE) {
          ExifRational *rt = (ExifRational *) entry->data;
          gdouble v = fabs (value);
          ExifEntry *ref_entry = NULL;
          char ref;
          const ExifTag ref_tag = entry->tag == EXIF_TAG_GPS_LATITUDE ?
              EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF;

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

          /* MM - minutes */
          rt->numerator = (gulong) (v * 60.0);
          rt->denominator = 1;
          GST_DEBUG ("min: %lf : %lu / %lu", v, (gulong) rt->numerator,
              (gulong) rt->denominator);
          v -= ((gdouble) rt->numerator / 60.0);
          rt++;

          /* SS - seconds */
          rt->numerator = (gulong) (0.5 + v * 3600.0);
          rt->denominator = 1;
          GST_DEBUG ("sec: %lf : %lu / %lu", v, (gulong) rt->numerator,
              (gulong) rt->denominator);

          if (entry->tag == EXIF_TAG_GPS_LONGITUDE) {
            GST_DEBUG ("longitude : %lf", value);
            ref = (value < 0.0) ? 'W' : 'E';
          } else {
            GST_DEBUG ("latitude : %lf", value);
            ref = (value < 0.0) ? 'S' : 'N';
          }

          ref_entry = exif_data_get_entry (ed, ref_tag);
          if (ref_entry) {
            exif_entry_ref (ref_entry);
          } else {
            ref_entry = exif_entry_new ();
            exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry);
            exif_entry_initialize (ref_entry, ref_tag);
          }
          if (ref_entry->data == NULL) {
            ref_entry->format = EXIF_FORMAT_ASCII;
            ref_entry->components = 2;
            ref_entry->size = 2;
            ref_entry->data = g_malloc (2);
          }
          ref_entry->data[0] = ref;
          ref_entry->data[1] = 0;
          exif_entry_unref (ref_entry);
        } else if (entry->tag == EXIF_TAG_GPS_ALTITUDE) {
          ExifEntry *ref_entry = NULL;
          ExifRational *rt = (ExifRational *) entry->data;

          rt->numerator = (gulong) fabs (10.0 * value);
          rt->denominator = 10;

          GST_DEBUG ("altitude : %lf", value);

          ref_entry = exif_data_get_entry (ed, EXIF_TAG_GPS_ALTITUDE_REF);
          if (ref_entry) {
            exif_entry_ref (ref_entry);
          } else {
            ref_entry = exif_entry_new ();
            exif_content_add_entry (ed->ifd[EXIF_IFD_GPS], ref_entry);
            exif_entry_initialize (ref_entry, EXIF_TAG_GPS_ALTITUDE_REF);
          }
          if (ref_entry->data == NULL) {
            ref_entry->format = EXIF_FORMAT_BYTE;
            ref_entry->components = 1;
            ref_entry->size = 1;
            ref_entry->data = g_malloc (1);
          }
          if (value > 0.0) {
            ref_entry->data[0] = 0;
          } else {
            ref_entry->data[0] = 1;
          }
          exif_entry_unref (ref_entry);
        }
      }
        break;
      default:
        break;
    }
  }

done:

  if (entry)
    exif_entry_unref (entry);

}
Пример #24
0
/**
 * a_geotag_create_waypoint_from_file:
 * @filename: The image file to process
 * @vcmode:   The current location mode to use in the positioning of Waypoint
 * @name:     Returns a name for the Waypoint (can be NULL)
 *
 * Returns: An allocated Waypoint or NULL if Waypoint could not be generated (e.g. no EXIF info)
 *
 */
VikWaypoint* a_geotag_create_waypoint_from_file ( const gchar *filename, VikCoordMode vcmode, gchar **name )
{
	// Default return values (for failures)
	*name = NULL;
	VikWaypoint *wp = NULL;

	// TODO use log?
	//ExifLog *log = NULL;

	// open image with libexif
	ExifData *ed = exif_data_new_from_file ( filename );

	// Detect EXIF load failure
	if ( !ed )
		// return with no Waypoint
		return wp;

	struct LatLon ll;

	gchar str[128];
	ExifEntry *ee;

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_VERSION_ID);
	// Confirm this has a GPS Id - normally "2.0.0.0" or "2.2.0.0"
	if ( ! ( ee && ee->components == 4 ) )
		goto MyReturn;
	// Could test for these versions explicitly but may have byte order issues...
	//if ( ! ( ee->data[0] == 2 && ee->data[2] == 0 && ee->data[3] == 0 ) )
	//	goto MyReturn;


	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_MAP_DATUM);
	if ( ! ( ee && ee->components > 0 && ee->format == EXIF_FORMAT_ASCII ) )
		goto MyReturn;

	// If map datum specified - only deal in WGS-84 - the defacto standard
	if ( ee && ee->components > 0 ) {
		exif_entry_get_value ( ee, str, 128 );
		if ( strncmp (str, "WGS-84", 6) )
			goto MyReturn;
	}

	//
	// Lat & Long is necessary to form a waypoint.
	//
	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE);
	if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		goto MyReturn;
  
	ll.lat = Rational2Double ( ee->data,
							   exif_format_get_size(ee->format),
							   exif_data_get_byte_order(ed) );

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LATITUDE_REF);
	if ( ee ) {
		exif_entry_get_value ( ee, str, 128 );
		if ( str[0] == 'S' )
			ll.lat = -ll.lat;
	}

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE);
	if ( ! ( ee && ee->components == 3 && ee->format == EXIF_FORMAT_RATIONAL ) )
		goto MyReturn;

	ll.lon = Rational2Double ( ee->data,
							   exif_format_get_size(ee->format),
							   exif_data_get_byte_order(ed) );

	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_LONGITUDE_REF);
	if ( ee ) {
		exif_entry_get_value ( ee, str, 128 );
		if ( str[0] == 'W' )
			ll.lon = -ll.lon;
	}

	//
	// Not worried if none of the other fields exist, as can default the values to something
	//

	gdouble alt = VIK_DEFAULT_ALTITUDE;
	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE);
	if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_RATIONAL ) {
		alt = Rational2Double ( ee->data,
								0,
								exif_data_get_byte_order(ed) );

		ee = exif_content_get_entry (ed->ifd[EXIF_IFD_GPS], EXIF_TAG_GPS_ALTITUDE_REF);
		if ( ee && ee->components == 1 && ee->format == EXIF_FORMAT_BYTE && ee->data[0] == 1 )
			alt = -alt;
	}

	// Name
	ee = exif_content_get_entry (ed->ifd[EXIF_IFD_0], EXIF_TAG_XP_TITLE);
	if ( ee ) {
		exif_entry_get_value ( ee, str, 128 );
		*name = g_strdup ( str );
	}

	//
	// Now create Waypoint with acquired information
	//
	wp = vik_waypoint_new();
	wp->visible = TRUE;
	// Set info from exif values
	// Location
	vik_coord_load_from_latlon ( &(wp->coord), vcmode, &ll );
	// Altitude
	wp->altitude = alt;

	wp->comment = geotag_get_exif_comment ( ed );

	vik_waypoint_set_image ( wp, filename );

MyReturn:
	// Finished with EXIF
	exif_data_free ( ed );

	return wp;
}
Пример #25
0
static int iExifWriteTag(ExifData* exif, int index, const char* name, int data_type, int attrib_count, const void* attrib_data)
{
  int c;

  ExifTag tag = exif_tag_from_name(name);
  if (tag == 0)
  {
    if (!imStrEqual(name, "GPSVersionID"))  // EXIF_TAG_GPS_VERSION_ID==0
      return 1;
  }

  ExifEntry *entry = exif_entry_new();
  ExifByteOrder byte_order = exif_data_get_byte_order(exif);

  ExifContent *content;
  if (name[0] == 'G' && name[1] == 'P' && name[2] == 'S')
  {
    content = exif->ifd[EXIF_IFD_GPS];      // GPS tags

    if (!iExifGetGPSTagInfo((int)tag, &(entry->format), &(entry->components)))
    {
      exif_entry_free(entry);
      return 1;
    }

  }
  else 
  {
    if (tag > EXIF_TAG_COPYRIGHT)
      content = exif->ifd[EXIF_IFD_EXIF];     // EXIF tags
    else
      content = exif->ifd[EXIF_IFD_0];        // TIFF tags 

    if (!iExifGetTagInfo(tag, &(entry->format), &(entry->components)))
    {
      exif_entry_free(entry);
      return 1;
    }
  }

  int format_size = exif_format_get_size(entry->format);
  if (entry->components == 0)
    entry->components = attrib_count;

  entry->tag = tag;
  entry->size = format_size * entry->components;
  entry->data = (imbyte*)malloc(entry->size);

  if (tag == EXIF_TAG_RESOLUTION_UNIT)
  {
    int res_unit;
    if (imStrEqual((char*)attrib_data, "DPI"))
      res_unit = 2;
    else
      res_unit = 3;

    exif_content_add_entry(content, entry);
    exif_set_short(entry->data, byte_order, (imushort)res_unit);
    return 1;
  }

  /* test if tag type is the same as the attribute type */
  if (iExifGetDataType(entry->format) != data_type)
  {
    exif_entry_free(entry);
    return 1;
  }

  exif_content_add_entry(content, entry);

  switch (entry->format) 
  {
  case EXIF_FORMAT_UNDEFINED:
  case EXIF_FORMAT_ASCII:
  case EXIF_FORMAT_SBYTE:
  case EXIF_FORMAT_BYTE:
    {
      imbyte *bvalue = (imbyte*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
        entry->data[c] = bvalue[c];
    }
    break;
  case EXIF_FORMAT_SHORT:
    {
      imushort *usvalue = (imushort*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
        exif_set_short(entry->data + format_size * c, byte_order, usvalue[c]);
    }
    break;
  case EXIF_FORMAT_SSHORT:
    {
      short *svalue = (short*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
        exif_set_sshort(entry->data + format_size * c, byte_order, svalue[c]);
    }
    break;
  case EXIF_FORMAT_LONG:
    {
      int *ivalue = (int*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
        exif_set_long(entry->data + format_size * c, byte_order, (unsigned int)ivalue[c]);
    }
    break;
  case EXIF_FORMAT_SLONG:
    {
      int *ivalue = (int*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
        exif_set_slong(entry->data + format_size * c, byte_order, (int)ivalue[c]);
    }
    break;
  case EXIF_FORMAT_RATIONAL:
    {
      ExifRational v_rat;
      int num, den;
      float *fvalue = (float*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
      {
        iGetRational(fvalue[c], &num, &den, 1);
        v_rat.numerator = num;
        v_rat.denominator = den;
        exif_set_rational(entry->data + format_size * c, byte_order, v_rat);
      }
    }
    break;
  case EXIF_FORMAT_SRATIONAL:
    {
      ExifSRational v_srat;
      int num, den;
      float *fvalue = (float*)attrib_data;
      for (c = 0; c < (int)entry->components; c++) 
      {
        iGetRational(fvalue[c], &num, &den, 1);
        v_srat.numerator = num;
        v_srat.denominator = den;
        exif_set_srational(entry->data + format_size * c, byte_order, v_srat);
      }
    }
    break;
  case EXIF_FORMAT_FLOAT:   // defined but unsupported in libEXIF
  case EXIF_FORMAT_DOUBLE:  // defined but unsupported in libEXIF
    break;
  }

  /* no need to release the entry here,
     it will be handled internally 
     because we added the entry to the ExifContent */

  (void)index;
  return 1;
}
Пример #26
0
/** Heavily based on convert_arg_to_entry from exif command line tool.
 *  But without ExifLog, exitting, use of g_* io functions
 *   and can take a gdouble value instead of a string
 */
static void convert_to_entry (const char *set_value, gdouble gdvalue, ExifEntry *e, ExifByteOrder o)
{
	unsigned int i, numcomponents;
	char *value_p = NULL;
	char *buf = NULL;
	/*
	 * ASCII strings are handled separately,
	 * since they don't require any conversion.
	 */
	if (e->format == EXIF_FORMAT_ASCII ||
	    e->tag == EXIF_TAG_USER_COMMENT) {
		if (e->data) g_free (e->data);
		e->components = strlen (set_value) + 1;
		if (e->tag == EXIF_TAG_USER_COMMENT)
			e->components += 8 - 1;
		e->size = sizeof (char) * e->components;
		e->data = g_malloc (e->size);
		if (!e->data) {
			g_warning (_("Not enough memory."));
			return;
		}
		if (e->tag == EXIF_TAG_USER_COMMENT) {
			/* assume ASCII charset */
			/* TODO: get this from the current locale */
			memcpy ((char *) e->data, "ASCII\0\0\0", 8);
			memcpy ((char *) e->data + 8, set_value,
					strlen (set_value));
		} else
			strcpy ((char *) e->data, set_value);
		return;
	}

	/*
	 * Make sure we can handle this entry
	 */
	if ((e->components == 0) && *set_value) {
		g_warning (_("Setting a value for this tag is unsupported!"));
		return;
	}

	gboolean use_string = (set_value != NULL);
	if ( use_string ) {
		/* Copy the string so we can modify it */
		buf = g_strdup (set_value);
		if (!buf)
			return;
		value_p = strtok (buf, " ");
	}

	numcomponents = e->components;
	for (i = 0; i < numcomponents; ++i) {
		unsigned char s;

		if ( use_string ) {
			if (!value_p) {
				g_warning (_("Too few components specified (need %d, found %d)\n"), numcomponents, i);
				return;
			}
			if (!isdigit(*value_p) && (*value_p != '+') && (*value_p != '-')) {
				g_warning (_("Numeric value expected\n"));
				return;
			}
		}

		s = exif_format_get_size (e->format);
		switch (e->format) {
		case EXIF_FORMAT_ASCII:
			g_warning (_("This shouldn't happen!"));
			return;
			break;
		case EXIF_FORMAT_SHORT:
			exif_set_short (e->data + (s * i), o, atoi (value_p));
			break;
		case EXIF_FORMAT_SSHORT:
			exif_set_sshort (e->data + (s * i), o, atoi (value_p));
			break;
		case EXIF_FORMAT_RATIONAL: {
			ExifRational er;

			double val = 0.0 ;
			if ( use_string && value_p )
				val = fabs (atol (value_p));
			else
				val = fabs (gdvalue);

			if ( i == 0 ) {
				// One (or first) part rational

				// Sneak peek into tag as location tags need rounding down to give just the degrees part
				if ( e->tag == EXIF_TAG_GPS_LATITUDE || e->tag == EXIF_TAG_GPS_LONGITUDE ) {
					er.numerator = (ExifLong) floor ( val );
					er.denominator = 1.0;
				}
				else {
					// I don't see any point in doing anything too complicated here,
					//   such as trying to work out the 'best' denominator
					// For the moment use KISS principle.
					// Fix a precision of 1/100 metre as that's more than enough for GPS accuracy especially altitudes!
					er.denominator = 100.0;
					er.numerator = (ExifLong) (val * er.denominator);
				}
			}

			// Now for Location 3 part rationals do Mins and Seconds format

			// Rounded down minutes
			if ( i == 1 ) {
				er.denominator = 1.0;
				er.numerator = (ExifLong) ( (int) floor ( ( val - floor (val) ) * 60.0 ) );
			}

			// Finally seconds
			if ( i == 2 ) {
				er.denominator = 100.0;

				// Fractional minute.
				double FracPart = ((val - floor(val)) * 60) - (double)(int) floor ( ( val - floor (val) ) * 60.0 );
				er.numerator = (ExifLong) ( (int)floor(FracPart * 6000) ); // Convert to seconds.
			}
			exif_set_rational (e->data + (s * i), o, er );
			break;
		}
		case EXIF_FORMAT_LONG:
			exif_set_long (e->data + (s * i), o, atol (value_p));
			break;
		case EXIF_FORMAT_SLONG:
			exif_set_slong (e->data + (s * i), o, atol (value_p));
			break;
		case EXIF_FORMAT_BYTE:
		case EXIF_FORMAT_SBYTE:
		case EXIF_FORMAT_UNDEFINED: /* treat as byte array */
			e->data[s * i] = atoi (value_p);
			break;
		case EXIF_FORMAT_FLOAT:
		case EXIF_FORMAT_DOUBLE:
		case EXIF_FORMAT_SRATIONAL:
		default:
			g_warning (_("Not yet implemented!"));
			return;
		}
		
		if ( use_string )
			value_p = strtok (NULL, " ");

	}

	g_free (buf);

	if ( use_string )
		if ( value_p )
			g_warning (_("Warning; Too many components specified!"));
}
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;
}
static void
exif_data_save_data_entry (ExifData *data, ExifEntry *e,
			   unsigned char **d, unsigned int *ds,
			   unsigned int offset)
{
	unsigned int doff, s;
	unsigned int ts;

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

	/*
	 * Each entry is 12 bytes long. The memory for the entry has
	 * already been allocated.
	 */
	exif_set_short (*d + 6 + offset + 0,
			data->priv->order, (ExifShort) e->tag);
	exif_set_short (*d + 6 + offset + 2,
			data->priv->order, (ExifShort) e->format);

	if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) {
		/* If this is the maker note tag, update it. */
		if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) {
			/* TODO: this is using the wrong ExifMem to free e->data */
			exif_mem_free (data->priv->mem, e->data);
			e->data = NULL;
			e->size = 0;
			exif_mnote_data_set_offset (data->priv->md, *ds - 6);
			exif_mnote_data_save (data->priv->md, &e->data, &e->size);
			e->components = e->size;
		}
	}

	exif_set_long  (*d + 6 + offset + 4,
			data->priv->order, e->components);

	/*
	 * Size? If bigger than 4 bytes, the actual data is not in
	 * the entry but somewhere else.
	 */
	s = exif_format_get_size (e->format) * e->components;
	if (s > 4) {
		unsigned char *t;
		doff = *ds - 6;
		ts = *ds + s;

		/*
		 * According to the TIFF specification,
		 * the offset must be an even number. If we need to introduce
		 * a padding byte, we set it to 0.
		 */
		if (s & 1)
			ts++;
		t = exif_mem_realloc (data->priv->mem, *d, ts);
		if (!t) {
			EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts);
		  	return;
		}
		*d = t;
		*ds = ts;
		exif_set_long (*d + 6 + offset + 8, data->priv->order, doff);
		if (s & 1) 
			*(*d + *ds - 1) = '\0';

	} else
		doff = offset + 8;

	/* Write the data. Fill unneeded bytes with 0. Do not crash with
	 * e->data is NULL */
	if (e->data) {
		memcpy (*d + 6 + doff, e->data, s);
	} else {
		memset (*d + 6 + doff, 0, s);
	}
	if (s < 4) 
		memset (*d + 6 + doff + s, 0, (4 - s));
}
Пример #29
0
/** 
 * @brief save the MnoteData from ne to buf
 * 
 * @param ne extract the data from this structure 
 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
 * @param buf_size the size of the buffer
 */
static void
exif_mnote_data_olympus_save (ExifMnoteData *ne,
		unsigned char **buf, unsigned int *buf_size)
{
	ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
	size_t i, o, s, doff, base = 0, o2 = 6 + 2;
	size_t datao = 0;
	unsigned char *t;
	size_t ts;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number of entries.
	 */
	*buf_size = 6 + 2 + 2 + n->count * 12;
	switch (n->version) {
	case olympusV1:
	case sanyoV1:
	case epsonV1:
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
					(n->version==epsonV1?"EPSON":"OLYMP"));
		exif_set_short (*buf + 6, n->order, (ExifShort) 1);
		datao = n->offset;
		break;
	case olympusV2:
		*buf_size += 8-6 + 4;
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, "OLYMPUS");
		exif_set_short (*buf + 8, n->order, (ExifShort) (
			(n->order == EXIF_BYTE_ORDER_INTEL) ?
			('I' << 8) | 'I' :
			('M' << 8) | 'M'));
		exif_set_short (*buf + 10, n->order, (ExifShort) 3);
		o2 += 4;
		break;
	case nikonV1: 
		base = MNOTE_NIKON1_TAG_BASE;

		/* v1 has offsets based to main IFD, not makernote IFD */
		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 */
	case nikonV2: 
		*buf_size += 8 + 2;
		*buf_size += 4; /* Next IFD pointer */
		*buf = exif_mem_alloc (ne->mem, *buf_size);
		if (!*buf) {
			EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
			return;
		}

		/* Write the header and the number of entries. */
		strcpy ((char *)*buf, "Nikon");
		(*buf)[6] = n->version;

		if (n->version == nikonV2) {
			exif_set_short (*buf + 10, n->order, (ExifShort) (
				(n->order == EXIF_BYTE_ORDER_INTEL) ?
				('I' << 8) | 'I' :
				('M' << 8) | 'M'));
			exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
			exif_set_long (*buf + 14, n->order, (ExifShort) 8);
			o2 += 2 + 8;
		}
		datao -= 10;
		/* Reset next IFD pointer */
		exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
		break;

	default:
		return;
	}

	exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
	o2 += 2;

	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = o2 + i * 12;
		exif_set_short (*buf + o + 0, n->order,
				(ExifShort) (n->entries[i].tag - base));
		exif_set_short (*buf + o + 2, n->order,
				(ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order,
				n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			doff = *buf_size;
			ts = *buf_size + s;
			t = exif_mem_realloc (ne->mem, *buf,
						 sizeof (char) * ts);
			if (!t) {
				EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
				return;
			}
			*buf = t;
			*buf_size = ts;
			exif_set_long (*buf + o, n->order, datao + doff);
		} else
			doff = o;

		/* Write the data. */
		if (n->entries[i].data) {
			memcpy (*buf + doff, n->entries[i].data, s);
		} else {
			/* Most certainly damaged input file */
			memset (*buf + doff, 0, s);
		}
	}
}
Пример #30
0
static void
exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
			   unsigned int *buf_size)
{
	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
	size_t i, o, s, doff;
	unsigned char *t;
	size_t ts;

	if (!n || !buf || !buf_size) return;

	/*
	 * Allocate enough memory for all entries and the number
	 * of entries.
	 */
	*buf_size = 8 + 4 + 2 + n->count * 12 + 4;
	*buf = exif_mem_alloc (ne->mem, *buf_size);
	if (!*buf) {
		*buf_size = 0;
		return;
	}

	/*
	 * Header: "FUJIFILM" and 4 bytes offset to the first entry.
	 * As the first entry will start right thereafter, the offset is 12.
	 */
	memcpy (*buf, "FUJIFILM", 8);
	exif_set_long (*buf + 8, n->order, 12);

	/* Save the number of entries */
	exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
	
	/* Save each entry */
	for (i = 0; i < n->count; i++) {
		o = 8 + 4 + 2 + i * 12;
		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
		exif_set_long  (*buf + o + 4, n->order, n->entries[i].components);
		o += 8;
		s = exif_format_get_size (n->entries[i].format) *
						n->entries[i].components;
		if (s > 65536) {
			/* Corrupt data: EXIF data size is limited to the
			 * maximum size of a JPEG segment (64 kb).
			 */
			continue;
		}
		if (s > 4) {
			ts = *buf_size + s;

			/* Ensure even offsets. Set padding bytes to 0. */
			if (s & 1) ts += 1;
			t = exif_mem_realloc (ne->mem, *buf, ts);
			if (!t) {
				return;
			}
			*buf = t;
			*buf_size = ts;
			doff = *buf_size - s;
			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
			exif_set_long (*buf + o, n->order, doff);
		} else
			doff = o;

		/*
		 * Write the data. Fill unneeded bytes with 0. Do not
		 * crash if data is NULL.
		 */
		if (!n->entries[i].data) memset (*buf + doff, 0, s);
		else memcpy (*buf + doff, n->entries[i].data, s);
	}
}