void exif_content_fix (ExifContent *c) { ExifIfd ifd = exif_content_get_ifd (c); ExifDataType dt; ExifTag t; ExifEntry *e; if (!c) return; dt = exif_data_get_data_type (c->parent); /* First of all, fix all existing entries. */ exif_content_foreach_entry (c, fix_func, NULL); /* * Then check for existing tags that are not allowed and for * non-existing mandatory tags. */ for (t = 0; t <= 0xffff; t++) { switch (exif_tag_get_support_level_in_ifd (t, ifd, dt)) { case EXIF_SUPPORT_LEVEL_MANDATORY: if (exif_content_get_entry (c, t)) break; exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", "Tag '%s' is mandatory in IFD '%s' and has therefore been added.", exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd)); e = exif_entry_new (); exif_content_add_entry (c, e); exif_entry_initialize (e, t); exif_entry_unref (e); break; case EXIF_SUPPORT_LEVEL_NOT_RECORDED: e = exif_content_get_entry (c, t); if (!e) break; exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", "Tag '%s' is not recoreded in IFD '%s' and has therefore been " "removed.", exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd)); exif_content_remove_entry (c, e); break; case EXIF_SUPPORT_LEVEL_OPTIONAL: default: break; } } }
/* tags do not uniquely set tag names: the same tag can have different * names in different ifds. * * As long as this entry has been linked to an ifd, get the tag name. */ static const char * vips_exif_entry_get_name( ExifEntry *entry ) { if( !entry->parent ) return( NULL ); return( exif_tag_get_name_in_ifd( entry->tag, exif_entry_get_ifd( entry ) ) ); }
/* show given exif tag content */ static void exif_get_tag(ExifData *d, ExifIfd ifd, ExifTag tag, char* buffer, unsigned int maxsize) { char s[MAX_EXIF_DATA]; if ( (d != NULL) && (buffer != NULL) && (maxsize>0) ) { ExifEntry *entry = exif_content_get_entry(d->ifd[ifd], tag); if (entry != NULL) { /* Get the contents of the tag in human-readable form */ exif_entry_get_value(entry, s, maxsize); /* Don't bother printing it if it's entirely blank */ exif_trim_spaces(s); if (*s != '\0') { D(("%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), s)); snprintf(buffer, (size_t)maxsize, "%s: %s\n", exif_tag_get_name_in_ifd(tag,ifd), s); } } } }
void exif_content_fix (ExifContent *c) { ExifIfd ifd = exif_content_get_ifd (c); ExifDataType dt; ExifEntry *e; unsigned int i, num; if (!c) return; dt = exif_data_get_data_type (c->parent); /* * First of all, fix all existing entries. */ exif_content_foreach_entry (c, fix_func, NULL); /* * Go through each tag and if it's not recorded, remove it. If one * is removed, exif_content_foreach_entry() will skip the next entry, * so if this happens do the loop again from the beginning to ensure * they're all checked. This could be avoided if we stop relying on * exif_content_foreach_entry but loop intelligently here. */ do { num = c->count; exif_content_foreach_entry (c, remove_not_recorded, NULL); } while (num != c->count); /* * Then check for non-existing mandatory tags and create them if needed */ num = exif_tag_table_count(); for (i = 0; i < num; ++i) { const ExifTag t = exif_tag_table_get_tag (i); if (exif_tag_get_support_level_in_ifd (t, ifd, dt) == EXIF_SUPPORT_LEVEL_MANDATORY) { if (exif_content_get_entry (c, t)) /* This tag already exists */ continue; exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", "Tag '%s' is mandatory in IFD '%s' and has therefore been added.", exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd)); e = exif_entry_new (); exif_content_add_entry (c, e); exif_entry_initialize (e, t); exif_entry_unref (e); } } }
static void parse_exif_entry(ExifEntry * e, void *data) { MediaScanResult *r = (MediaScanResult *)data; const char *key; char val[1024]; // Get orientation if (e->tag == 0x112) { ExifByteOrder o = exif_data_get_byte_order(e->parent->parent); r->image->orientation = exif_get_short(e->data, o); LOG_DEBUG("Exif orientation: %d\n", r->image->orientation); } // Get key and value key = exif_tag_get_name_in_ifd(e->tag, exif_entry_get_ifd(e)); exif_entry_get_value(e, val, sizeof(val)); LOG_DEBUG("Saving Exif entry: %s: %s\n", key, val); tag_add_item(r->_tag, key, (const char *)val); }
void exif_content_fix (ExifContent *c) { ExifIfd ifd = exif_content_get_ifd (c); ExifDataType dt; ExifEntry *e; unsigned int i, num; if (!c) return; dt = exif_data_get_data_type (c->parent); exif_content_foreach_entry (c, fix_func, NULL); do { num = c->count; exif_content_foreach_entry (c, remove_not_recorded, NULL); } while (num != c->count); num = exif_tag_table_count(); for (i = 0; i < num; ++i) { const ExifTag t = exif_tag_table_get_tag (i); if (exif_tag_get_support_level_in_ifd (t, ifd, dt) == EXIF_SUPPORT_LEVEL_MANDATORY) { if (exif_content_get_entry (c, t)) continue; exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", "Tag '%s' is mandatory in IFD '%s' and has therefore been added.", exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd)); e = exif_entry_new (); exif_content_add_entry (c, e); exif_entry_initialize (e, t); exif_entry_unref (e); } } }
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); }
GstTagList * gst_droidcamsrc_exif_tags_from_jpeg_data (void *data, size_t size) { GstTagList *tags = NULL; ExifMem *mem = exif_mem_new (g_malloc0, g_realloc, g_free); ExifData *exif = exif_data_new_mem (mem); unsigned char *exif_data = NULL; void *_exif_data = NULL; unsigned int exif_data_size = 0; GstBuffer *buffer; ExifEntry *iso; int x, i; exif_data_load_data (exif, data, size); exif_data_set_data_type (exif, EXIF_DATA_TYPE_COMPRESSED); exif_data_save_data (exif, &exif_data, &exif_data_size); if (!exif_data_size) { goto out; } if (exif_data_size <= 6) { goto out; } /* dump the data. based on libexif code */ for (x = 0; x < EXIF_IFD_COUNT; x++) { if (exif->ifd[x] && exif->ifd[x]->count) { for (i = 0; i < exif->ifd[x]->count; i++) { char val[1024]; ExifEntry *e = exif->ifd[x]->entries[i]; GST_LOG ("Exif IFD: %s. Tag 0x%x (%s) = %s", exif_ifd_get_name (x), e->tag, exif_tag_get_name_in_ifd (e->tag, exif_entry_get_ifd (e)), exif_entry_get_value (e, val, sizeof (val))); } } } _exif_data = exif_data; exif_data += 6; exif_data_size -= 6; buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, exif_data, exif_data_size, 0, exif_data_size, NULL, NULL); tags = gst_tag_list_from_exif_buffer_with_tiff_header (buffer); gst_buffer_unref (buffer); /* We don't want these tags */ gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MANUFACTURER); gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MODEL); gst_tag_list_remove_tag (tags, GST_TAG_APPLICATION_NAME); gst_tag_list_remove_tag (tags, GST_TAG_DATE_TIME); /* we have a mess with ISO so we will just behave as N9 */ iso = exif_content_get_entry (exif->ifd[EXIF_IFD_EXIF], EXIF_TAG_ISO_SPEED_RATINGS); if (iso) { #ifdef __arm__ guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_MOTOROLA); #else guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_INTEL); #endif gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CAPTURING_ISO_SPEED, val, NULL); } /* TODO: the following are being dropped * * 0x213 EXIF_TAG_YCBCR_POSITIONING * 0x9004 EXIF_TAG_DATE_TIME_DIGITIZED * 0x9101 EXIF_TAG_COMPONENTS_CONFIGURATION * 0xa001 EXIF_TAG_COLOR_SPACE * 0xa002 EXIF_TAG_PIXEL_X_DIMENSION * 0xa003 EXIF_TAG_PIXEL_Y_DIMENSION * 0xa005 EXIF_TAG_INTEROPERABILITY_IFD_POINTER * thumbnail. * 0x100 EXIF_TAG_IMAGE_WIDTH * 0x101 EXIF_TAG_IMAGE_LENGTH * 0x9203 EXIF_TAG_BRIGHTNESS_VALUE * 0x9205 EXIF_TAG_MAX_APERTURE_VALUE * 0x9206 EXIF_TAG_SUBJECT_DISTANCE * 0x9208 EXIF_TAG_LIGHT_SOURCE * 0x9286 EXIF_TAG_USER_COMMENT */ out: if (_exif_data) { exif_mem_free (mem, _exif_data); } if (exif) { exif_data_free (exif); } exif_mem_unref (mem); return tags; }
/*! 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 void exif_entry_cb (ExifEntry *entry, gpointer data) { GtkTreeStore *store; EogExifDetails *view; EogExifDetailsPrivate *priv; ExifCategory cat; ExifIfd ifd = exif_entry_get_ifd (entry); char *path; char b[1024]; const gint key = ifd << 16 | entry->tag; /* This should optimize away if comparision is correct */ g_warn_if_fail (EXIF_IFD_COUNT <= G_MAXUINT16); view = EOG_EXIF_DETAILS (data); priv = view->priv; store = GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (view))); /* Take the tag's IFD into account when caching their GtkTreePaths. * That should fix key collisions for tags that have the same number * but are stored in different IFDs. Exif tag numbers are 16-bit * values so we should be able to set the high word to the IFD number. */ path = g_hash_table_lookup (priv->id_path_hash, GINT_TO_POINTER (key)); if (path != NULL) { set_row_data (store, path, NULL, exif_tag_get_name_in_ifd (entry->tag, ifd), eog_exif_entry_get_value (entry, b, sizeof(b))); } else { ExifMnoteData *mnote = (entry->tag == EXIF_TAG_MAKER_NOTE ? exif_data_get_mnote_data (entry->parent->parent) : NULL); if (mnote) { // Supported MakerNote Found unsigned int i, c = exif_mnote_data_count (mnote); for (i = 0; i < c; i++) { path = g_hash_table_lookup (priv->id_path_hash_mnote, GINT_TO_POINTER (i)); if (path != NULL) { set_row_data (store, path, NULL, exif_mnote_data_get_title (mnote, i), exif_mnote_data_get_value (mnote, i, b, sizeof(b))); } else { path = set_row_data (store, NULL, exif_categories[EXIF_CATEGORY_MAKER_NOTE].path, exif_mnote_data_get_title (mnote, i), exif_mnote_data_get_value (mnote, i, b, sizeof(b))); g_hash_table_insert (priv->id_path_hash_mnote, GINT_TO_POINTER (i), path); } } } else { cat = get_exif_category (entry); path = set_row_data (store, NULL, exif_categories[cat].path, exif_tag_get_name_in_ifd (entry->tag, ifd), eog_exif_entry_get_value (entry, b, sizeof(b))); g_hash_table_insert (priv->id_path_hash, GINT_TO_POINTER (key), path); } } }
static int Egettag (lua_State *L) { /** entry.tag */ ExifEntry *entry = checkentry(L); ExifIfd ifd = exif_entry_get_ifd(entry); lua_pushstring(L, exif_tag_get_name_in_ifd(entry->tag, ifd)); return 1; }
static void foreach_exif_entry( ExifEntry * entry , void * _closure ) { if ( ! entry ) { return; } //......................................................................... // Bail out of types we don't handle switch( entry->format ) { case EXIF_FORMAT_UNDEFINED: case EXIF_FORMAT_FLOAT: case EXIF_FORMAT_DOUBLE: return; default: break; } //......................................................................... unsigned char component_size = exif_format_get_size( entry->format ); ExifIfd ifd = exif_content_get_ifd( entry->parent ); const char * tag_name = exif_tag_get_name_in_ifd( entry->tag , ifd ); if ( ! tag_name || ! entry->data || ! entry->size || ! component_size || ! entry->components ) { return; } //......................................................................... // Add a prefix based on the IFD String name( tag_name ); switch( ifd ) { case EXIF_IFD_0: name = "IMAGE/" + name; break; case EXIF_IFD_1: name = "THUMBNAIL/" + name; break; case EXIF_IFD_EXIF: name = "EXIF/" + name; break; case EXIF_IFD_GPS: name = "GPS/" + name; break; case EXIF_IFD_INTEROPERABILITY: name = "INTEROP/" + name; break; default: return; } ExifClosure * closure = ( ExifClosure * ) _closure; JSON::Object * tags = closure->tags; //......................................................................... // ASCII ones are easy if ( entry->format == EXIF_FORMAT_ASCII ) { (*tags)[ name ] = String( ( const char * ) entry->data , entry->size ); return; } //......................................................................... if ( ( entry->components * component_size ) != entry->size ) { return; } ExifByteOrder byte_order = exif_data_get_byte_order( closure->exif_data ); const unsigned char * data = entry->data; JSON::Array array; for ( unsigned long i = 0; i < entry->components; ++i ) { switch( entry->format ) { case EXIF_FORMAT_BYTE: array.append( JSON::Value( int( * data ) ) ); break; case EXIF_FORMAT_SHORT: array.append( JSON::Value( int( exif_get_short( data , byte_order ) ) ) ); break; case EXIF_FORMAT_LONG: array.append( JSON::Value( int( exif_get_long( data , byte_order ) ) ) ); break; case EXIF_FORMAT_SBYTE: array.append( JSON::Value( int( * ( ( const char * ) data ) ) ) ); break; case EXIF_FORMAT_SSHORT: array.append( JSON::Value( exif_get_sshort( data , byte_order ) ) ); break; case EXIF_FORMAT_SLONG: array.append( JSON::Value( exif_get_slong( data , byte_order ) ) ); break; // TODO: I don't like representing a rational number as a string with a slash, case EXIF_FORMAT_SRATIONAL: { ExifSRational r = exif_get_srational( data , byte_order ); array.append( Util::format("%ld/%ld" , r.numerator , r.denominator ) ); break; } case EXIF_FORMAT_RATIONAL: { ExifRational r = exif_get_rational( data , byte_order ); array.append( Util::format("%lu/%lu" , r.numerator , r.denominator ) ); break; } default: break; } data += component_size; } if ( array.size() == 1 ) { (*tags)[ name ] = array[ 0 ]; } else if ( array.size() > 1 ) { (*tags)[ name ] = array; } }
static void analyzer_jpeg_exif_entry_analyze(ExifEntry *entry, void *pload) { ExifIfd ifd = exif_content_get_ifd(entry->parent); const char *tag_name = exif_tag_get_name_in_ifd(entry->tag, ifd); if (!tag_name) // Unknown tag return; struct ptype *value = NULL; // First parse ascii values if (entry->format == EXIF_FORMAT_ASCII) { char *str = malloc(entry->size); if (!str) { pom_oom(entry->size); return; } memcpy(str, entry->data, entry->size); // Make sure it's NULL terminated str[entry->size - 1] = 0; value = ptype_alloc("string"); if (!value) { free(str); return; } PTYPE_STRING_SETVAL_P(value, str); } else if (entry->components == 1) { ExifByteOrder byte_order = exif_data_get_byte_order(entry->parent->parent); if (entry->format == EXIF_FORMAT_BYTE) { value = ptype_alloc("uint8"); if (!value) return; PTYPE_UINT8_SETVAL(value, *entry->data); } else if (entry->format == EXIF_FORMAT_SHORT) { value = ptype_alloc("uint16"); if (!value) return; PTYPE_UINT16_SETVAL(value, exif_get_short(entry->data, byte_order)); } else if (entry->format == EXIF_FORMAT_LONG) { value = ptype_alloc("uint32"); if (!value) return; PTYPE_UINT32_SETVAL(value, exif_get_long(entry->data, byte_order)); } } if (!value) { // Fallback for types not parsed by us yet // FIXME this is subject to the locale char buff[256]; buff[sizeof(buff) - 1] = 0; exif_entry_get_value(entry, buff, sizeof(buff) - 1); value = ptype_alloc("string"); if (!value) return; PTYPE_STRING_SETVAL(value, buff); } char *key = strdup(tag_name); if (!key) { pom_oom(strlen(tag_name) + 1); return; } struct data *data = analyzer_pload_buffer_get_data(pload); data_item_add_ptype(data, analyzer_jpeg_pload_exif, key, value); }