EXIF library (libexif) Internals  0.6.24
exif-content.c
Go to the documentation of this file.
1 /* exif-content.c
2  *
3  * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301 USA.
19  */
20 
21 #include <config.h>
22 
23 #include <libexif/exif-content.h>
24 #include <libexif/exif-system.h>
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 
30 /* unused constant
31  * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
32  */
33 
35 {
36  unsigned int ref_count;
37 
40 };
41 
44 {
45  ExifMem *mem = exif_mem_new_default ();
46  ExifContent *content = exif_content_new_mem (mem);
47 
48  exif_mem_unref (mem);
49 
50  return content;
51 }
52 
55 {
56  ExifContent *content;
57 
58  if (!mem) return NULL;
59 
60  content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
61  if (!content)
62  return NULL;
63  content->priv = exif_mem_alloc (mem,
64  (ExifLong) sizeof (ExifContentPrivate));
65  if (!content->priv) {
66  exif_mem_free (mem, content);
67  return NULL;
68  }
69 
70  content->priv->ref_count = 1;
71 
72  content->priv->mem = mem;
73  exif_mem_ref (mem);
74 
75  return content;
76 }
77 
78 void
80 {
81  if (!content)
82  return;
83 
84  content->priv->ref_count++;
85 }
86 
87 void
89 {
90  if (!content)
91  return;
92 
93  content->priv->ref_count--;
94  if (!content->priv->ref_count)
95  exif_content_free (content);
96 }
97 
98 void
100 {
101  ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
102  unsigned int i;
103 
104  if (!content) return;
105 
106  for (i = 0; i < content->count; i++)
107  exif_entry_unref (content->entries[i]);
108  exif_mem_free (mem, content->entries);
109 
110  if (content->priv) {
111  exif_log_unref (content->priv->log);
112  }
113 
114  exif_mem_free (mem, content->priv);
115  exif_mem_free (mem, content);
116  exif_mem_unref (mem);
117 }
118 
119 void
120 exif_content_dump (ExifContent *content, unsigned int indent)
121 {
122  char buf[1024];
123  unsigned int i, l;
124 
125  if (!content)
126  return;
127 
128  l = MIN(sizeof(buf)-1, 2*indent);
129  memset(buf, ' ', l);
130  buf[l] = '\0';
131 
132  printf ("%sDumping exif content (%u entries)...\n", buf,
133  content->count);
134  for (i = 0; i < content->count; i++)
135  exif_entry_dump (content->entries[i], indent + 1);
136 }
137 
138 void
140 {
141  ExifEntry **entries;
142  if (!c || !c->priv || !entry || entry->parent) return;
143 
144  /* One tag can only be added once to an IFD. */
145  if (exif_content_get_entry (c, entry->tag)) {
146  exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
147  "An attempt has been made to add "
148  "the tag '%s' twice to an IFD. This is against "
149  "specification.", exif_tag_get_name (entry->tag));
150  return;
151  }
152 
153  entries = exif_mem_realloc (c->priv->mem,
154  c->entries, sizeof (ExifEntry*) * (c->count + 1));
155  if (!entries) return;
156  entry->parent = c;
157  entries[c->count++] = entry;
158  c->entries = entries;
159  exif_entry_ref (entry);
160 }
161 
162 void
164 {
165  unsigned int i;
166  ExifEntry **t, *temp;
167 
168  if (!c || !c->priv || !e || (e->parent != c)) return;
169 
170  /* Search the entry */
171  for (i = 0; i < c->count; i++)
172  if (c->entries[i] == e)
173  break;
174 
175  if (i == c->count)
176  return;
177 
178  /* Remove the entry */
179  temp = c->entries[c->count-1];
180  if (c->count > 1) {
181  t = exif_mem_realloc (c->priv->mem, c->entries,
182  sizeof(ExifEntry*) * (c->count - 1));
183  if (!t) {
184  return;
185  }
186  c->entries = t;
187  c->count--;
188  if (i != c->count) { /* we deallocated the last slot already */
189  memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
190  t[c->count-1] = temp;
191  }
192  } else {
193  exif_mem_free (c->priv->mem, c->entries);
194  c->entries = NULL;
195  c->count = 0;
196  }
197  e->parent = NULL;
198  exif_entry_unref (e);
199 }
200 
201 ExifEntry *
203 {
204  unsigned int i;
205 
206  if (!content)
207  return (NULL);
208 
209  for (i = 0; i < content->count; i++)
210  if (content->entries[i]->tag == tag)
211  return (content->entries[i]);
212  return (NULL);
213 }
214 
215 void
217  ExifContentForeachEntryFunc func, void *data)
218 {
219  unsigned int i;
220 
221  if (!content || !func)
222  return;
223 
224  for (i = 0; i < content->count; i++)
225  func (content->entries[i], data);
226 }
227 
228 void
230 {
231  if (!content || !content->priv || !log || content->priv->log == log)
232  return;
233 
234  if (content->priv->log) exif_log_unref (content->priv->log);
235  content->priv->log = log;
236  exif_log_ref (log);
237 }
238 
239 ExifIfd
241 {
242  if (!c || !c->parent) return EXIF_IFD_COUNT;
243 
244  return
245  ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
246  ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
247  ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
248  ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
249  ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
251 }
252 
253 static void
254 fix_func (ExifEntry *e, void *UNUSED(data))
255 {
256  exif_entry_fix (e);
257 }
258 
265 static void
267 {
269  ExifContent *c = e->parent;
271  ExifTag t = e->tag;
272 
273  if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
275  exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
276  "Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
277  "removed.", t, exif_ifd_get_name (ifd));
279  }
280 
281 }
282 
283 void
285 {
287  ExifDataType dt;
288  ExifEntry *e;
289  unsigned int i, num;
290 
291  if (!c)
292  return;
293 
295 
296  /*
297  * First of all, fix all existing entries.
298  */
300 
301  /*
302  * Go through each tag and if it's not recorded, remove it. If one
303  * is removed, exif_content_foreach_entry() will skip the next entry,
304  * so if this happens do the loop again from the beginning to ensure
305  * they're all checked. This could be avoided if we stop relying on
306  * exif_content_foreach_entry but loop intelligently here.
307  */
308  do {
309  num = c->count;
311  } while (num != c->count);
312 
313  /*
314  * Then check for non-existing mandatory tags and create them if needed
315  */
316  num = exif_tag_table_count();
317  for (i = 0; i < num; ++i) {
318  const ExifTag t = exif_tag_table_get_tag (i);
319  if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
321  if (exif_content_get_entry (c, t))
322  /* This tag already exists */
323  continue;
324  exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
325  "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
327  e = exif_entry_new ();
328  exif_content_add_entry (c, e);
329  exif_entry_initialize (e, t);
330  exif_entry_unref (e);
331  }
332  }
333 }
void exif_content_remove_entry(ExifContent *c, ExifEntry *e)
Remove an EXIF tag from an IFD.
Definition: exif-content.c:163
ExifIfd exif_content_get_ifd(ExifContent *c)
Return the IFD number in which the given ExifContent is found.
Definition: exif-content.c:240
void exif_content_fix(ExifContent *c)
Fix the IFD to bring it into specification.
Definition: exif-content.c:284
static void fix_func(ExifEntry *e, void *UNUSED(data))
Definition: exif-content.c:254
void exif_content_ref(ExifContent *content)
Increase reference counter for ExifContent.
Definition: exif-content.c:79
void exif_content_unref(ExifContent *content)
Decrease reference counter for ExifContent.
Definition: exif-content.c:88
void exif_content_add_entry(ExifContent *c, ExifEntry *entry)
Add an EXIF tag to an IFD.
Definition: exif-content.c:139
ExifContent * exif_content_new_mem(ExifMem *mem)
Reserve memory for and initialize new ExifContent using the specified memory allocator.
Definition: exif-content.c:54
void exif_content_dump(ExifContent *content, unsigned int indent)
Dump contents of the IFD to stdout.
Definition: exif-content.c:120
ExifEntry * exif_content_get_entry(ExifContent *content, ExifTag tag)
Return the ExifEntry in this IFD corresponding to the given tag.
Definition: exif-content.c:202
void exif_content_log(ExifContent *content, ExifLog *log)
Set the log message object for this IFD.
Definition: exif-content.c:229
static void remove_not_recorded(ExifEntry *e, void *UNUSED(data))
Check if this entry is unknown and if so, delete it.
Definition: exif-content.c:266
ExifContent * exif_content_new(void)
Reserve memory for and initialize a new ExifContent.
Definition: exif-content.c:43
void exif_content_foreach_entry(ExifContent *content, ExifContentForeachEntryFunc func, void *data)
Executes function on each EXIF tag in this IFD in turn.
Definition: exif-content.c:216
void exif_content_free(ExifContent *content)
Actually free the ExifContent.
Definition: exif-content.c:99
Handling EXIF IFDs.
void(* ExifContentForeachEntryFunc)(ExifEntry *, void *user_data)
Definition: exif-content.h:130
ExifDataType
Represents the type of image data to which the EXIF data applies.
ExifDataType exif_data_get_data_type(ExifData *d)
Return the data type for the given ExifData.
Definition: exif-data.c:1357
ExifEntry * exif_entry_new(void)
Reserve memory for and initialize a new ExifEntry.
Definition: exif-entry.c:111
void exif_entry_unref(ExifEntry *e)
Decrease reference counter for ExifEntry.
Definition: exif-entry.c:147
void exif_entry_fix(ExifEntry *e)
Fix the type or format of the given EXIF entry to bring it into spec.
Definition: exif-entry.c:205
void exif_entry_initialize(ExifEntry *e, ExifTag tag)
Initialize an empty ExifEntry with default data in the correct format for the given tag.
Definition: exif-entry.c:1459
void exif_entry_dump(ExifEntry *e, unsigned int indent)
Dump text representation of ExifEntry to stdout.
Definition: exif-entry.c:598
void exif_entry_ref(ExifEntry *e)
Increase reference counter for ExifEntry.
Definition: exif-entry.c:139
#define exif_entry_get_ifd(e)
Return the IFD number of the given ExifEntry.
Definition: exif-entry.h:180
ExifIfd ifd
Definition: exif-ifd.c:28
const char * exif_ifd_get_name(ExifIfd ifd)
Return a textual name of the given IFD.
Definition: exif-ifd.c:40
ExifIfd
Possible EXIF Image File Directories.
Definition: exif-ifd.h:29
@ EXIF_IFD_GPS
Definition: exif-ifd.h:33
@ EXIF_IFD_INTEROPERABILITY
Definition: exif-ifd.h:34
@ EXIF_IFD_EXIF
Definition: exif-ifd.h:32
@ EXIF_IFD_1
Definition: exif-ifd.h:31
@ EXIF_IFD_COUNT
Not a real value, just (max_value + 1).
Definition: exif-ifd.h:35
@ EXIF_IFD_0
Definition: exif-ifd.h:30
void exif_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format,...)
Definition: exif-log.c:135
void exif_log_unref(ExifLog *log)
Definition: exif-log.c:104
void exif_log_ref(ExifLog *log)
Definition: exif-log.c:97
@ EXIF_LOG_CODE_DEBUG
Definition: exif-log.h:56
void * exif_mem_realloc(ExifMem *mem, void *d, ExifLong ds)
Definition: exif-mem.c:89
void exif_mem_free(ExifMem *mem, void *d)
Definition: exif-mem.c:69
void exif_mem_unref(ExifMem *mem)
Unrefcount an ExifMem.
Definition: exif-mem.c:61
ExifMem * exif_mem_new_default(void)
Create a new ExifMem with default values for your convenience.
Definition: exif-mem.c:95
void * exif_mem_alloc(ExifMem *mem, ExifLong ds)
Definition: exif-mem.c:79
void exif_mem_ref(ExifMem *mem)
Refcount an ExifMem.
Definition: exif-mem.c:54
System specific definitions, not for installation!
#define UNUSED(param)
Definition: exif-system.h:29
const char * exif_tag_get_name(ExifTag tag)
Definition: exif-tag.c:1147
ExifTag exif_tag_table_get_tag(unsigned int n)
Definition: exif-tag.c:980
const char * exif_tag_get_name_in_ifd(ExifTag tag, ExifIfd ifd)
Return a textual name of the given tag when found in the given IFD.
Definition: exif-tag.c:1038
unsigned int exif_tag_table_count(void)
Return the number of entries in the EXIF tag table, including the terminating NULL entry.
Definition: exif-tag.c:973
ExifSupportLevel exif_tag_get_support_level_in_ifd(ExifTag tag, ExifIfd ifd, ExifDataType t)
Return whether the given tag is mandatory or not in the given IFD and data type according to the EXIF...
Definition: exif-tag.c:1256
ExifTag
EXIF tags.
Definition: exif-tag.h:34
@ EXIF_SUPPORT_LEVEL_NOT_RECORDED
This tag is not allowed in the given IFD.
Definition: exif-tag.h:213
@ EXIF_SUPPORT_LEVEL_MANDATORY
This tag is mandatory in the given IFD.
Definition: exif-tag.h:216
uint32_t ExifLong
EXIF Unsigned Long data type.
Definition: exif-utils.h:54
#define MIN(a, b)
Definition: exif-utils.h:180
MnoteAppleTag tag
unsigned int ref_count
Definition: exif-content.c:36
unsigned int count
Definition: exif-content.h:43
ExifContentPrivate * priv
Definition: exif-content.h:48
ExifData * parent
Data containing this content.
Definition: exif-content.h:46
ExifEntry ** entries
Definition: exif-content.h:42
Data found in one EXIF tag.
Definition: exif-entry.h:43
ExifContent * parent
ExifContent containing this entry.
Definition: exif-entry.h:65
ExifTag tag
EXIF tag for this entry.
Definition: exif-entry.h:45

libexif Generated by doxygen