00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <libexif/exif-content.h>
00024 #include <libexif/exif-system.h>
00025
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029
00030
00031
00032
00033
00034 struct _ExifContentPrivate
00035 {
00036 unsigned int ref_count;
00037
00038 ExifMem *mem;
00039 ExifLog *log;
00040 };
00041
00042 ExifContent *
00043 exif_content_new (void)
00044 {
00045 ExifMem *mem = exif_mem_new_default ();
00046 ExifContent *content = exif_content_new_mem (mem);
00047
00048 exif_mem_unref (mem);
00049
00050 return content;
00051 }
00052
00053 ExifContent *
00054 exif_content_new_mem (ExifMem *mem)
00055 {
00056 ExifContent *content;
00057
00058 if (!mem) return NULL;
00059
00060 content = exif_mem_alloc (mem, (ExifLong) sizeof (ExifContent));
00061 if (!content)
00062 return NULL;
00063 content->priv = exif_mem_alloc (mem,
00064 (ExifLong) sizeof (ExifContentPrivate));
00065 if (!content->priv) {
00066 exif_mem_free (mem, content);
00067 return NULL;
00068 }
00069
00070 content->priv->ref_count = 1;
00071
00072 content->priv->mem = mem;
00073 exif_mem_ref (mem);
00074
00075 return content;
00076 }
00077
00078 void
00079 exif_content_ref (ExifContent *content)
00080 {
00081 content->priv->ref_count++;
00082 }
00083
00084 void
00085 exif_content_unref (ExifContent *content)
00086 {
00087 content->priv->ref_count--;
00088 if (!content->priv->ref_count)
00089 exif_content_free (content);
00090 }
00091
00092 void
00093 exif_content_free (ExifContent *content)
00094 {
00095 ExifMem *mem = (content && content->priv) ? content->priv->mem : NULL;
00096 unsigned int i;
00097
00098 if (!content) return;
00099
00100 for (i = 0; i < content->count; i++)
00101 exif_entry_unref (content->entries[i]);
00102 exif_mem_free (mem, content->entries);
00103
00104 if (content->priv) {
00105 exif_log_unref (content->priv->log);
00106 }
00107
00108 exif_mem_free (mem, content->priv);
00109 exif_mem_free (mem, content);
00110 exif_mem_unref (mem);
00111 }
00112
00113 void
00114 exif_content_dump (ExifContent *content, unsigned int indent)
00115 {
00116 char buf[1024];
00117 unsigned int i;
00118
00119 for (i = 0; i < 2 * indent; i++)
00120 buf[i] = ' ';
00121 buf[i] = '\0';
00122
00123 if (!content)
00124 return;
00125
00126 printf ("%sDumping exif content (%u entries)...\n", buf,
00127 content->count);
00128 for (i = 0; i < content->count; i++)
00129 exif_entry_dump (content->entries[i], indent + 1);
00130 }
00131
00132 void
00133 exif_content_add_entry (ExifContent *c, ExifEntry *entry)
00134 {
00135 ExifEntry **entries;
00136 if (!c || !c->priv || !entry || entry->parent) return;
00137
00138
00139 if (exif_content_get_entry (c, entry->tag)) {
00140 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "ExifContent",
00141 "An attempt has been made to add "
00142 "the tag '%s' twice to an IFD. This is against "
00143 "specification.", exif_tag_get_name (entry->tag));
00144 return;
00145 }
00146
00147 entries = exif_mem_realloc (c->priv->mem,
00148 c->entries, sizeof (ExifEntry*) * (c->count + 1));
00149 if (!entries) return;
00150 entry->parent = c;
00151 entries[c->count++] = entry;
00152 c->entries = entries;
00153 exif_entry_ref (entry);
00154 }
00155
00156 void
00157 exif_content_remove_entry (ExifContent *c, ExifEntry *e)
00158 {
00159 unsigned int i;
00160 ExifEntry **t, *temp;
00161
00162 if (!c || !c->priv || !e || (e->parent != c)) return;
00163
00164
00165 for (i = 0; i < c->count; i++)
00166 if (c->entries[i] == e)
00167 break;
00168
00169 if (i == c->count)
00170 return;
00171
00172
00173 temp = c->entries[c->count-1];
00174 if (c->count > 1) {
00175 t = exif_mem_realloc (c->priv->mem, c->entries,
00176 sizeof(ExifEntry*) * (c->count - 1));
00177 if (!t) {
00178 return;
00179 }
00180 c->entries = t;
00181 c->count--;
00182 if (i != c->count) {
00183 memmove (&t[i], &t[i + 1], sizeof (ExifEntry*) * (c->count - i - 1));
00184 t[c->count-1] = temp;
00185 }
00186 } else {
00187 exif_mem_free (c->priv->mem, c->entries);
00188 c->entries = NULL;
00189 c->count = 0;
00190 }
00191 e->parent = NULL;
00192 exif_entry_unref (e);
00193 }
00194
00195 ExifEntry *
00196 exif_content_get_entry (ExifContent *content, ExifTag tag)
00197 {
00198 unsigned int i;
00199
00200 if (!content)
00201 return (NULL);
00202
00203 for (i = 0; i < content->count; i++)
00204 if (content->entries[i]->tag == tag)
00205 return (content->entries[i]);
00206 return (NULL);
00207 }
00208
00209 void
00210 exif_content_foreach_entry (ExifContent *content,
00211 ExifContentForeachEntryFunc func, void *data)
00212 {
00213 unsigned int i;
00214
00215 if (!content || !func)
00216 return;
00217
00218 for (i = 0; i < content->count; i++)
00219 func (content->entries[i], data);
00220 }
00221
00222 void
00223 exif_content_log (ExifContent *content, ExifLog *log)
00224 {
00225 if (!content || !content->priv || !log || content->priv->log == log)
00226 return;
00227
00228 if (content->priv->log) exif_log_unref (content->priv->log);
00229 content->priv->log = log;
00230 exif_log_ref (log);
00231 }
00232
00233 ExifIfd
00234 exif_content_get_ifd (ExifContent *c)
00235 {
00236 if (!c || !c->parent) return EXIF_IFD_COUNT;
00237
00238 return
00239 ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
00240 ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
00241 ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
00242 ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
00243 ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
00244 EXIF_IFD_COUNT;
00245 }
00246
00247 static void
00248 fix_func (ExifEntry *e, void *UNUSED(data))
00249 {
00250 exif_entry_fix (e);
00251 }
00252
00259 static void
00260 remove_not_recorded (ExifEntry *e, void *UNUSED(data))
00261 {
00262 ExifIfd ifd = exif_entry_get_ifd(e) ;
00263 ExifContent *c = e->parent;
00264 ExifDataType dt = exif_data_get_data_type (c->parent);
00265 ExifTag t = e->tag;
00266
00267 if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
00268 EXIF_SUPPORT_LEVEL_NOT_RECORDED) {
00269 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
00270 "Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
00271 "removed.", t, exif_ifd_get_name (ifd));
00272 exif_content_remove_entry (c, e);
00273 }
00274
00275 }
00276
00277 void
00278 exif_content_fix (ExifContent *c)
00279 {
00280 ExifIfd ifd = exif_content_get_ifd (c);
00281 ExifDataType dt;
00282 ExifEntry *e;
00283 unsigned int i, num;
00284
00285 if (!c)
00286 return;
00287
00288 dt = exif_data_get_data_type (c->parent);
00289
00290
00291
00292
00293 exif_content_foreach_entry (c, fix_func, NULL);
00294
00295
00296
00297
00298
00299
00300
00301
00302 do {
00303 num = c->count;
00304 exif_content_foreach_entry (c, remove_not_recorded, NULL);
00305 } while (num != c->count);
00306
00307
00308
00309
00310 num = exif_tag_table_count();
00311 for (i = 0; i < num; ++i) {
00312 const ExifTag t = exif_tag_table_get_tag (i);
00313 if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
00314 EXIF_SUPPORT_LEVEL_MANDATORY) {
00315 if (exif_content_get_entry (c, t))
00316
00317 continue;
00318 exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
00319 "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
00320 exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd));
00321 e = exif_entry_new ();
00322 exif_content_add_entry (c, e);
00323 exif_entry_initialize (e, t);
00324 exif_entry_unref (e);
00325 }
00326 }
00327 }