EXIF library (libexif) Internals 0.6.26
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 * SPDX-License-Identifier: LGPL-2.0-or-later
21 */
22
23#include <config.h>
24
26#include <libexif/exif-system.h>
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31
32/* unused constant
33 * static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
34 */
35
37{
38 unsigned int ref_count;
39
42};
43
46{
48 ExifContent *content = exif_content_new_mem (mem);
49
50 exif_mem_unref (mem);
51
52 return content;
53}
54
57{
58 ExifContent *content;
59
60 if (!mem) return NULL;
61
62 content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
63 if (!content)
64 return NULL;
65 content->priv = exif_mem_alloc (mem,
66 (ExifLong) sizeof (ExifContentPrivate));
67 if (!content->priv) {
68 exif_mem_free (mem, content);
69 return NULL;
70 }
71
72 content->priv->ref_count = 1;
73
74 content->priv->mem = mem;
75 exif_mem_ref (mem);
76
77 return content;
78}
79
80void
82{
83 if (!content)
84 return;
85
86 content->priv->ref_count++;
87}
88
89void
91{
92 if (!content)
93 return;
94
95 content->priv->ref_count--;
96 if (!content->priv->ref_count)
97 exif_content_free (content);
98}
99
100void
102{
103 ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
104 unsigned int i;
105
106 if (!content) return;
107
108 for (i = 0; i < content->count; i++)
109 exif_entry_unref (content->entries[i]);
110 exif_mem_free (mem, content->entries);
111
112 if (content->priv) {
113 exif_log_unref (content->priv->log);
114 }
115
116 exif_mem_free (mem, content->priv);
117 exif_mem_free (mem, content);
118 exif_mem_unref (mem);
119}
120
121void
122exif_content_dump (ExifContent *content, unsigned int indent)
123{
124 char buf[1024];
125 unsigned int i, l;
126
127 if (!content)
128 return;
129
130 l = MIN(sizeof(buf)-1, 2*indent);
131 memset(buf, ' ', l);
132 buf[l] = '\0';
133
134 printf ("%sDumping exif content (%u entries)...\n", buf,
135 content->count);
136 for (i = 0; i < content->count; i++)
137 exif_entry_dump (content->entries[i], indent + 1);
138}
139
140void
142{
143 ExifEntry **entries;
144 if (!c || !c->priv || !entry || entry->parent) return;
145
146 /* One tag can only be added once to an IFD. */
147 if (exif_content_get_entry (c, entry->tag)) {
148 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
149 "An attempt has been made to add "
150 "the tag '%s' twice to an IFD. This is against "
151 "specification.", exif_tag_get_name (entry->tag));
152 return;
153 }
154
155 entries = exif_mem_realloc (c->priv->mem,
156 c->entries, sizeof (ExifEntry*) * (c->count + 1));
157 if (!entries) return;
158 entry->parent = c;
159 entries[c->count++] = entry;
160 c->entries = entries;
161 exif_entry_ref (entry);
162}
163
164void
166{
167 unsigned int i;
168 ExifEntry **t, *temp;
169
170 if (!c || !c->priv || !e || (e->parent != c)) return;
171
172 /* Search the entry */
173 for (i = 0; i < c->count; i++)
174 if (c->entries[i] == e)
175 break;
176
177 if (i == c->count)
178 return;
179
180 /* Remove the entry */
181 temp = c->entries[c->count-1];
182 if (c->count > 1) {
183 t = exif_mem_realloc (c->priv->mem, c->entries,
184 sizeof(ExifEntry*) * (c->count - 1));
185 if (!t) {
186 return;
187 }
188 c->entries = t;
189 c->count--;
190 if (i != c->count) { /* we deallocated the last slot already */
191 memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
192 t[c->count-1] = temp;
193 }
194 } else {
195 exif_mem_free (c->priv->mem, c->entries);
196 c->entries = NULL;
197 c->count = 0;
198 }
199 e->parent = NULL;
201}
202
203ExifEntry *
205{
206 unsigned int i;
207
208 if (!content)
209 return (NULL);
210
211 for (i = 0; i < content->count; i++)
212 if (content->entries[i]->tag == tag)
213 return (content->entries[i]);
214 return (NULL);
215}
216
217void
219 ExifContentForeachEntryFunc func, void *data)
220{
221 unsigned int i;
222
223 if (!content || !func)
224 return;
225
226 for (i = 0; i < content->count; i++)
227 func (content->entries[i], data);
228}
229
230void
232{
233 if (!content || !content->priv || !log || content->priv->log == log)
234 return;
235
236 if (content->priv->log) exif_log_unref (content->priv->log);
237 content->priv->log = log;
238 exif_log_ref (log);
239}
240
243{
244 if (!c || !c->parent) return EXIF_IFD_COUNT;
245
246 return
247 ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
248 ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
249 ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
250 ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
251 ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
253}
254
255static void
256fix_func (ExifEntry *e, void *UNUSED(data))
257{
258 exif_entry_fix (e);
259}
260
267static void
269{
271 ExifContent *c = e->parent;
273 ExifTag t = e->tag;
274
277 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
278 "Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
279 "removed.", t, exif_ifd_get_name (ifd));
281 }
282
283}
284
285void
287{
289 ExifDataType dt;
290 ExifEntry *e;
291 unsigned int i, num;
292
293 if (!c)
294 return;
295
297
298 /*
299 * First of all, fix all existing entries.
300 */
302
303 /*
304 * Go through each tag and if it's not recorded, remove it. If one
305 * is removed, exif_content_foreach_entry() will skip the next entry,
306 * so if this happens do the loop again from the beginning to ensure
307 * they're all checked. This could be avoided if we stop relying on
308 * exif_content_foreach_entry but loop intelligently here.
309 */
310 do {
311 num = c->count;
313 } while (num != c->count);
314
315 /*
316 * Then check for non-existing mandatory tags and create them if needed
317 */
318 num = exif_tag_table_count();
319 for (i = 0; i < num; ++i) {
320 const ExifTag t = exif_tag_table_get_tag (i);
323 if (exif_content_get_entry (c, t))
324 /* This tag already exists */
325 continue;
326 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
327 "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
329 e = exif_entry_new ();
333 }
334 }
335}
void exif_content_remove_entry(ExifContent *c, ExifEntry *e)
Remove an EXIF tag from an IFD.
ExifIfd exif_content_get_ifd(ExifContent *c)
Return the IFD number in which the given ExifContent is found.
void exif_content_fix(ExifContent *c)
Fix the IFD to bring it into specification.
static void fix_func(ExifEntry *e, void *UNUSED(data))
void exif_content_ref(ExifContent *content)
Increase reference counter for ExifContent.
ExifContent * exif_content_new_mem(ExifMem *mem)
Reserve memory for and initialize new ExifContent using the specified memory allocator.
ExifEntry * exif_content_get_entry(ExifContent *content, ExifTag tag)
Return the ExifEntry in this IFD corresponding to the given tag.
void exif_content_unref(ExifContent *content)
Decrease reference counter for ExifContent.
void exif_content_add_entry(ExifContent *c, ExifEntry *entry)
Add an EXIF tag to an IFD.
void exif_content_dump(ExifContent *content, unsigned int indent)
Dump contents of the IFD to stdout.
void exif_content_log(ExifContent *content, ExifLog *log)
Set the log message object for this IFD.
static void remove_not_recorded(ExifEntry *e, void *UNUSED(data))
Check if this entry is unknown and if so, delete it.
ExifContent * exif_content_new(void)
Reserve memory for and initialize a new ExifContent.
void exif_content_foreach_entry(ExifContent *content, ExifContentForeachEntryFunc func, void *data)
Executes function on each EXIF tag in this IFD in turn.
void exif_content_free(ExifContent *content)
Actually free the ExifContent.
Handling EXIF IFDs.
void(* ExifContentForeachEntryFunc)(ExifEntry *, void *user_data)
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:1369
ExifEntry * exif_entry_new(void)
Reserve memory for and initialize a new ExifEntry.
Definition exif-entry.c:113
void exif_entry_unref(ExifEntry *e)
Decrease reference counter for ExifEntry.
Definition exif-entry.c:149
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:207
void exif_entry_initialize(ExifEntry *e, ExifTag tag)
Initialize an empty ExifEntry with default data in the correct format for the given tag.
void exif_entry_dump(ExifEntry *e, unsigned int indent)
Dump text representation of ExifEntry to stdout.
Definition exif-entry.c:600
void exif_entry_ref(ExifEntry *e)
Increase reference counter for ExifEntry.
Definition exif-entry.c:141
#define exif_entry_get_ifd(e)
Return the IFD number of the given ExifEntry.
Definition exif-entry.h:182
ExifIfd ifd
Definition exif-ifd.c:30
const char * exif_ifd_get_name(ExifIfd ifd)
Return a textual name of the given IFD.
Definition exif-ifd.c:42
ExifIfd
Possible EXIF Image File Directories.
Definition exif-ifd.h:31
@ EXIF_IFD_GPS
Definition exif-ifd.h:35
@ EXIF_IFD_INTEROPERABILITY
Definition exif-ifd.h:36
@ EXIF_IFD_EXIF
Definition exif-ifd.h:34
@ EXIF_IFD_1
Definition exif-ifd.h:33
@ EXIF_IFD_COUNT
Not a real value, just (max_value + 1).
Definition exif-ifd.h:37
@ EXIF_IFD_0
Definition exif-ifd.h:32
void exif_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format,...)
Definition exif-log.c:137
void exif_log_unref(ExifLog *log)
Definition exif-log.c:106
void exif_log_ref(ExifLog *log)
Definition exif-log.c:99
@ EXIF_LOG_CODE_DEBUG
Definition exif-log.h:58
void exif_mem_free(ExifMem *mem, void *d)
Definition exif-mem.c:91
void exif_mem_unref(ExifMem *mem)
Unrefcount an ExifMem.
Definition exif-mem.c:83
void * exif_mem_alloc(ExifMem *mem, ExifLong ds)
Definition exif-mem.c:101
void * exif_mem_realloc(ExifMem *mem, void *d, ExifLong ds)
Definition exif-mem.c:111
ExifMem * exif_mem_new_default(void)
Create a new ExifMem with default values for your convenience.
Definition exif-mem.c:117
void exif_mem_ref(ExifMem *mem)
Refcount an ExifMem.
Definition exif-mem.c:76
System specific definitions, not for installation!
#define UNUSED(param)
Definition exif-system.h:31
ExifTag exif_tag_table_get_tag(unsigned int n)
Definition exif-tag.c:984
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:1042
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:977
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:1260
const char * exif_tag_get_name(ExifTag tag)
Definition exif-tag.c:1151
ExifTag
EXIF tags.
Definition exif-tag.h:36
@ EXIF_SUPPORT_LEVEL_NOT_RECORDED
This tag is not allowed in the given IFD.
Definition exif-tag.h:215
@ EXIF_SUPPORT_LEVEL_MANDATORY
This tag is mandatory in the given IFD.
Definition exif-tag.h:218
uint32_t ExifLong
EXIF Unsigned Long data type.
Definition exif-utils.h:56
#define MIN(a, b)
Definition exif-utils.h:182
MnoteAppleTag tag
unsigned int ref_count
unsigned int count
ExifContentPrivate * priv
ExifData * parent
Data containing this content.
ExifEntry ** entries
Data found in one EXIF tag.
Definition exif-entry.h:45
ExifContent * parent
ExifContent containing this entry.
Definition exif-entry.h:67
ExifTag tag
EXIF tag for this entry.
Definition exif-entry.h:47

libexif Generated by doxygen