X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libexif%2Fexif-content.c;h=6d6c589d07b89fc42c994d6b2ef1c0d0e53b7486;hb=18fd0ff7408961416a3077071320d95c66873b5d;hp=429c0eb6b5d2e5d93cc8ffb8445550896112e624;hpb=ec40af3b98eb91c28f06e7e679511f86785399d4;p=platform%2Fupstream%2Flibexif.git diff --git a/libexif/exif-content.c b/libexif/exif-content.c index 429c0eb..6d6c589 100644 --- a/libexif/exif-content.c +++ b/libexif/exif-content.c @@ -1,57 +1,78 @@ /* exif-content.c * - * Copyright (C) 2001 Lutz Müller + * Copyright (c) 2001 Lutz Mueller * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. */ + #include -#include "exif-content.h" + +#include +#include #include #include #include -//#define DEBUG - -static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; +/* unused constant + * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; + */ struct _ExifContentPrivate { unsigned int ref_count; + + ExifMem *mem; + ExifLog *log; }; ExifContent * exif_content_new (void) { + ExifMem *mem = exif_mem_new_default (); + ExifContent *content = exif_content_new_mem (mem); + + exif_mem_unref (mem); + + return content; +} + +ExifContent * +exif_content_new_mem (ExifMem *mem) +{ ExifContent *content; - content = malloc (sizeof (ExifContent)); + if (!mem) return NULL; + + content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent)); if (!content) - return (NULL); - memset (content, 0, sizeof (ExifContent)); - content->priv = malloc (sizeof (ExifContentPrivate)); + return NULL; + content->priv = exif_mem_alloc (mem, + (ExifLong) sizeof (ExifContentPrivate)); if (!content->priv) { - free (content); - return (NULL); + exif_mem_free (mem, content); + return NULL; } - memset (content->priv, 0, sizeof (ExifContentPrivate)); content->priv->ref_count = 1; - return (content); + content->priv->mem = mem; + exif_mem_ref (mem); + + return content; } void @@ -71,13 +92,22 @@ exif_content_unref (ExifContent *content) 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]); - free (content->entries); - free (content->priv); - free (content); + 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 @@ -93,46 +123,73 @@ exif_content_dump (ExifContent *content, unsigned int indent) if (!content) return; - printf ("%sDumping exif content (%i entries)...\n", buf, + printf ("%sDumping exif content (%u entries)...\n", buf, content->count); for (i = 0; i < content->count; i++) exif_entry_dump (content->entries[i], indent + 1); } void -exif_content_add_entry (ExifContent *content, ExifEntry *entry) +exif_content_add_entry (ExifContent *c, ExifEntry *entry) { - if (entry->parent) + ExifEntry **entries; + if (!c || !c->priv || !entry || entry->parent) return; + + /* One tag can only be added once to an IFD. */ + if (exif_content_get_entry (c, entry->tag)) { + exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent", + "An attempt has been made to add " + "the tag '%s' twice to an IFD. This is against " + "specification.", exif_tag_get_name (entry->tag)); return; + } - entry->parent = content; - content->entries = realloc (content->entries, - sizeof (ExifEntry) * (content->count + 1)); - content->entries[content->count] = entry; + entries = exif_mem_realloc (c->priv->mem, + c->entries, sizeof (ExifEntry*) * (c->count + 1)); + if (!entries) return; + entry->parent = c; + entries[c->count++] = entry; + c->entries = entries; exif_entry_ref (entry); - content->count++; } void -exif_content_remove_entry (ExifContent *content, ExifEntry *entry) +exif_content_remove_entry (ExifContent *c, ExifEntry *e) { unsigned int i; + ExifEntry **t, *temp; - if (entry->parent != content) - return; + if (!c || !c->priv || !e || (e->parent != c)) return; - for (i = 0; i < content->count; i++) - if (content->entries[i] == entry) - break; - if (i == content->count) - return; + /* Search the entry */ + for (i = 0; i < c->count; i++) + if (c->entries[i] == e) + break; - memmove (&content->entries[i], &content->entries[i + 1], - sizeof (ExifEntry) * (content->count - i - 1)); - content->count--; + if (i == c->count) + return; - entry->parent = NULL; - exif_entry_unref (entry); + /* Remove the entry */ + 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) { /* we deallocated the last slot already */ + 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); } ExifEntry * @@ -148,3 +205,123 @@ exif_content_get_entry (ExifContent *content, ExifTag tag) return (content->entries[i]); return (NULL); } + +void +exif_content_foreach_entry (ExifContent *content, + ExifContentForeachEntryFunc func, void *data) +{ + unsigned int i; + + if (!content || !func) + return; + + for (i = 0; i < content->count; i++) + func (content->entries[i], data); +} + +void +exif_content_log (ExifContent *content, ExifLog *log) +{ + if (!content || !content->priv || !log || content->priv->log == log) + return; + + if (content->priv->log) exif_log_unref (content->priv->log); + content->priv->log = log; + exif_log_ref (log); +} + +ExifIfd +exif_content_get_ifd (ExifContent *c) +{ + if (!c || !c->parent) return EXIF_IFD_COUNT; + + return + ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF : + ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 : + ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 : + ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS : + ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY : + EXIF_IFD_COUNT; +} + +static void +fix_func (ExifEntry *e, void *UNUSED(data)) +{ + exif_entry_fix (e); +} + +/*! + * Check if this entry is unknown and if so, delete it. + * \note Be careful calling this function in a loop. Deleting an entry from + * an ExifContent changes the index of subsequent entries, as well as the + * total size of the entries array. + */ +static void +remove_not_recorded (ExifEntry *e, void *UNUSED(data)) +{ + ExifIfd ifd = exif_entry_get_ifd(e) ; + ExifContent *c = e->parent; + ExifDataType dt = exif_data_get_data_type (c->parent); + ExifTag t = e->tag; + + if (exif_tag_get_support_level_in_ifd (t, ifd, dt) == + EXIF_SUPPORT_LEVEL_NOT_RECORDED) { + exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content", + "Tag 0x%04x is not recorded in IFD '%s' and has therefore been " + "removed.", t, exif_ifd_get_name (ifd)); + exif_content_remove_entry (c, e); + } + +} + +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); + } + } +}