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;
}
Beispiel #2
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;
}
/*! 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;
		}
	}
}