static void exif_mnote_data_free (ExifMnoteData *d) { ExifMem *mem = d ? d->mem : NULL; if (!d) return; if (d->priv) { if (d->methods.free) d->methods.free (d); exif_mem_free (mem, d->priv); d->priv = NULL; } exif_log_unref (d->log); exif_mem_free (mem, d); exif_mem_unref (mem); }
static void exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n) { ExifMnoteData *d = (ExifMnoteData *) n; unsigned int i; if (!n) return; if (n->entries) { for (i = 0; i < n->count; i++) if (n->entries[i].data) { exif_mem_free (d->mem, n->entries[i].data); n->entries[i].data = NULL; } exif_mem_free (d->mem, n->entries); n->entries = NULL; n->count = 0; } }
void exif_log_free (ExifLog *log) { ExifMem *mem = log ? log->mem : NULL; if (!log) return; exif_mem_free (mem, log); exif_mem_unref (mem); }
void exif_content_free (ExifContent *content) { ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL; unsigned int i; if (!content) return; for (i = 0; i < content->count; i++) exif_entry_unref (content->entries[i]); exif_mem_free (mem, content->entries); if (content->priv) { exif_log_unref (content->priv->log); } exif_mem_free (mem, content->priv); exif_mem_free (mem, content); exif_mem_unref (mem); }
void exif_loader_reset (ExifLoader *loader) { if (!loader) return; exif_mem_free (loader->mem, loader->buf); loader->buf = NULL; loader->size = 0; loader->bytes_read = 0; loader->state = 0; loader->b_len = 0; loader->data_format = EL_DATA_FORMAT_UNKNOWN; }
static void exif_loader_free (ExifLoader *loader) { ExifMem *mem; if (!loader) return; mem = loader->mem; exif_loader_reset (loader); exif_mem_free (mem, loader); exif_mem_unref (mem); }
void exif_data_free (ExifData *data) { unsigned int i; ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL; if (!data) return; for (i = 0; i < EXIF_IFD_COUNT; i++) { if (data->ifd[i]) { exif_content_unref (data->ifd[i]); data->ifd[i] = NULL; } } if (data->data) { exif_mem_free (mem, data->data); data->data = NULL; } if (data->priv) { if (data->priv->log) { exif_log_unref (data->priv->log); data->priv->log = NULL; } if (data->priv->md) { exif_mnote_data_unref (data->priv->md); data->priv->md = NULL; } exif_mem_free (mem, data->priv); exif_mem_free (mem, data); } exif_mem_unref (mem); }
ExifData * exif_data_new_mem (ExifMem *mem) { ExifData *data; unsigned int i; if (!mem) return NULL; data = exif_mem_alloc (mem, sizeof (ExifData)); if (!data) return (NULL); data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate)); if (!data->priv) { exif_mem_free (mem, data); return (NULL); } data->priv->ref_count = 1; data->priv->mem = mem; exif_mem_ref (mem); for (i = 0; i < EXIF_IFD_COUNT; i++) { data->ifd[i] = exif_content_new_mem (data->priv->mem); if (!data->ifd[i]) { exif_data_free (data); return (NULL); } data->ifd[i]->parent = data; } /* Default options */ #ifndef NO_VERBOSE_TAG_STRINGS /* * When the tag list is compiled away, setting this option prevents * any tags from being loaded */ exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS); #endif exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); /* Default data type: none */ exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT); return (data); }
static void exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d, unsigned int ds, ExifLong offset, ExifLong size) { if ((ds < offset + size) || (offset > ds)) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail offset (%u) or size (%u).", offset, size); return; } if (data->data) exif_mem_free (data->priv->mem, data->data); data->size = size; data->data = exif_data_alloc (data, data->size); if (!data->data) return; memcpy (data->data, d + offset, data->size); }
static void exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d, unsigned int ds, ExifLong o, ExifLong s) { /* Sanity checks */ if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) { exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail offset (%u) or size (%u).", o, s); return; } if (data->data) exif_mem_free (data->priv->mem, data->data); if (!(data->data = exif_data_alloc (data, s))) { EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", s); data->size = 0; return; } data->size = s; memcpy (data->data, d + o, s); }
void exif_content_remove_entry (ExifContent *c, ExifEntry *e) { unsigned int i; ExifEntry **t, *temp; if (!c || !c->priv || !e || (e->parent != c)) return; for (i = 0; i < c->count; i++) if (c->entries[i] == e) break; if (i == c->count) return; temp = c->entries[c->count-1]; if (c->count > 1) { t = exif_mem_realloc (c->priv->mem, c->entries, sizeof(ExifEntry*) * (c->count - 1)); if (!t) { return; } c->entries = t; c->count--; if (i != c->count) { memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1)); t[c->count-1] = temp; } } else { exif_mem_free (c->priv->mem, c->entries); c->entries = NULL; c->count = 0; } e->parent = NULL; exif_entry_unref (e); }
ExifContent * exif_content_new_mem (ExifMem *mem) { ExifContent *content; if (!mem) return NULL; content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent)); if (!content) return NULL; content->priv = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContentPrivate)); if (!content->priv) { exif_mem_free (mem, content); return NULL; } content->priv->ref_count = 1; content->priv->mem = mem; exif_mem_ref (mem); return content; }
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; }
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)); }