1548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* exif-data.c 2548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 3548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Copyright (c) 2001 Lutz Mueller <lutz@users.sourceforge.net> 4548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 5548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is free software; you can redistribute it and/or 6548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * modify it under the terms of the GNU Lesser General Public 7548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License as published by the Free Software Foundation; either 8548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * version 2 of the License, or (at your option) any later version. 9548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 10548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * This library is distributed in the hope that it will be useful, 11548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * but WITHOUT ANY WARRANTY; without even the implied warranty of 12548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Lesser General Public License for more details. 14548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 15548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * You should have received a copy of the GNU Lesser General Public 16548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * License along with this library; if not, write to the 17548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Boston, MA 02110-1301 USA. 19548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 20548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 21548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <config.h> 22548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 23548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-mnote-data.h> 24548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-data.h> 25548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-ifd.h> 26548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-mnote-data-priv.h> 27548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-utils.h> 28548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-loader.h> 29548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-log.h> 30548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/i18n.h> 31548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/exif-system.h> 32548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 33548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/canon/exif-mnote-data-canon.h> 34548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/fuji/exif-mnote-data-fuji.h> 35548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/olympus/exif-mnote-data-olympus.h> 36548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <libexif/pentax/exif-mnote-data-pentax.h> 37548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 38548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <stdlib.h> 39548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <stdio.h> 40548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#include <string.h> 41548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 42548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#undef JPEG_MARKER_SOI 43548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define JPEG_MARKER_SOI 0xd8 44548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#undef JPEG_MARKER_APP0 45548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define JPEG_MARKER_APP0 0xe0 46548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#undef JPEG_MARKER_APP1 47548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define JPEG_MARKER_APP1 0xe1 48548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 49548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; 50548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 51548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstruct _ExifDataPrivate 52548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 53548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifByteOrder order; 54548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 55548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMnoteData *md; 56548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 57548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifLog *log; 58548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMem *mem; 59548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 60548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ref_count; 61548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 62548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Temporarily used while loading data */ 63548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int offset_mnote; 64548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 65548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifDataOption options; 66548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifDataType data_type; 67548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen}; 68548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 69548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void * 70548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_alloc (ExifData *data, unsigned int i) 71548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 72548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen void *d; 73548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 74548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !i) 75548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return NULL; 76548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 77548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d = exif_mem_alloc (data->priv->mem, i); 78548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (d) 79548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return d; 80548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 81548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", i); 82548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return NULL; 83548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 84548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 85548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifMnoteData * 86548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_get_mnote_data (ExifData *d) 87548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 88548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (d && d->priv) ? d->priv->md : NULL; 89548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 90548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 91548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifData * 92548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_new (void) 93548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 94548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMem *mem = exif_mem_new_default (); 95548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifData *d = exif_data_new_mem (mem); 96548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 97548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_unref (mem); 98548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 99548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return d; 100548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 101548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 102548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifData * 103548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_new_mem (ExifMem *mem) 104548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 105548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifData *data; 106548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 107548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 108548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!mem) 109548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return NULL; 110548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 111548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data = exif_mem_alloc (mem, sizeof (ExifData)); 112548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 113548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (NULL); 114548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv = exif_mem_alloc (mem, sizeof (ExifDataPrivate)); 115548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data->priv) { 116548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (mem, data); 117548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (NULL); 118548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 119548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->ref_count = 1; 120548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 121548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->mem = mem; 122548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_ref (mem); 123548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 124548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) { 125548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[i] = exif_content_new_mem (data->priv->mem); 126548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data->ifd[i]) { 127548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_free (data); 128548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (NULL); 129548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 130548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[i]->parent = data; 131548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 132548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 133548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Default options */ 134548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#ifndef NO_VERBOSE_TAG_STRINGS 135548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 136548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * When the tag list is compiled away, setting this option prevents 137548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * any tags from being loaded 138548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 139548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_set_option (data, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS); 140548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#endif 141548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_set_option (data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); 142548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 143548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Default data type: none */ 144548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_set_data_type (data, EXIF_DATA_TYPE_COUNT); 145548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 146548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (data); 147548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 148548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 149548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifData * 150548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_new_from_data (const unsigned char *data, unsigned int size) 151548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 152548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifData *edata; 153548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 154548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen edata = exif_data_new (); 155548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data (edata, data, size); 156548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (edata); 157548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 158548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 159548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic int 160548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_load_data_entry (ExifData *data, ExifEntry *entry, 161548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const unsigned char *d, 162548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int size, unsigned int offset) 163548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 164548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int s, doff; 165548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 166548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->tag = exif_get_short (d + offset + 0, data->priv->order); 167548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->format = exif_get_short (d + offset + 2, data->priv->order); 168548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->components = exif_get_long (d + offset + 4, data->priv->order); 169548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 170548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* FIXME: should use exif_tag_get_name_in_ifd here but entry->parent 171548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * has not been set yet 172548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 173548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 174548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Loading entry 0x%x ('%s')...", entry->tag, 175548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_tag_get_name (entry->tag)); 176548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 177548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* {0,1,2,4,8} x { 0x00000000 .. 0xffffffff } 178548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * -> { 0x000000000 .. 0x7fffffff8 } */ 179548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size(entry->format) * entry->components; 180548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((s < entry->components) || (s == 0)){ 181548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return 0; 182548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 183548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 184548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 185548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Size? If bigger than 4 bytes, the actual data is not 186548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * in the entry but somewhere else (offset). 187548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 188548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) 189548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = exif_get_long (d + offset + 8, data->priv->order); 190548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else 191548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = offset + 8; 192548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 193548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sanity checks */ 194548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) { 195548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 196548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Tag data past end of buffer (%u > %u)", doff+s, size); 197548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return 0; 198548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 199548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 200548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->data = exif_data_alloc (data, s); 201548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (entry->data) { 202548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->size = s; 203548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (entry->data, d + doff, s); 204548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 205548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* FIXME: What do our callers do if (entry->data == NULL)? */ 206548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY(data->priv->log, "ExifData", s); 207548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 208548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 209548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* If this is the MakerNote, remember the offset */ 210548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (entry->tag == EXIF_TAG_MAKER_NOTE) { 211548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!entry->data) { 212548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 213548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "MakerNote found with empty data"); 214548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else if (entry->size > 6) { 215548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, 216548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_CODE_DEBUG, "ExifData", 217548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "MakerNote found (%02x %02x %02x %02x " 218548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "%02x %02x %02x...).", 219548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->data[0], entry->data[1], entry->data[2], 220548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->data[3], entry->data[4], entry->data[5], 221548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry->data[6]); 222548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 223548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->offset_mnote = doff; 224548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 225548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return 1; 226548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 227548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 228548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 229548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_save_data_entry (ExifData *data, ExifEntry *e, 230548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char **d, unsigned int *ds, 231548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int offset) 232548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 233548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int doff, s; 234548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ts; 235548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 236548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv) 237548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 238548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 239548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 240548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Each entry is 12 bytes long. The memory for the entry has 241548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * already been allocated. 242548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 243548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, 244548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order, (ExifShort) e->tag); 245548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, 246548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order, (ExifShort) e->format); 247548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 248548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!(data->priv->options & EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE)) { 249548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* If this is the maker note tag, update it. */ 250548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((e->tag == EXIF_TAG_MAKER_NOTE) && data->priv->md) { 251548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* TODO: this is using the wrong ExifMem to free e->data */ 252548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (data->priv->mem, e->data); 253548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen e->data = NULL; 254548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen e->size = 0; 255548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_set_offset (data->priv->md, *ds - 6); 256548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_save (data->priv->md, &e->data, &e->size); 257548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen e->components = e->size; 258548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 259548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 260548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 261548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, 262548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order, e->components); 263548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 264548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 265548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Size? If bigger than 4 bytes, the actual data is not in 266548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * the entry but somewhere else. 267548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 268548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen s = exif_format_get_size (e->format) * e->components; 269548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s > 4) { 270548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char *t; 271548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = *ds - 6; 272548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts = *ds + s; 273548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 274548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 275548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * According to the TIFF specification, 276548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * the offset must be an even number. If we need to introduce 277548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * a padding byte, we set it to 0. 278548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 279548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) 280548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts++; 281548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen t = exif_mem_realloc (data->priv->mem, *d, ts); 282548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!t) { 283548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); 284548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 285548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 286548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *d = t; 287548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = ts; 288548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, doff); 289548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s & 1) 290548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *(*d + *ds - 1) = '\0'; 291548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 292548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else 293548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen doff = offset + 8; 294548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 295548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Write the data. Fill unneeded bytes with 0. Do not crash with 296548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * e->data is NULL */ 297548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (e->data) { 298548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*d + 6 + doff, e->data, s); 299548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 300548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memset (*d + 6 + doff, 0, s); 301548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 302548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (s < 4) 303548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memset (*d + 6 + doff + s, 0, (4 - s)); 304548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 305548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 306548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 307548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_load_data_thumbnail (ExifData *data, const unsigned char *d, 308548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ds, ExifLong o, ExifLong s) 309548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 310548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sanity checks */ 311548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) { 312548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 313548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Bogus thumbnail offset (%u) or size (%u).", 314548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o, s); 315548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 316548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 317548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 318548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->data) 319548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (data->priv->mem, data->data); 320548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!(data->data = exif_data_alloc (data, s))) { 321548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", s); 322548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->size = 0; 323548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 324548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 325548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->size = s; 326548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (data->data, d + o, s); 327548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 328548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 329548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#undef CHECK_REC 330548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define CHECK_REC(i) \ 331548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenif ((i) == ifd) { \ 332548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \ 333548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Recursive entry in IFD " \ 334548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "'%s' detected. Skipping...", \ 335548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_ifd_get_name (i)); \ 336548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; \ 337548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} \ 338548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenif (data->ifd[(i)]->count) { \ 339548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, \ 340548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Attempt to load IFD " \ 341548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "'%s' multiple times detected. " \ 342548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Skipping...", \ 343548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_ifd_get_name (i)); \ 344548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; \ 345548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 346548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 347548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/*! Load data for an IFD. 348548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 349548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in,out] data #ExifData 350548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] ifd IFD to load 351548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] d pointer to buffer containing raw IFD data 352548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] ds size of raw data in buffer at \c d 353548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] offset offset into buffer at \c d at which IFD starts 354548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] recursion_depth number of times this function has been 355548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * recursively called without returning 356548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 357548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 358548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_load_data_content (ExifData *data, ExifIfd ifd, 359548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const unsigned char *d, 360548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ds, unsigned int offset, unsigned int recursion_depth) 361548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 362548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifLong o, thumbnail_offset = 0, thumbnail_length = 0; 363548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifShort n; 364548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifEntry *entry; 365548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 366548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifTag tag; 367548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 368548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv) 369548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 370548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 371548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* check for valid ExifIfd enum range */ 372548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((((int)ifd) < 0) || ( ((int)ifd) >= EXIF_IFD_COUNT)) 373548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 374548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 375548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (recursion_depth > 30) { 376548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", 377548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Deep recursion detected!"); 378548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 379548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 380548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 381548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Read the number of entries */ 382548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((offset + 2 < offset) || (offset + 2 < 2) || (offset + 2 > ds)) { 383548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", 384548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Tag data past end of buffer (%u > %u)", offset+2, ds); 385548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 386548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 387548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n = exif_get_short (d + offset, data->priv->order); 388548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 389548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Loading %hu entries...", n); 390548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 2; 391548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 392548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Check if we have enough data. */ 393548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (offset + 12 * n > ds) { 394548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n = (ds - offset) / 12; 395548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 396548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Short data; only loading %hu entries...", n); 397548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 398548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 399548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < n; i++) { 400548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 401548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen tag = exif_get_short (d + offset + 12 * i, data->priv->order); 402548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen switch (tag) { 403548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_EXIF_IFD_POINTER: 404548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_GPS_INFO_IFD_POINTER: 405548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: 406548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: 407548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: 408548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen o = exif_get_long (d + offset + 12 * i + 8, 409548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order); 410548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* FIXME: IFD_POINTER tags aren't marked as being in a 411548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * specific IFD, so exif_tag_get_name_in_ifd won't work 412548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 413548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 414548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Sub-IFD entry 0x%x ('%s') at %u.", tag, 415548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_tag_get_name(tag), o); 416548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen switch (tag) { 417548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_EXIF_IFD_POINTER: 418548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen CHECK_REC (EXIF_IFD_EXIF); 419548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_content (data, EXIF_IFD_EXIF, d, ds, o, recursion_depth + 1); 420548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 421548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_GPS_INFO_IFD_POINTER: 422548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen CHECK_REC (EXIF_IFD_GPS); 423548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_content (data, EXIF_IFD_GPS, d, ds, o, recursion_depth + 1); 424548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 425548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: 426548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen CHECK_REC (EXIF_IFD_INTEROPERABILITY); 427548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_content (data, EXIF_IFD_INTEROPERABILITY, d, ds, o, recursion_depth + 1); 428548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 429548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_JPEG_INTERCHANGE_FORMAT: 430548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen thumbnail_offset = o; 431548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (thumbnail_offset && thumbnail_length) 432548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_thumbnail (data, d, 433548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds, thumbnail_offset, 434548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen thumbnail_length); 435548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 436548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: 437548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen thumbnail_length = o; 438548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (thumbnail_offset && thumbnail_length) 439548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_thumbnail (data, d, 440548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds, thumbnail_offset, 441548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen thumbnail_length); 442548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 443548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen default: 444548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 445548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 446548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 447548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen default: 448548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 449548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 450548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * If we don't know the tag, don't fail. It could be that new 451548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * versions of the standard have defined additional tags. Note that 452548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 0 is a valid tag in the GPS IFD. 453548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 454548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!exif_tag_get_name_in_ifd (tag, ifd)) { 455548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 456548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 457548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Special case: Tag and format 0. That's against specification 458548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * (at least up to 2.2). But Photoshop writes it anyways. 459548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 460548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!memcmp (d + offset + 12 * i, "\0\0\0\0", 4)) { 461548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 462548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Skipping empty entry at position %u in '%s'.", i, 463548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_ifd_get_name (ifd)); 464548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 465548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 466548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 467548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Unknown tag 0x%04x (entry %u in '%s'). Please report this tag " 468548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "to <libexif-devel@lists.sourceforge.net>.", tag, i, 469548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_ifd_get_name (ifd)); 470548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->options & EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS) 471548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 472548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 473548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen entry = exif_entry_new_mem (data->priv->mem); 474548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (exif_data_load_data_entry (data, entry, d, ds, 475548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset + 12 * i)) 476548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_add_entry (data->ifd[ifd], entry); 477548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_entry_unref (entry); 478548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 479548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 480548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 481548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 482548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 483548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic int 484548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissencmp_func (const unsigned char *p1, const unsigned char *p2, ExifByteOrder o) 485548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 486548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifShort tag1 = exif_get_short (p1, o); 487548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifShort tag2 = exif_get_short (p2, o); 488548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 489548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (tag1 < tag2) ? -1 : (tag1 > tag2) ? 1 : 0; 490548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 491548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 492548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic int 493548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissencmp_func_intel (const void *elem1, const void *elem2) 494548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 495548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return cmp_func ((const unsigned char *) elem1, 496548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (const unsigned char *) elem2, EXIF_BYTE_ORDER_INTEL); 497548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 498548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 499548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic int 500548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissencmp_func_motorola (const void *elem1, const void *elem2) 501548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 502548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return cmp_func ((const unsigned char *) elem1, 503548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (const unsigned char *) elem2, EXIF_BYTE_ORDER_MOTOROLA); 504548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 505548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 506548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 507548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_save_data_content (ExifData *data, ExifContent *ifd, 508548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char **d, unsigned int *ds, 509548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int offset) 510548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 511548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int j, n_ptr = 0, n_thumb = 0; 512548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifIfd i; 513548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned char *t; 514548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ts; 515548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 516548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv || !ifd || !d || !ds) 517548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 518548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 519548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) 520548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ifd == data->ifd[i]) 521548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 522548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i == EXIF_IFD_COUNT) 523548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; /* error */ 524548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 525548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 526548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Check if we need some extra entries for pointers or the thumbnail. 527548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 528548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen switch (i) { 529548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_0: 530548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 531548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 532548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * The pointer to IFD_EXIF is in IFD_0. The pointer to 533548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * IFD_INTEROPERABILITY is in IFD_EXIF. 534548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 535548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_EXIF]->count || 536548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[EXIF_IFD_INTEROPERABILITY]->count) 537548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n_ptr++; 538548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 539548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* The pointer to IFD_GPS is in IFD_0. */ 540548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_GPS]->count) 541548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n_ptr++; 542548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 543548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 544548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_1: 545548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->size) 546548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n_thumb = 2; 547548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 548548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_EXIF: 549548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) 550548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n_ptr++; 551548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen default: 552548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 553548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 554548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 555548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 556548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Allocate enough memory for all entries 557548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * and the number of entries. 558548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 559548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts = *ds + (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4); 560548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen t = exif_mem_realloc (data->priv->mem, *d, ts); 561548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!t) { 562548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", ts); 563548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 564548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 565548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *d = t; 566548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = ts; 567548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 568548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Save the number of entries */ 569548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset, data->priv->order, 570548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (ExifShort) (ifd->count + n_ptr + n_thumb)); 571548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 2; 572548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 573548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 574548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Save each entry. Make sure that no memcpys from NULL pointers are 575548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * performed 576548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 577548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 578548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Saving %i entries (IFD '%s', offset: %i)...", 579548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ifd->count, exif_ifd_get_name (i), offset); 580548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (j = 0; j < ifd->count; j++) { 581548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ifd->entries[j]) { 582548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_entry (data, ifd->entries[j], d, ds, 583548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset + 12 * j); 584548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 585548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 586548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 587548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12 * ifd->count; 588548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 589548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Now save special entries. */ 590548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen switch (i) { 591548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_0: 592548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 593548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 594548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * The pointer to IFD_EXIF is in IFD_0. 595548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF, 596548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * therefore, if IFD_INTEROPERABILITY is not empty, we need 597548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * IFD_EXIF even if latter is empty. 598548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 599548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_EXIF]->count || 600548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { 601548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, data->priv->order, 602548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_TAG_EXIF_IFD_POINTER); 603548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, data->priv->order, 604548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_FORMAT_LONG); 605548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, data->priv->order, 606548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1); 607548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, 608548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 609548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_content (data, 610548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6); 611548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12; 612548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 613548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 614548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* The pointer to IFD_GPS is in IFD_0, too. */ 615548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_GPS]->count) { 616548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, data->priv->order, 617548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_TAG_GPS_INFO_IFD_POINTER); 618548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, data->priv->order, 619548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_FORMAT_LONG); 620548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, data->priv->order, 621548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1); 622548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, 623548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 624548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_content (data, 625548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6); 626548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12; 627548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 628548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 629548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 630548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_EXIF: 631548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 632548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 633548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF. 634548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * See note above. 635548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 636548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) { 637548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, data->priv->order, 638548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_TAG_INTEROPERABILITY_IFD_POINTER); 639548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, data->priv->order, 640548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_FORMAT_LONG); 641548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, data->priv->order, 642548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1); 643548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, 644548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 645548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_content (data, 646548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, 647548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 648548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12; 649548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 650548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 651548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 652548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_1: 653548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 654548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 655548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Information about the thumbnail (if any) is saved in 656548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * IFD_1. 657548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 658548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->size) { 659548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 660548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */ 661548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, data->priv->order, 662548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_TAG_JPEG_INTERCHANGE_FORMAT); 663548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, data->priv->order, 664548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_FORMAT_LONG); 665548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, data->priv->order, 666548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1); 667548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, 668548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 669548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts = *ds + data->size; 670548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen t = exif_mem_realloc (data->priv->mem, *d, ts); 671548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!t) { 672548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_LOG_NO_MEMORY (data->priv->log, "ExifData", 673548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ts); 674548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 675548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 676548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *d = t; 677548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = ts; 678548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*d + *ds - data->size, data->data, data->size); 679548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12; 680548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 681548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */ 682548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 0, data->priv->order, 683548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); 684548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 6 + offset + 2, data->priv->order, 685548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_FORMAT_LONG); 686548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 4, data->priv->order, 687548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1); 688548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset + 8, data->priv->order, 689548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->size); 690548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset += 12; 691548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 692548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 693548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 694548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen default: 695548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 696548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 697548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 698548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sort the directory according to TIFF specification */ 699548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen qsort (*d + 6 + offset - (ifd->count + n_ptr + n_thumb) * 12, 700548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (ifd->count + n_ptr + n_thumb), 12, 701548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen (data->priv->order == EXIF_BYTE_ORDER_INTEL) ? cmp_func_intel : cmp_func_motorola); 702548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 703548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Correctly terminate the directory */ 704548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count || 705548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->size)) { 706548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 707548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 708548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * We are saving IFD 0. Tell where IFD 1 starts and save 709548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * IFD 1. 710548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 711548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6); 712548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds, 713548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 714548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else 715548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 6 + offset, data->priv->order, 0); 716548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 717548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 718548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissentypedef enum { 719548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_NONE = 0, 720548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_CANON = 1, 721548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_OLYMPUS = 2, 722548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_PENTAX = 3, 723548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_NIKON = 4, 724548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_CASIO = 5, 725548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen EXIF_DATA_TYPE_MAKER_NOTE_FUJI = 6 726548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} ExifDataTypeMakerNote; 727548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 728548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/*! If MakerNote is recognized, load it. 729548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 730548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in,out] data #ExifData 731548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] d pointer to raw EXIF data 732548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * \param[in] ds length of data at d 733548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 734548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 735548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelisseninterpret_maker_note(ExifData *data, const unsigned char *d, unsigned int ds) 736548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 737548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen int mnoteid; 738548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifEntry* e = exif_data_get_entry (data, EXIF_TAG_MAKER_NOTE); 739548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!e) 740548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 741548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 742548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if ((mnoteid = exif_mnote_data_olympus_identify (data, e)) != 0) { 743548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, 744548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Olympus MakerNote variant type %d", mnoteid); 745548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->md = exif_mnote_data_olympus_new (data->priv->mem); 746548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 747548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else if ((mnoteid = exif_mnote_data_canon_identify (data, e)) != 0) { 748548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, 749548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Canon MakerNote variant type %d", mnoteid); 750548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->md = exif_mnote_data_canon_new (data->priv->mem, data->priv->options); 751548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 752548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else if ((mnoteid = exif_mnote_data_fuji_identify (data, e)) != 0) { 753548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, 754548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Fuji MakerNote variant type %d", mnoteid); 755548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->md = exif_mnote_data_fuji_new (data->priv->mem); 756548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 757548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* NOTE: Must do Pentax detection last because some of the 758548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * heuristics are pretty general. */ 759548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else if ((mnoteid = exif_mnote_data_pentax_identify (data, e)) != 0) { 760548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, 761548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Pentax MakerNote variant type %d", mnoteid); 762548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->md = exif_mnote_data_pentax_new (data->priv->mem); 763548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 764548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 765548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 766548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * If we are able to interpret the maker note, do so. 767548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 768548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->md) { 769548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_log (data->priv->md, data->priv->log); 770548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_set_byte_order (data->priv->md, 771548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order); 772548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_set_offset (data->priv->md, 773548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->offset_mnote); 774548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_load (data->priv->md, d, ds); 775548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 776548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 777548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 778548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen#define LOG_TOO_SMALL \ 779548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifData", \ 780548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen _("Size of data too small to allow for EXIF data.")); 781548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 782548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 783548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_load_data (ExifData *data, const unsigned char *d_orig, 784548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int ds) 785548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 786548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int l; 787548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifLong offset; 788548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifShort n; 789548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const unsigned char *d = d_orig; 790548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int len, fullds; 791548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 792548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv || !d || !ds) 793548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 794548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 795548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 796548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Parsing %i byte(s) EXIF data...\n", ds); 797548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 798548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 799548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * It can be that the data starts with the EXIF header. If it does 800548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * not, search the EXIF marker. 801548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 802548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds < 6) { 803548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen LOG_TOO_SMALL; 804548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 805548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 806548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!memcmp (d, ExifHeader, 6)) { 807548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 808548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Found EXIF header."); 809548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 810548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen while (ds >= 3) { 811548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen while (ds && (d[0] == 0xff)) { 812548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d++; 813548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds--; 814548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 815548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 816548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* JPEG_MARKER_SOI */ 817548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds && d[0] == JPEG_MARKER_SOI) { 818548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d++; 819548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds--; 820548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 821548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 822548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 823548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* JPEG_MARKER_APP0 */ 824548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds >= 3 && d[0] == JPEG_MARKER_APP0) { 825548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d++; 826548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds--; 827548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen l = (d[0] << 8) | d[1]; 828548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (l > ds) 829548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 830548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d += l; 831548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds -= l; 832548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen continue; 833548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 834548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 835548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* JPEG_MARKER_APP1 */ 836548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds && d[0] == JPEG_MARKER_APP1) 837548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 838548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 839548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Unknown marker or data. Give up. */ 840548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, 841548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", _("EXIF marker not found.")); 842548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 843548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 844548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds < 3) { 845548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen LOG_TOO_SMALL; 846548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 847548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 848548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d++; 849548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds--; 850548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen len = (d[0] << 8) | d[1]; 851548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 852548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "We have to deal with %i byte(s) of EXIF data.", 853548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen len); 854548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d += 2; 855548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds -= 2; 856548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 857548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 858548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 859548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * Verify the exif header 860548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * (offset 2, length 6). 861548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 862548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds < 6) { 863548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen LOG_TOO_SMALL; 864548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 865548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 866548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (memcmp (d, ExifHeader, 6)) { 867548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, 868548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", _("EXIF header not found.")); 869548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 870548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 871548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 872548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 873548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Found EXIF header."); 874548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 875548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sanity check the data length */ 876548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds < 14) 877548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 878548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 879548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* The JPEG APP1 section can be no longer than 64 KiB (including a 880548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 16-bit length), so cap the data length to protect against overflow 881548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen in future offset calculations */ 882548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen fullds = ds; 883548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds > 0xfffe) 884548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ds = 0xfffe; 885548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 886548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Byte order (offset 6, length 2) */ 887548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!memcmp (d + 6, "II", 2)) 888548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order = EXIF_BYTE_ORDER_INTEL; 889548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else if (!memcmp (d + 6, "MM", 2)) 890548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order = EXIF_BYTE_ORDER_MOTOROLA; 891548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else { 892548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, 893548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", _("Unknown encoding.")); 894548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 895548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 896548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 897548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Fixed value */ 898548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (exif_get_short (d + 8, data->priv->order) != 0x002a) 899548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 900548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 901548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* IFD 0 offset */ 902548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset = exif_get_long (d + 10, data->priv->order); 903548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 904548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "IFD 0 at %i.", (int) offset); 905548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 906548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sanity check the offset, being careful about overflow */ 907548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (offset > ds || offset + 6 + 2 > ds) 908548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 909548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 910548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Parse the actual exif data (usually offset 14 from start) */ 911548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0); 912548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 913548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* IFD 1 offset */ 914548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen n = exif_get_short (d + 6 + offset, data->priv->order); 915548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (offset + 6 + 2 + 12 * n + 4 > ds) 916548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 917548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 918548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order); 919548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (offset) { 920548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 921548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "IFD 1 at %i.", (int) offset); 922548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 923548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Sanity check. */ 924548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (offset > ds || offset + 6 > ds) { 925548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA, 926548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "ExifData", "Bogus offset of IFD1."); 927548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 928548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_load_data_content (data, EXIF_IFD_1, d + 6, ds - 6, offset, 0); 929548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 930548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 931548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 932548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 933548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * If we got an EXIF_TAG_MAKER_NOTE, try to interpret it. Some 934548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * cameras use pointers in the maker note tag that point to the 935548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * space between IFDs. Here is the only place where we have access 936548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * to that data. 937548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 938548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen interpret_maker_note(data, d, fullds); 939548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 940548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Fixup tags if requested */ 941548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION) 942548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_fix (data); 943548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 944548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 945548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 946548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds) 947548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 948548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (ds) 949548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = 0; /* This means something went wrong */ 950548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 951548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !d || !ds) 952548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 953548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 954548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Header */ 955548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = 14; 956548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *d = exif_data_alloc (data, *ds); 957548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!*d) { 958548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds = 0; 959548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 960548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 961548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*d, ExifHeader, 6); 962548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 963548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Order (offset 6) */ 964548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->order == EXIF_BYTE_ORDER_INTEL) { 965548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*d + 6, "II", 2); 966548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } else { 967548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen memcpy (*d + 6, "MM", 2); 968548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 969548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 970548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Fixed value (2 bytes, offset 8) */ 971548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_short (*d + 8, data->priv->order, 0x002a); 972548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 973548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* 974548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * IFD 0 offset (4 bytes, offset 10). 975548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * We will start 8 bytes after the 976548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * EXIF header (2 bytes for order, another 2 for the test, and 977548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen * 4 bytes for the IFD 0 offset make 8 bytes together). 978548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen */ 979548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_set_long (*d + 10, data->priv->order, 8); 980548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 981548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* Now save IFD 0. IFD 1 will be saved automatically. */ 982548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 983548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Saving IFDs..."); 984548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds, 985548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen *ds - 6); 986548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", 987548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "Saved %i byte(s) EXIF data.", *ds); 988548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 989548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 990548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifData * 991548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_new_from_file (const char *path) 992548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 993548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifData *edata; 994548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifLoader *loader; 995548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 996548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen loader = exif_loader_new (); 997548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_loader_write_file (loader, path); 998548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen edata = exif_loader_get_data (loader); 999548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_loader_unref (loader); 1000548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1001548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (edata); 1002548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1003548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1004548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1005548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_ref (ExifData *data) 1006548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1007548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 1008548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1009548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1010548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->ref_count++; 1011548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1012548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1013548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1014548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_unref (ExifData *data) 1015548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1016548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 1017548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1018548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1019548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->ref_count--; 1020548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data->priv->ref_count) 1021548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_free (data); 1022548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1023548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1024548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1025548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_free (ExifData *data) 1026548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1027548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1028548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifMem *mem = (data && data->priv) ? data->priv->mem : NULL; 1029548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1030548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 1031548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1032548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1033548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) { 1034548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[i]) { 1035548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_unref (data->ifd[i]); 1036548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->ifd[i] = NULL; 1037548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1038548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1039548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1040548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->data) { 1041548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (mem, data->data); 1042548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->data = NULL; 1043548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1044548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1045548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv) { 1046548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->log) { 1047548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log_unref (data->priv->log); 1048548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->log = NULL; 1049548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1050548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->md) { 1051548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_unref (data->priv->md); 1052548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->md = NULL; 1053548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1054548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (mem, data->priv); 1055548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_free (mem, data); 1056548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1057548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1058548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mem_unref (mem); 1059548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1060548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1061548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1062548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_dump (ExifData *data) 1063548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1064548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1065548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1066548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 1067548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1068548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1069548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) { 1070548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->ifd[i] && data->ifd[i]->count) { 1071548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen printf ("Dumping IFD '%s'...\n", 1072548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_ifd_get_name (i)); 1073548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_dump (data->ifd[i], 0); 1074548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1075548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1076548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1077548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->data) { 1078548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen printf ("%i byte(s) thumbnail data available.", data->size); 1079548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->size >= 4) { 1080548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n", 1081548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->data[0], data->data[1], 1082548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->data[data->size - 2], 1083548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->data[data->size - 1]); 1084548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1085548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1086548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1087548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1088548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifByteOrder 1089548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_get_byte_order (ExifData *data) 1090548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1091548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data) 1092548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (0); 1093548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1094548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (data->priv->order); 1095548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1096548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1097548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1098548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func, 1099548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen void *user_data) 1100548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1101548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1102548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1103548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !func) 1104548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1105548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1106548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) 1107548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen func (data->ifd[i], user_data); 1108548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1109548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1110548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissentypedef struct _ByteOrderChangeData ByteOrderChangeData; 1111548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstruct _ByteOrderChangeData { 1112548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifByteOrder old, new; 1113548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen}; 1114548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1115548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 1116548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenentry_set_byte_order (ExifEntry *e, void *data) 1117548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1118548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ByteOrderChangeData *d = data; 1119548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1120548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!e) 1121548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1122548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1123548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_array_set_byte_order (e->format, e->data, e->components, d->old, d->new); 1124548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1125548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1126548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 1127548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissencontent_set_byte_order (ExifContent *content, void *data) 1128548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1129548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_foreach_entry (content, entry_set_byte_order, data); 1130548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1131548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1132548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1133548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_set_byte_order (ExifData *data, ExifByteOrder order) 1134548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1135548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ByteOrderChangeData d; 1136548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1137548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || (order == data->priv->order)) 1138548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1139548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1140548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d.old = data->priv->order; 1141548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d.new = order; 1142548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_foreach_content (data, content_set_byte_order, &d); 1143548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->order = order; 1144548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (data->priv->md) 1145548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_mnote_data_set_byte_order (data->priv->md, order); 1146548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1147548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1148548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1149548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_log (ExifData *data, ExifLog *log) 1150548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1151548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1152548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1153548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv) 1154548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1155548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log_unref (data->priv->log); 1156548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen data->priv->log = log; 1157548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log_ref (log); 1158548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1159548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; i < EXIF_IFD_COUNT; i++) 1160548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_log (data->ifd[i], log); 1161548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1162548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1163548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen/* Used internally within libexif */ 1164548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifLog *exif_data_get_log (ExifData *); 1165548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifLog * 1166548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_get_log (ExifData *data) 1167548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1168548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!data || !data->priv) 1169548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return NULL; 1170548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return data->priv->log; 1171548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1172548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1173548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic const struct { 1174548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen ExifDataOption option; 1175548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const char *name; 1176548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen const char *description; 1177548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} exif_data_option[] = { 1178548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen {EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS, N_("Ignore unknown tags"), 1179548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen N_("Ignore unknown tags when loading EXIF data.")}, 1180548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen {EXIF_DATA_OPTION_FOLLOW_SPECIFICATION, N_("Follow specification"), 1181548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen N_("Add, correct and remove entries to get EXIF data that follows " 1182548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "the specification.")}, 1183548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen {EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE, N_("Do not change maker note"), 1184548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen N_("When loading and resaving Exif data, save the maker note unmodified." 1185548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen " Be aware that the maker note can get corrupted.")}, 1186548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen {0, NULL, NULL} 1187548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen}; 1188548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1189548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenconst char * 1190548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_option_get_name (ExifDataOption o) 1191548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1192548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1193548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1194548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; exif_data_option[i].name; i++) 1195548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (exif_data_option[i].option == o) 1196548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 1197548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return _(exif_data_option[i].name); 1198548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1199548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1200548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenconst char * 1201548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_option_get_description (ExifDataOption o) 1202548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1203548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int i; 1204548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1205548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen for (i = 0; exif_data_option[i].description; i++) 1206548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (exif_data_option[i].option == o) 1207548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 1208548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return _(exif_data_option[i].description); 1209548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1210548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1211548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1212548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_set_option (ExifData *d, ExifDataOption o) 1213548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1214548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d) 1215548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1216548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1217548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->priv->options |= o; 1218548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1219548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1220548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1221548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_unset_option (ExifData *d, ExifDataOption o) 1222548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1223548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d) 1224548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1225548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1226548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->priv->options &= ~o; 1227548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1228548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1229548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenstatic void 1230548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenfix_func (ExifContent *c, void *UNUSED(data)) 1231548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1232548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen switch (exif_content_get_ifd (c)) { 1233548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen case EXIF_IFD_1: 1234548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (c->parent->data) 1235548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_fix (c); 1236548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen else if (c->count) { 1237548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data", 1238548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "No thumbnail but entries on thumbnail. These entries have been " 1239548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "removed."); 1240548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen while (c->count) { 1241548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen unsigned int cnt = c->count; 1242548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_remove_entry (c, c->entries[c->count - 1]); 1243548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (cnt == c->count) { 1244548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen /* safety net */ 1245548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_log (c->parent->priv->log, EXIF_LOG_CODE_DEBUG, "exif-data", 1246548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen "failed to remove last entry from entries."); 1247548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen c->count--; 1248548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1249548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1250548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1251548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen break; 1252548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen default: 1253548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_content_fix (c); 1254548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen } 1255548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1256548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1257548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1258548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_fix (ExifData *d) 1259548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1260548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen exif_data_foreach_content (d, fix_func, NULL); 1261548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1262548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1263548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenvoid 1264548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_set_data_type (ExifData *d, ExifDataType dt) 1265548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1266548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen if (!d || !d->priv) 1267548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return; 1268548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1269548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen d->priv->data_type = dt; 1270548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1271548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen 1272548dde4863e9a2315e3f327efe63ff55949addb8Marco NelissenExifDataType 1273548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissenexif_data_get_data_type (ExifData *d) 1274548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen{ 1275548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen return (d && d->priv) ? d->priv->data_type : EXIF_DATA_TYPE_UNKNOWN; 1276548dde4863e9a2315e3f327efe63ff55949addb8Marco Nelissen} 1277