OLD | NEW |
(Empty) | |
| 1 /* exif-data.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-mnote-data.h> |
| 24 #include <libexif/exif-data.h> |
| 25 #include <libexif/exif-ifd.h> |
| 26 #include <libexif/exif-mnote-data-priv.h> |
| 27 #include <libexif/exif-utils.h> |
| 28 #include <libexif/exif-loader.h> |
| 29 #include <libexif/exif-log.h> |
| 30 #include <libexif/i18n.h> |
| 31 #include <libexif/exif-system.h> |
| 32 |
| 33 #include <libexif/canon/exif-mnote-data-canon.h> |
| 34 #include <libexif/fuji/exif-mnote-data-fuji.h> |
| 35 #include <libexif/olympus/exif-mnote-data-olympus.h> |
| 36 #include <libexif/pentax/exif-mnote-data-pentax.h> |
| 37 |
| 38 #include <stdlib.h> |
| 39 #include <stdio.h> |
| 40 #include <string.h> |
| 41 |
| 42 #undef JPEG_MARKER_SOI |
| 43 #define JPEG_MARKER_SOI 0xd8 |
| 44 #undef JPEG_MARKER_APP0 |
| 45 #define JPEG_MARKER_APP0 0xe0 |
| 46 #undef JPEG_MARKER_APP1 |
| 47 #define JPEG_MARKER_APP1 0xe1 |
| 48 |
| 49 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; |
| 50 |
| 51 struct _ExifDataPrivate |
| 52 { |
| 53 ExifByteOrder order; |
| 54 |
| 55 ExifMnoteData *md; |
| 56 |
| 57 ExifLog *log; |
| 58 ExifMem *mem; |
| 59 |
| 60 unsigned int ref_count; |
| 61 |
| 62 /* Temporarily used while loading data */ |
| 63 unsigned int offset_mnote; |
| 64 |
| 65 ExifDataOption options; |
| 66 ExifDataType data_type; |
| 67 }; |
| 68 |
| 69 static void * |
| 70 exif_data_alloc (ExifData *data, unsigned int i) |
| 71 { |
| 72 void *d; |
| 73 |
| 74 if (!data || !i) |
| 75 return NULL; |
| 76 |
| 77 d = exif_mem_alloc (data->priv->mem, i); |
| 78 if (d) |
| 79 return d; |
| 80 |
| 81 EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i); |
| 82 return NULL; |
| 83 } |
| 84 |
| 85 ExifMnoteData * |
| 86 exif_data_get_mnote_data (ExifData *d) |
| 87 { |
| 88 return (d && d->priv) ? d->priv->md : NULL; |
| 89 } |
| 90 |
| 91 ExifData * |
| 92 exif_data_new (void) |
| 93 { |
| 94 ExifMem *mem = exif_mem_new_default (); |
| 95 ExifData *d = exif_data_new_mem (mem); |
| 96 |
| 97 exif_mem_unref (mem); |
| 98 |
| 99 return d; |
| 100 } |
| 101 |
| 102 ExifData * |
| 103 exif_data_new_mem (ExifMem *mem) |
| 104 { |
| 105 ExifData *data; |
| 106 unsigned int i; |
| 107 |
| 108 if (!mem) |
| 109 return NULL; |
| 110 |
| 111 data = exif_mem_alloc (mem, sizeof (ExifData)); |
| 112 if (!data) |
| 113 return (NULL); |
| 114 data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate)); |
| 115 if (!data->priv) { |
| 116 exif_mem_free (mem, data); |
| 117 return (NULL); |
| 118 } |
| 119 data->priv->ref_count = 1; |
| 120 |
| 121 data->priv->mem = mem; |
| 122 exif_mem_ref (mem); |
| 123 |
| 124 for (i = 0; i < EXIF_IFD_COUNT; i++) { |
| 125 data->ifd[i] = exif_content_new_mem (data->priv->mem); |
| 126 if (!data->ifd[i]) { |
| 127 exif_data_free (data); |
| 128 return (NULL); |
| 129 } |
| 130 data->ifd[i]->parent = data; |
| 131 } |
| 132 |
| 133 /* Default options */ |
| 134 #ifndef NO_VERBOSE_TAG_STRINGS |
| 135 /* |
| 136 * When the tag list is compiled away, setting this option prevents |
| 137 * any tags from being loaded |
| 138 */ |
| 139 exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS); |
| 140 #endif |
| 141 exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); |
| 142 |
| 143 /* Default data type: none */ |
| 144 exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT); |
| 145 |
| 146 return (data); |
| 147 } |
| 148 |
| 149 ExifData * |
| 150 exif_data_new_from_data (const unsigned char *data, unsigned int size) |
| 151 { |
| 152 ExifData *edata; |
| 153 |
| 154 edata = exif_data_new (); |
| 155 exif_data_load_data (edata, data, size); |
| 156 return (edata); |
| 157 } |
| 158 |
| 159 static int |
| 160 exif_data_load_data_entry (ExifData *data, ExifEntry *entry, |
| 161 const unsigned char *d, |
| 162 unsigned int size, unsigned int offset) |
| 163 { |
| 164 unsigned int s, doff; |
| 165 |
| 166 entry->tag = exif_get_short (d + offset + 0, data->priv->order); |
| 167 entry->format = exif_get_short (d + offset + 2, data->priv->order); |
| 168 entry->components = exif_get_long (d + offset + 4, data->priv->order); |
| 169 |
| 170 /* FIXME: should use exif_tag_get_name_in_ifd here but entry->parent |
| 171 * has not been set yet |
| 172 */ |
| 173 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 174 "Loading entry 0x%x ('%s')...", entry->tag, |
| 175 exif_tag_get_name (entry->tag)); |
| 176 |
| 177 /* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff } |
| 178 * -> { 0x000000000 .. 0x7fffffff8 } */ |
| 179 s = exif_format_get_size(entry->format) * entry->components; |
| 180 if ((s < entry->components) || (s == 0)){ |
| 181 return 0; |
| 182 } |
| 183 |
| 184 /* |
| 185 * Size? If bigger than 4 bytes, the actual data is not |
| 186 * in the entry but somewhere else (offset). |
| 187 */ |
| 188 if (s > 4) |
| 189 doff = exif_get_long (d + offset + 8, data->priv->order); |
| 190 else |
| 191 doff = offset + 8; |
| 192 |
| 193 /* Sanity checks */ |
| 194 if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) { |
| 195 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 196 "Tag data past end of buffer (%u > %u)", doff+
s, size); |
| 197 return 0; |
| 198 } |
| 199 |
| 200 entry->data = exif_data_alloc (data, s); |
| 201 if (entry->data) { |
| 202 entry->size = s; |
| 203 memcpy (entry->data, d + doff, s); |
| 204 } else { |
| 205 /* FIXME: What do our callers do if (entry->data == NULL)? */ |
| 206 EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", s); |
| 207 } |
| 208 |
| 209 /* If this is the MakerNote, remember the offset */ |
| 210 if (entry->tag == EXIF_TAG_MAKER_NOTE) { |
| 211 if (!entry->data) { |
| 212 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifDat
a", |
| 213 "MakerNote found with empty data"); |
| 214 } else if (entry->size > 6) { |
| 215 exif_log (data->priv->log, |
| 216 EXIF_LOG_CODE_DEBUG, "ExifData", |
| 217 "MakerNote found (%02x %02x %02x
%02x " |
| 218 "%02x %02x %02x...).", |
| 219 entry->data[0], entry->data[1], e
ntry->data[2], |
| 220 entry->data[3], entry->data[4], e
ntry->data[5], |
| 221 entry->data[6]); |
| 222 } |
| 223 data->priv->offset_mnote = doff; |
| 224 } |
| 225 return 1; |
| 226 } |
| 227 |
| 228 static void |
| 229 exif_data_save_data_entry (ExifData *data, ExifEntry *e, |
| 230 unsigned char **d, unsigned int *ds, |
| 231 unsigned int offset) |
| 232 { |
| 233 unsigned int doff, s; |
| 234 unsigned int ts; |
| 235 |
| 236 if (!data || !data->priv) |
| 237 return; |
| 238 |
| 239 /* |
| 240 * Each entry is 12 bytes long. The memory for the entry has |
| 241 * already been allocated. |
| 242 */ |
| 243 exif_set_short (*d + 6 + offset + 0, |
| 244 data->priv->order, (ExifShort) e->tag); |
| 245 exif_set_short (*d + 6 + offset + 2, |
| 246 data->priv->order, (ExifShort) e->format); |
| 247 |
| 248 if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) { |
| 249 /* If this is the maker note tag, update it. */ |
| 250 if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { |
| 251 /* TODO: this is using the wrong ExifMem to free e->data
*/ |
| 252 exif_mem_free (data->priv->mem, e->data); |
| 253 e->data = NULL; |
| 254 e->size = 0; |
| 255 exif_mnote_data_set_offset (data->priv->md, *ds - 6); |
| 256 exif_mnote_data_save (data->priv->md, &e->data, &e->size
); |
| 257 e->components = e->size; |
| 258 } |
| 259 } |
| 260 |
| 261 exif_set_long (*d + 6 + offset + 4, |
| 262 data->priv->order, e->components); |
| 263 |
| 264 /* |
| 265 * Size? If bigger than 4 bytes, the actual data is not in |
| 266 * the entry but somewhere else. |
| 267 */ |
| 268 s = exif_format_get_size (e->format) * e->components; |
| 269 if (s > 4) { |
| 270 unsigned char *t; |
| 271 doff = *ds - 6; |
| 272 ts = *ds + s; |
| 273 |
| 274 /* |
| 275 * According to the TIFF specification, |
| 276 * the offset must be an even number. If we need to introduce |
| 277 * a padding byte, we set it to 0. |
| 278 */ |
| 279 if (s & 1) |
| 280 ts++; |
| 281 t = exif_mem_realloc (data->priv->mem, *d, ts); |
| 282 if (!t) { |
| 283 EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); |
| 284 return; |
| 285 } |
| 286 *d = t; |
| 287 *ds = ts; |
| 288 exif_set_long (*d + 6 + offset + 8, data->priv->order, doff); |
| 289 if (s & 1) |
| 290 *(*d + *ds - 1) = '\0'; |
| 291 |
| 292 } else |
| 293 doff = offset + 8; |
| 294 |
| 295 /* Write the data. Fill unneeded bytes with 0. Do not crash with |
| 296 * e->data is NULL */ |
| 297 if (e->data) { |
| 298 memcpy (*d + 6 + doff, e->data, s); |
| 299 } else { |
| 300 memset (*d + 6 + doff, 0, s); |
| 301 } |
| 302 if (s < 4) |
| 303 memset (*d + 6 + doff + s, 0, (4 - s)); |
| 304 } |
| 305 |
| 306 static void |
| 307 exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d, |
| 308 unsigned int ds, ExifLong o, ExifLong s) |
| 309 { |
| 310 /* Sanity checks */ |
| 311 if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) { |
| 312 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 313 "Bogus thumbnail offset (%u) or size (%u).", |
| 314 o, s); |
| 315 return; |
| 316 } |
| 317 |
| 318 if (data->data) |
| 319 exif_mem_free (data->priv->mem, data->data); |
| 320 if (!(data->data = exif_data_alloc (data, s))) { |
| 321 EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", s); |
| 322 data->size = 0; |
| 323 return; |
| 324 } |
| 325 data->size = s; |
| 326 memcpy (data->data, d + o, s); |
| 327 } |
| 328 |
| 329 #undef CHECK_REC |
| 330 #define CHECK_REC(i) \ |
| 331 if ((i) == ifd) { \ |
| 332 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \ |
| 333 "ExifData", "Recursive entry in IFD " \ |
| 334 "'%s' detected. Skipping...", \ |
| 335 exif_ifd_get_name (i)); \ |
| 336 break; \ |
| 337 } \ |
| 338 if (data->ifd[(i)]->count) { \ |
| 339 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \ |
| 340 "ExifData", "Attempt to load IFD " \ |
| 341 "'%s' multiple times detected. " \ |
| 342 "Skipping...", \ |
| 343 exif_ifd_get_name (i)); \ |
| 344 break; \ |
| 345 } |
| 346 |
| 347 /*! Load data for an IFD. |
| 348 * |
| 349 * \param[in,out] data #ExifData |
| 350 * \param[in] ifd IFD to load |
| 351 * \param[in] d pointer to buffer containing raw IFD data |
| 352 * \param[in] ds size of raw data in buffer at \c d |
| 353 * \param[in] offset offset into buffer at \c d at which IFD starts |
| 354 * \param[in] recursion_depth number of times this function has been |
| 355 * recursively called without returning |
| 356 */ |
| 357 static void |
| 358 exif_data_load_data_content (ExifData *data, ExifIfd ifd, |
| 359 const unsigned char *d, |
| 360 unsigned int ds, unsigned int offset, unsigned int
recursion_depth) |
| 361 { |
| 362 ExifLong o, thumbnail_offset = 0, thumbnail_length = 0; |
| 363 ExifShort n; |
| 364 ExifEntry *entry; |
| 365 unsigned int i; |
| 366 ExifTag tag; |
| 367 |
| 368 if (!data || !data->priv) |
| 369 return; |
| 370 |
| 371 /* check for valid ExifIfd enum range */ |
| 372 if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT)) |
| 373 return; |
| 374 |
| 375 if (recursion_depth > 30) { |
| 376 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData
", |
| 377 "Deep recursion detected!"); |
| 378 return; |
| 379 } |
| 380 |
| 381 /* Read the number of entries */ |
| 382 if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) { |
| 383 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData
", |
| 384 "Tag data past end of buffer (%u > %u)", offset+2, ds)
; |
| 385 return; |
| 386 } |
| 387 n = exif_get_short (d + offset, data->priv->order); |
| 388 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 389 "Loading %hu entries...", n); |
| 390 offset += 2; |
| 391 |
| 392 /* Check if we have enough data. */ |
| 393 if (offset + 12 * n > ds) { |
| 394 n = (ds - offset) / 12; |
| 395 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 396 "Short data; only loading %hu entries...", n); |
| 397 } |
| 398 |
| 399 for (i = 0; i < n; i++) { |
| 400 |
| 401 tag = exif_get_short (d + offset + 12 * i, data->priv->order); |
| 402 switch (tag) { |
| 403 case EXIF_TAG_EXIF_IFD_POINTER: |
| 404 case EXIF_TAG_GPS_INFO_IFD_POINTER: |
| 405 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: |
| 406 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: |
| 407 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: |
| 408 o = exif_get_long (d + offset + 12 * i + 8, |
| 409 data->priv->order); |
| 410 /* FIXME: IFD_POINTER tags aren't marked as being in a |
| 411 * specific IFD, so exif_tag_get_name_in_ifd won't work |
| 412 */ |
| 413 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifDat
a", |
| 414 "Sub-IFD entry 0x%x ('%s') at %u.", tag, |
| 415 exif_tag_get_name(tag), o); |
| 416 switch (tag) { |
| 417 case EXIF_TAG_EXIF_IFD_POINTER: |
| 418 CHECK_REC (EXIF_IFD_EXIF); |
| 419 exif_data_load_data_content (data, EXIF_IFD_EXIF
, d, ds, o, recursion_depth + 1); |
| 420 break; |
| 421 case EXIF_TAG_GPS_INFO_IFD_POINTER: |
| 422 CHECK_REC (EXIF_IFD_GPS); |
| 423 exif_data_load_data_content (data, EXIF_IFD_GPS,
d, ds, o, recursion_depth + 1); |
| 424 break; |
| 425 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: |
| 426 CHECK_REC (EXIF_IFD_INTEROPERABILITY); |
| 427 exif_data_load_data_content (data, EXIF_IFD_INTE
ROPERABILITY, d, ds, o, recursion_depth + 1); |
| 428 break; |
| 429 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: |
| 430 thumbnail_offset = o; |
| 431 if (thumbnail_offset && thumbnail_length) |
| 432 exif_data_load_data_thumbnail (data, d, |
| 433 ds, thumb
nail_offset, |
| 434 thumbnail
_length); |
| 435 break; |
| 436 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: |
| 437 thumbnail_length = o; |
| 438 if (thumbnail_offset && thumbnail_length) |
| 439 exif_data_load_data_thumbnail (data, d, |
| 440 ds, thumb
nail_offset, |
| 441 thumbnail
_length); |
| 442 break; |
| 443 default: |
| 444 return; |
| 445 } |
| 446 break; |
| 447 default: |
| 448 |
| 449 /* |
| 450 * If we don't know the tag, don't fail. It could be tha
t new |
| 451 * versions of the standard have defined additional tags
. Note that |
| 452 * 0 is a valid tag in the GPS IFD. |
| 453 */ |
| 454 if (!exif_tag_get_name_in_ifd (tag, ifd)) { |
| 455 |
| 456 /* |
| 457 * Special case: Tag and format 0. That's agains
t specification |
| 458 * (at least up to 2.2). But Photoshop writes it
anyways. |
| 459 */ |
| 460 if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)
) { |
| 461 exif_log (data->priv->log, EXIF_LOG_CODE
_DEBUG, "ExifData", |
| 462 "Skipping empty entry at posit
ion %u in '%s'.", i, |
| 463 exif_ifd_get_name (ifd)); |
| 464 break; |
| 465 } |
| 466 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG,
"ExifData", |
| 467 "Unknown tag 0x%04x (entry %u in '%s')
. Please report this tag " |
| 468 "to <libexif-devel@lists.sourceforge.n
et>.", tag, i, |
| 469 exif_ifd_get_name (ifd)); |
| 470 if (data->priv->options & EXIF_DATA_OPTION_IGNOR
E_UNKNOWN_TAGS) |
| 471 break; |
| 472 } |
| 473 entry = exif_entry_new_mem (data->priv->mem); |
| 474 if (exif_data_load_data_entry (data, entry, d, ds, |
| 475 offset + 12 * i)) |
| 476 exif_content_add_entry (data->ifd[ifd], entry); |
| 477 exif_entry_unref (entry); |
| 478 break; |
| 479 } |
| 480 } |
| 481 } |
| 482 |
| 483 static int |
| 484 cmp_func (const unsigned char *p1, const unsigned char *p2, ExifByteOrder o) |
| 485 { |
| 486 ExifShort tag1 = exif_get_short (p1, o); |
| 487 ExifShort tag2 = exif_get_short (p2, o); |
| 488 |
| 489 return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0; |
| 490 } |
| 491 |
| 492 static int |
| 493 cmp_func_intel (const void *elem1, const void *elem2) |
| 494 { |
| 495 return cmp_func ((const unsigned char *) elem1, |
| 496 (const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL); |
| 497 } |
| 498 |
| 499 static int |
| 500 cmp_func_motorola (const void *elem1, const void *elem2) |
| 501 { |
| 502 return cmp_func ((const unsigned char *) elem1, |
| 503 (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA
); |
| 504 } |
| 505 |
| 506 static void |
| 507 exif_data_save_data_content (ExifData *data, ExifContent *ifd, |
| 508 unsigned char **d, unsigned int *ds, |
| 509 unsigned int offset) |
| 510 { |
| 511 unsigned int j, n_ptr = 0, n_thumb = 0; |
| 512 ExifIfd i; |
| 513 unsigned char *t; |
| 514 unsigned int ts; |
| 515 |
| 516 if (!data || !data->priv || !ifd || !d || !ds) |
| 517 return; |
| 518 |
| 519 for (i = 0; i < EXIF_IFD_COUNT; i++) |
| 520 if (ifd == data->ifd[i]) |
| 521 break; |
| 522 if (i == EXIF_IFD_COUNT) |
| 523 return; /* error */ |
| 524 |
| 525 /* |
| 526 * Check if we need some extra entries for pointers or the thumbnail. |
| 527 */ |
| 528 switch (i) { |
| 529 case EXIF_IFD_0: |
| 530 |
| 531 /* |
| 532 * The pointer to IFD_EXIF is in IFD_0. The pointer to |
| 533 * IFD_INTEROPERABILITY is in IFD_EXIF. |
| 534 */ |
| 535 if (data->ifd[EXIF_IFD_EXIF]->count || |
| 536 data->ifd[EXIF_IFD_INTEROPERABILITY]->count) |
| 537 n_ptr++; |
| 538 |
| 539 /* The pointer to IFD_GPS is in IFD_0. */ |
| 540 if (data->ifd[EXIF_IFD_GPS]->count) |
| 541 n_ptr++; |
| 542 |
| 543 break; |
| 544 case EXIF_IFD_1: |
| 545 if (data->size) |
| 546 n_thumb = 2; |
| 547 break; |
| 548 case EXIF_IFD_EXIF: |
| 549 if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) |
| 550 n_ptr++; |
| 551 default: |
| 552 break; |
| 553 } |
| 554 |
| 555 /* |
| 556 * Allocate enough memory for all entries |
| 557 * and the number of entries. |
| 558 */ |
| 559 ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4); |
| 560 t = exif_mem_realloc (data->priv->mem, *d, ts); |
| 561 if (!t) { |
| 562 EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); |
| 563 return; |
| 564 } |
| 565 *d = t; |
| 566 *ds = ts; |
| 567 |
| 568 /* Save the number of entries */ |
| 569 exif_set_short (*d + 6 + offset, data->priv->order, |
| 570 (ExifShort) (ifd->count + n_ptr + n_thumb)); |
| 571 offset += 2; |
| 572 |
| 573 /* |
| 574 * Save each entry. Make sure that no memcpys from NULL pointers are |
| 575 * performed |
| 576 */ |
| 577 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 578 "Saving %i entries (IFD '%s', offset: %i)...", |
| 579 ifd->count, exif_ifd_get_name (i), offset); |
| 580 for (j = 0; j < ifd->count; j++) { |
| 581 if (ifd->entries[j]) { |
| 582 exif_data_save_data_entry (data, ifd->entries[j], d, ds, |
| 583 offset + 12 * j); |
| 584 } |
| 585 } |
| 586 |
| 587 offset += 12 * ifd->count; |
| 588 |
| 589 /* Now save special entries. */ |
| 590 switch (i) { |
| 591 case EXIF_IFD_0: |
| 592 |
| 593 /* |
| 594 * The pointer to IFD_EXIF is in IFD_0. |
| 595 * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF, |
| 596 * therefore, if IFD_INTEROPERABILITY is not empty, we need |
| 597 * IFD_EXIF even if latter is empty. |
| 598 */ |
| 599 if (data->ifd[EXIF_IFD_EXIF]->count || |
| 600 data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { |
| 601 exif_set_short (*d + 6 + offset + 0, data->priv->order, |
| 602 EXIF_TAG_EXIF_IFD_POINTER); |
| 603 exif_set_short (*d + 6 + offset + 2, data->priv->order, |
| 604 EXIF_FORMAT_LONG); |
| 605 exif_set_long (*d + 6 + offset + 4, data->priv->order, |
| 606 1); |
| 607 exif_set_long (*d + 6 + offset + 8, data->priv->order, |
| 608 *ds - 6); |
| 609 exif_data_save_data_content (data, |
| 610 data->ifd[EXIF_IFD_EXIF], d
, ds, *ds - 6); |
| 611 offset += 12; |
| 612 } |
| 613 |
| 614 /* The pointer to IFD_GPS is in IFD_0, too. */ |
| 615 if (data->ifd[EXIF_IFD_GPS]->count) { |
| 616 exif_set_short (*d + 6 + offset + 0, data->priv->order, |
| 617 EXIF_TAG_GPS_INFO_IFD_POINTER); |
| 618 exif_set_short (*d + 6 + offset + 2, data->priv->order, |
| 619 EXIF_FORMAT_LONG); |
| 620 exif_set_long (*d + 6 + offset + 4, data->priv->order, |
| 621 1); |
| 622 exif_set_long (*d + 6 + offset + 8, data->priv->order, |
| 623 *ds - 6); |
| 624 exif_data_save_data_content (data, |
| 625 data->ifd[EXIF_IFD_GPS], d,
ds, *ds - 6); |
| 626 offset += 12; |
| 627 } |
| 628 |
| 629 break; |
| 630 case EXIF_IFD_EXIF: |
| 631 |
| 632 /* |
| 633 * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF. |
| 634 * See note above. |
| 635 */ |
| 636 if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { |
| 637 exif_set_short (*d + 6 + offset + 0, data->priv->order, |
| 638 EXIF_TAG_INTEROPERABILITY_IFD_POINTER); |
| 639 exif_set_short (*d + 6 + offset + 2, data->priv->order, |
| 640 EXIF_FORMAT_LONG); |
| 641 exif_set_long (*d + 6 + offset + 4, data->priv->order, |
| 642 1); |
| 643 exif_set_long (*d + 6 + offset + 8, data->priv->order, |
| 644 *ds - 6); |
| 645 exif_data_save_data_content (data, |
| 646 data->ifd[EXIF_IFD_INTEROPE
RABILITY], d, ds, |
| 647 *ds - 6); |
| 648 offset += 12; |
| 649 } |
| 650 |
| 651 break; |
| 652 case EXIF_IFD_1: |
| 653 |
| 654 /* |
| 655 * Information about the thumbnail (if any) is saved in |
| 656 * IFD_1. |
| 657 */ |
| 658 if (data->size) { |
| 659 |
| 660 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */ |
| 661 exif_set_short (*d + 6 + offset + 0, data->priv->order, |
| 662 EXIF_TAG_JPEG_INTERCHANGE_FORMAT); |
| 663 exif_set_short (*d + 6 + offset + 2, data->priv->order, |
| 664 EXIF_FORMAT_LONG); |
| 665 exif_set_long (*d + 6 + offset + 4, data->priv->order, |
| 666 1); |
| 667 exif_set_long (*d + 6 + offset + 8, data->priv->order, |
| 668 *ds - 6); |
| 669 ts = *ds + data->size; |
| 670 t = exif_mem_realloc (data->priv->mem, *d, ts); |
| 671 if (!t) { |
| 672 EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", |
| 673 ts); |
| 674 return; |
| 675 } |
| 676 *d = t; |
| 677 *ds = ts; |
| 678 memcpy (*d + *ds - data->size, data->data, data->size); |
| 679 offset += 12; |
| 680 |
| 681 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */ |
| 682 exif_set_short (*d + 6 + offset + 0, data->priv->order, |
| 683 EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH)
; |
| 684 exif_set_short (*d + 6 + offset + 2, data->priv->order, |
| 685 EXIF_FORMAT_LONG); |
| 686 exif_set_long (*d + 6 + offset + 4, data->priv->order, |
| 687 1); |
| 688 exif_set_long (*d + 6 + offset + 8, data->priv->order, |
| 689 data->size); |
| 690 offset += 12; |
| 691 } |
| 692 |
| 693 break; |
| 694 default: |
| 695 break; |
| 696 } |
| 697 |
| 698 /* Sort the directory according to TIFF specification */ |
| 699 qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12, |
| 700 (ifd->count + n_ptr + n_thumb), 12, |
| 701 (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : c
mp_func_motorola); |
| 702 |
| 703 /* Correctly terminate the directory */ |
| 704 if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count || |
| 705 data->size)) { |
| 706 |
| 707 /* |
| 708 * We are saving IFD 0. Tell where IFD 1 starts and save |
| 709 * IFD 1. |
| 710 */ |
| 711 exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6); |
| 712 exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds, |
| 713 *ds - 6); |
| 714 } else |
| 715 exif_set_long (*d + 6 + offset, data->priv->order, 0); |
| 716 } |
| 717 |
| 718 typedef enum { |
| 719 EXIF_DATA_TYPE_MAKER_NOTE_NONE = 0, |
| 720 EXIF_DATA_TYPE_MAKER_NOTE_CANON = 1, |
| 721 EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS = 2, |
| 722 EXIF_DATA_TYPE_MAKER_NOTE_PENTAX = 3, |
| 723 EXIF_DATA_TYPE_MAKER_NOTE_NIKON = 4, |
| 724 EXIF_DATA_TYPE_MAKER_NOTE_CASIO = 5, |
| 725 EXIF_DATA_TYPE_MAKER_NOTE_FUJI = 6 |
| 726 } ExifDataTypeMakerNote; |
| 727 |
| 728 /*! If MakerNote is recognized, load it. |
| 729 * |
| 730 * \param[in,out] data #ExifData |
| 731 * \param[in] d pointer to raw EXIF data |
| 732 * \param[in] ds length of data at d |
| 733 */ |
| 734 static void |
| 735 interpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds) |
| 736 { |
| 737 int mnoteid; |
| 738 ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE); |
| 739 if (!e) |
| 740 return; |
| 741 |
| 742 if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) { |
| 743 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, |
| 744 "ExifData", "Olympus MakerNote variant type %d", mnoteid
); |
| 745 data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); |
| 746 |
| 747 } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) { |
| 748 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, |
| 749 "ExifData", "Canon MakerNote variant type %d", mnoteid); |
| 750 data->priv->md = exif_mnote_data_canon_new (data->priv->mem, dat
a->priv->options); |
| 751 |
| 752 } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) { |
| 753 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, |
| 754 "ExifData", "Fuji MakerNote variant type %d", mnoteid); |
| 755 data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); |
| 756 |
| 757 /* NOTE: Must do Pentax detection last because some of the |
| 758 * heuristics are pretty general. */ |
| 759 } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) { |
| 760 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, |
| 761 "ExifData", "Pentax MakerNote variant type %d", mnoteid)
; |
| 762 data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); |
| 763 } |
| 764 |
| 765 /* |
| 766 * If we are able to interpret the maker note, do so. |
| 767 */ |
| 768 if (data->priv->md) { |
| 769 exif_mnote_data_log (data->priv->md, data->priv->log); |
| 770 exif_mnote_data_set_byte_order (data->priv->md, |
| 771 data->priv->order); |
| 772 exif_mnote_data_set_offset (data->priv->md, |
| 773 data->priv->offset_mnote); |
| 774 exif_mnote_data_load (data->priv->md, d, ds); |
| 775 } |
| 776 } |
| 777 |
| 778 #define LOG_TOO_SMALL \ |
| 779 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \ |
| 780 _("Size of data too small to allow for EXIF data.")); |
| 781 |
| 782 void |
| 783 exif_data_load_data (ExifData *data, const unsigned char *d_orig, |
| 784 unsigned int ds_orig) |
| 785 { |
| 786 unsigned int l; |
| 787 ExifLong offset; |
| 788 ExifShort n; |
| 789 const unsigned char *d = d_orig; |
| 790 unsigned int ds = ds_orig, len; |
| 791 |
| 792 if (!data || !data->priv || !d || !ds) |
| 793 return; |
| 794 |
| 795 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 796 "Parsing %i byte(s) EXIF data...\n", ds); |
| 797 |
| 798 /* |
| 799 * It can be that the data starts with the EXIF header. If it does |
| 800 * not, search the EXIF marker. |
| 801 */ |
| 802 if (ds < 6) { |
| 803 LOG_TOO_SMALL; |
| 804 return; |
| 805 } |
| 806 if (!memcmp (d, ExifHeader, 6)) { |
| 807 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 808 "Found EXIF header."); |
| 809 } else { |
| 810 while (1) { |
| 811 while ((d[0] == 0xff) && ds) { |
| 812 d++; |
| 813 ds--; |
| 814 } |
| 815 |
| 816 /* JPEG_MARKER_SOI */ |
| 817 if (d[0] == JPEG_MARKER_SOI) { |
| 818 d++; |
| 819 ds--; |
| 820 continue; |
| 821 } |
| 822 |
| 823 /* JPEG_MARKER_APP0 */ |
| 824 if (d[0] == JPEG_MARKER_APP0) { |
| 825 d++; |
| 826 ds--; |
| 827 l = (d[0] << 8) | d[1]; |
| 828 if (l > ds) |
| 829 return; |
| 830 d += l; |
| 831 ds -= l; |
| 832 continue; |
| 833 } |
| 834 |
| 835 /* JPEG_MARKER_APP1 */ |
| 836 if (d[0] == JPEG_MARKER_APP1) |
| 837 break; |
| 838 |
| 839 /* Unknown marker or data. Give up. */ |
| 840 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, |
| 841 "ExifData", _("EXIF marker not found.")); |
| 842 return; |
| 843 } |
| 844 d++; |
| 845 ds--; |
| 846 if (ds < 2) { |
| 847 LOG_TOO_SMALL; |
| 848 return; |
| 849 } |
| 850 len = (d[0] << 8) | d[1]; |
| 851 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 852 "We have to deal with %i byte(s) of EXIF data.", |
| 853 len); |
| 854 d += 2; |
| 855 ds -= 2; |
| 856 } |
| 857 |
| 858 /* |
| 859 * Verify the exif header |
| 860 * (offset 2, length 6). |
| 861 */ |
| 862 if (ds < 6) { |
| 863 LOG_TOO_SMALL; |
| 864 return; |
| 865 } |
| 866 if (memcmp (d, ExifHeader, 6)) { |
| 867 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, |
| 868 "ExifData", _("EXIF header not found.")); |
| 869 return; |
| 870 } |
| 871 |
| 872 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 873 "Found EXIF header."); |
| 874 |
| 875 /* Byte order (offset 6, length 2) */ |
| 876 if (ds < 14) |
| 877 return; |
| 878 if (!memcmp (d + 6, "II", 2)) |
| 879 data->priv->order = EXIF_BYTE_ORDER_INTEL; |
| 880 else if (!memcmp (d + 6, "MM", 2)) |
| 881 data->priv->order = EXIF_BYTE_ORDER_MOTOROLA; |
| 882 else { |
| 883 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, |
| 884 "ExifData", _("Unknown encoding.")); |
| 885 return; |
| 886 } |
| 887 |
| 888 /* Fixed value */ |
| 889 if (exif_get_short (d + 8, data->priv->order) != 0x002a) |
| 890 return; |
| 891 |
| 892 /* IFD 0 offset */ |
| 893 offset = exif_get_long (d + 10, data->priv->order); |
| 894 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 895 "IFD 0 at %i.", (int) offset); |
| 896 |
| 897 /* Parse the actual exif data (usually offset 14 from start) */ |
| 898 exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0)
; |
| 899 |
| 900 /* IFD 1 offset */ |
| 901 if (offset + 6 + 2 > ds) { |
| 902 return; |
| 903 } |
| 904 n = exif_get_short (d + 6 + offset, data->priv->order); |
| 905 if (offset + 6 + 2 + 12 * n + 4 > ds) { |
| 906 return; |
| 907 } |
| 908 offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order); |
| 909 if (offset) { |
| 910 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 911 "IFD 1 at %i.", (int) offset); |
| 912 |
| 913 /* Sanity check. */ |
| 914 if (offset > ds - 6) { |
| 915 exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, |
| 916 "ExifData", "Bogus offset of IFD1."); |
| 917 } else { |
| 918 exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6,
offset, 0); |
| 919 } |
| 920 } |
| 921 |
| 922 /* |
| 923 * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some |
| 924 * cameras use pointers in the maker note tag that point to the |
| 925 * space between IFDs. Here is the only place where we have access |
| 926 * to that data. |
| 927 */ |
| 928 interpret_maker_note(data, d, ds); |
| 929 |
| 930 /* Fixup tags if requested */ |
| 931 if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION) |
| 932 exif_data_fix (data); |
| 933 } |
| 934 |
| 935 void |
| 936 exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds) |
| 937 { |
| 938 if (ds) |
| 939 *ds = 0; /* This means something went wrong */ |
| 940 |
| 941 if (!data || !d || !ds) |
| 942 return; |
| 943 |
| 944 /* Header */ |
| 945 *ds = 14; |
| 946 *d = exif_data_alloc (data, *ds); |
| 947 if (!*d) { |
| 948 *ds = 0; |
| 949 return; |
| 950 } |
| 951 memcpy (*d, ExifHeader, 6); |
| 952 |
| 953 /* Order (offset 6) */ |
| 954 if (data->priv->order == EXIF_BYTE_ORDER_INTEL) { |
| 955 memcpy (*d + 6, "II", 2); |
| 956 } else { |
| 957 memcpy (*d + 6, "MM", 2); |
| 958 } |
| 959 |
| 960 /* Fixed value (2 bytes, offset 8) */ |
| 961 exif_set_short (*d + 8, data->priv->order, 0x002a); |
| 962 |
| 963 /* |
| 964 * IFD 0 offset (4 bytes, offset 10). |
| 965 * We will start 8 bytes after the |
| 966 * EXIF header (2 bytes for order, another 2 for the test, and |
| 967 * 4 bytes for the IFD 0 offset make 8 bytes together). |
| 968 */ |
| 969 exif_set_long (*d + 10, data->priv->order, 8); |
| 970 |
| 971 /* Now save IFD 0. IFD 1 will be saved automatically. */ |
| 972 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 973 "Saving IFDs..."); |
| 974 exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds, |
| 975 *ds - 6); |
| 976 exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", |
| 977 "Saved %i byte(s) EXIF data.", *ds); |
| 978 } |
| 979 |
| 980 ExifData * |
| 981 exif_data_new_from_file (const char *path) |
| 982 { |
| 983 ExifData *edata; |
| 984 ExifLoader *loader; |
| 985 |
| 986 loader = exif_loader_new (); |
| 987 exif_loader_write_file (loader, path); |
| 988 edata = exif_loader_get_data (loader); |
| 989 exif_loader_unref (loader); |
| 990 |
| 991 return (edata); |
| 992 } |
| 993 |
| 994 void |
| 995 exif_data_ref (ExifData *data) |
| 996 { |
| 997 if (!data) |
| 998 return; |
| 999 |
| 1000 data->priv->ref_count++; |
| 1001 } |
| 1002 |
| 1003 void |
| 1004 exif_data_unref (ExifData *data) |
| 1005 { |
| 1006 if (!data) |
| 1007 return; |
| 1008 |
| 1009 data->priv->ref_count--; |
| 1010 if (!data->priv->ref_count) |
| 1011 exif_data_free (data); |
| 1012 } |
| 1013 |
| 1014 void |
| 1015 exif_data_free (ExifData *data) |
| 1016 { |
| 1017 unsigned int i; |
| 1018 ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL; |
| 1019 |
| 1020 if (!data) |
| 1021 return; |
| 1022 |
| 1023 for (i = 0; i < EXIF_IFD_COUNT; i++) { |
| 1024 if (data->ifd[i]) { |
| 1025 exif_content_unref (data->ifd[i]); |
| 1026 data->ifd[i] = NULL; |
| 1027 } |
| 1028 } |
| 1029 |
| 1030 if (data->data) { |
| 1031 exif_mem_free (mem, data->data); |
| 1032 data->data = NULL; |
| 1033 } |
| 1034 |
| 1035 if (data->priv) { |
| 1036 if (data->priv->log) { |
| 1037 exif_log_unref (data->priv->log); |
| 1038 data->priv->log = NULL; |
| 1039 } |
| 1040 if (data->priv->md) { |
| 1041 exif_mnote_data_unref (data->priv->md); |
| 1042 data->priv->md = NULL; |
| 1043 } |
| 1044 exif_mem_free (mem, data->priv); |
| 1045 exif_mem_free (mem, data); |
| 1046 } |
| 1047 |
| 1048 exif_mem_unref (mem); |
| 1049 } |
| 1050 |
| 1051 void |
| 1052 exif_data_dump (ExifData *data) |
| 1053 { |
| 1054 unsigned int i; |
| 1055 |
| 1056 if (!data) |
| 1057 return; |
| 1058 |
| 1059 for (i = 0; i < EXIF_IFD_COUNT; i++) { |
| 1060 if (data->ifd[i] && data->ifd[i]->count) { |
| 1061 printf ("Dumping IFD '%s'...\n", |
| 1062 exif_ifd_get_name (i)); |
| 1063 exif_content_dump (data->ifd[i], 0); |
| 1064 } |
| 1065 } |
| 1066 |
| 1067 if (data->data) { |
| 1068 printf ("%i byte(s) thumbnail data available.", data->size); |
| 1069 if (data->size >= 4) { |
| 1070 printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n", |
| 1071 data->data[0], data->data[1], |
| 1072 data->data[data->size - 2], |
| 1073 data->data[data->size - 1]); |
| 1074 } |
| 1075 } |
| 1076 } |
| 1077 |
| 1078 ExifByteOrder |
| 1079 exif_data_get_byte_order (ExifData *data) |
| 1080 { |
| 1081 if (!data) |
| 1082 return (0); |
| 1083 |
| 1084 return (data->priv->order); |
| 1085 } |
| 1086 |
| 1087 void |
| 1088 exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func, |
| 1089 void *user_data) |
| 1090 { |
| 1091 unsigned int i; |
| 1092 |
| 1093 if (!data || !func) |
| 1094 return; |
| 1095 |
| 1096 for (i = 0; i < EXIF_IFD_COUNT; i++) |
| 1097 func (data->ifd[i], user_data); |
| 1098 } |
| 1099 |
| 1100 typedef struct _ByteOrderChangeData ByteOrderChangeData; |
| 1101 struct _ByteOrderChangeData { |
| 1102 ExifByteOrder old, new; |
| 1103 }; |
| 1104 |
| 1105 static void |
| 1106 entry_set_byte_order (ExifEntry *e, void *data) |
| 1107 { |
| 1108 ByteOrderChangeData *d = data; |
| 1109 |
| 1110 if (!e) |
| 1111 return; |
| 1112 |
| 1113 exif_array_set_byte_order (e->format, e->data, e->components, d->old, d-
>new); |
| 1114 } |
| 1115 |
| 1116 static void |
| 1117 content_set_byte_order (ExifContent *content, void *data) |
| 1118 { |
| 1119 exif_content_foreach_entry (content, entry_set_byte_order, data); |
| 1120 } |
| 1121 |
| 1122 void |
| 1123 exif_data_set_byte_order (ExifData *data, ExifByteOrder order) |
| 1124 { |
| 1125 ByteOrderChangeData d; |
| 1126 |
| 1127 if (!data || (order == data->priv->order)) |
| 1128 return; |
| 1129 |
| 1130 d.old = data->priv->order; |
| 1131 d.new = order; |
| 1132 exif_data_foreach_content (data, content_set_byte_order, &d); |
| 1133 data->priv->order = order; |
| 1134 if (data->priv->md) |
| 1135 exif_mnote_data_set_byte_order (data->priv->md, order); |
| 1136 } |
| 1137 |
| 1138 void |
| 1139 exif_data_log (ExifData *data, ExifLog *log) |
| 1140 { |
| 1141 unsigned int i; |
| 1142 |
| 1143 if (!data || !data->priv) |
| 1144 return; |
| 1145 exif_log_unref (data->priv->log); |
| 1146 data->priv->log = log; |
| 1147 exif_log_ref (log); |
| 1148 |
| 1149 for (i = 0; i < EXIF_IFD_COUNT; i++) |
| 1150 exif_content_log (data->ifd[i], log); |
| 1151 } |
| 1152 |
| 1153 /* Used internally within libexif */ |
| 1154 ExifLog *exif_data_get_log (ExifData *); |
| 1155 ExifLog * |
| 1156 exif_data_get_log (ExifData *data) |
| 1157 { |
| 1158 if (!data || !data->priv) |
| 1159 return NULL; |
| 1160 return data->priv->log; |
| 1161 } |
| 1162 |
| 1163 static const struct { |
| 1164 ExifDataOption option; |
| 1165 const char *name; |
| 1166 const char *description; |
| 1167 } exif_data_option[] = { |
| 1168 {EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS, N_("Ignore unknown tags"), |
| 1169 N_("Ignore unknown tags when loading EXIF data.")}, |
| 1170 {EXIF_DATA_OPTION_FOLLOW_SPECIFICATION, N_("Follow specification"), |
| 1171 N_("Add, correct and remove entries to get EXIF data that follows " |
| 1172 "the specification.")}, |
| 1173 {EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE, N_("Do not change maker note")
, |
| 1174 N_("When loading and resaving Exif data, save the maker note unmodified
." |
| 1175 " Be aware that the maker note can get corrupted.")}, |
| 1176 {0, NULL, NULL} |
| 1177 }; |
| 1178 |
| 1179 const char * |
| 1180 exif_data_option_get_name (ExifDataOption o) |
| 1181 { |
| 1182 unsigned int i; |
| 1183 |
| 1184 for (i = 0; exif_data_option[i].name; i++) |
| 1185 if (exif_data_option[i].option == o) |
| 1186 break; |
| 1187 return _(exif_data_option[i].name); |
| 1188 } |
| 1189 |
| 1190 const char * |
| 1191 exif_data_option_get_description (ExifDataOption o) |
| 1192 { |
| 1193 unsigned int i; |
| 1194 |
| 1195 for (i = 0; exif_data_option[i].description; i++) |
| 1196 if (exif_data_option[i].option == o) |
| 1197 break; |
| 1198 return _(exif_data_option[i].description); |
| 1199 } |
| 1200 |
| 1201 void |
| 1202 exif_data_set_option (ExifData *d, ExifDataOption o) |
| 1203 { |
| 1204 if (!d) |
| 1205 return; |
| 1206 |
| 1207 d->priv->options |= o; |
| 1208 } |
| 1209 |
| 1210 void |
| 1211 exif_data_unset_option (ExifData *d, ExifDataOption o) |
| 1212 { |
| 1213 if (!d) |
| 1214 return; |
| 1215 |
| 1216 d->priv->options &= ~o; |
| 1217 } |
| 1218 |
| 1219 static void |
| 1220 fix_func (ExifContent *c, void *UNUSED(data)) |
| 1221 { |
| 1222 switch (exif_content_get_ifd (c)) { |
| 1223 case EXIF_IFD_1: |
| 1224 if (c->parent->data) |
| 1225 exif_content_fix (c); |
| 1226 else if (c->count) { |
| 1227 exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "ex
if-data", |
| 1228 "No thumbnail but entries on thumbnail. These
entries have been " |
| 1229 "removed."); |
| 1230 while (c->count) { |
| 1231 unsigned int cnt = c->count; |
| 1232 exif_content_remove_entry (c, c->entries[c->coun
t - 1]); |
| 1233 if (cnt == c->count) { |
| 1234 /* safety net */ |
| 1235 exif_log (c->parent->priv->log, EXIF_LOG
_CODE_DEBUG, "exif-data", |
| 1236 "failed to remove last entry from entrie
s."); |
| 1237 c->count--; |
| 1238 } |
| 1239 } |
| 1240 } |
| 1241 break; |
| 1242 default: |
| 1243 exif_content_fix (c); |
| 1244 } |
| 1245 } |
| 1246 |
| 1247 void |
| 1248 exif_data_fix (ExifData *d) |
| 1249 { |
| 1250 exif_data_foreach_content (d, fix_func, NULL); |
| 1251 } |
| 1252 |
| 1253 void |
| 1254 exif_data_set_data_type (ExifData *d, ExifDataType dt) |
| 1255 { |
| 1256 if (!d || !d->priv) |
| 1257 return; |
| 1258 |
| 1259 d->priv->data_type = dt; |
| 1260 } |
| 1261 |
| 1262 ExifDataType |
| 1263 exif_data_get_data_type (ExifData *d) |
| 1264 { |
| 1265 return (d && d->priv) ? d->priv->data_type : EXIF_DATA_TYPE_UNKNOWN; |
| 1266 } |
OLD | NEW |