exif-mnote-data-fuji.c

Go to the documentation of this file.
00001 /* exif-mnote-data-fuji.c
00002  *
00003  * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful, 
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details. 
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA  02110-1301  USA.
00019  */
00020 
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 
00025 #include <config.h>
00026 #include <libexif/exif-byte-order.h>
00027 #include <libexif/exif-utils.h>
00028 
00029 #include "exif-mnote-data-fuji.h"
00030 
00031 struct _MNoteFujiDataPrivate {
00032         ExifByteOrder order;
00033 };
00034 
00035 static void
00036 exif_mnote_data_fuji_clear (ExifMnoteDataFuji *n)
00037 {
00038         ExifMnoteData *d = (ExifMnoteData *) n;
00039         unsigned int i;
00040 
00041         if (!n) return;
00042 
00043         if (n->entries) {
00044                 for (i = 0; i < n->count; i++)
00045                         if (n->entries[i].data) {
00046                                 exif_mem_free (d->mem, n->entries[i].data);
00047                                 n->entries[i].data = NULL;
00048                         }
00049                 exif_mem_free (d->mem, n->entries);
00050                 n->entries = NULL;
00051                 n->count = 0;
00052         }
00053 }
00054 
00055 static void
00056 exif_mnote_data_fuji_free (ExifMnoteData *n)
00057 {
00058         if (!n) return;
00059 
00060         exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n);
00061 }
00062 
00063 static char *
00064 exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
00065 {
00066         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
00067 
00068         if (!d || !val) return NULL;
00069         if (i > n->count -1) return NULL;
00070 /*
00071         exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
00072                   "Querying value for tag '%s'...",
00073                   mnote_fuji_tag_get_name (n->entries[i].tag));
00074 */
00075         return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen);
00076 }
00077 
00078 static void
00079 exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
00080                            unsigned int *buf_size)
00081 {
00082         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
00083         size_t i, o, s, doff;
00084         unsigned char *t;
00085         size_t ts;
00086 
00087         if (!n || !buf || !buf_size) return;
00088 
00089         /*
00090          * Allocate enough memory for all entries and the number
00091          * of entries.
00092          */
00093         *buf_size = 8 + 4 + 2 + n->count * 12 + 4;
00094         *buf = exif_mem_alloc (ne->mem, *buf_size);
00095         if (!*buf) {
00096                 *buf_size = 0;
00097                 return;
00098         }
00099 
00100         /*
00101          * Header: "FUJIFILM" and 4 bytes offset to the first entry.
00102          * As the first entry will start right thereafter, the offset is 12.
00103          */
00104         memcpy (*buf, "FUJIFILM", 8);
00105         exif_set_long (*buf + 8, n->order, 12);
00106 
00107         /* Save the number of entries */
00108         exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
00109         
00110         /* Save each entry */
00111         for (i = 0; i < n->count; i++) {
00112                 o = 8 + 4 + 2 + i * 12;
00113                 exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
00114                 exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
00115                 exif_set_long  (*buf + o + 4, n->order, n->entries[i].components);
00116                 o += 8;
00117                 s = exif_format_get_size (n->entries[i].format) *
00118                                                 n->entries[i].components;
00119                 if (s > 65536) {
00120                         /* Corrupt data: EXIF data size is limited to the
00121                          * maximum size of a JPEG segment (64 kb).
00122                          */
00123                         continue;
00124                 }
00125                 if (s > 4) {
00126                         ts = *buf_size + s;
00127 
00128                         /* Ensure even offsets. Set padding bytes to 0. */
00129                         if (s & 1) ts += 1;
00130                         t = exif_mem_realloc (ne->mem, *buf, ts);
00131                         if (!t) {
00132                                 return;
00133                         }
00134                         *buf = t;
00135                         *buf_size = ts;
00136                         doff = *buf_size - s;
00137                         if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
00138                         exif_set_long (*buf + o, n->order, doff);
00139                 } else
00140                         doff = o;
00141 
00142                 /*
00143                  * Write the data. Fill unneeded bytes with 0. Do not
00144                  * crash if data is NULL.
00145                  */
00146                 if (!n->entries[i].data) memset (*buf + doff, 0, s);
00147                 else memcpy (*buf + doff, n->entries[i].data, s);
00148         }
00149 }
00150 
00151 static void
00152 exif_mnote_data_fuji_load (ExifMnoteData *en,
00153         const unsigned char *buf, unsigned int buf_size)
00154 {
00155         ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
00156         ExifLong c;
00157         size_t i, tcount, o, datao;
00158 
00159         if (!n || !buf || !buf_size) {
00160                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00161                           "ExifMnoteDataFuji", "Short MakerNote");
00162                 return;
00163         }
00164         datao = 6 + n->offset;
00165         if ((datao + 12 < datao) || (datao + 12 < 12) || (datao + 12 > buf_size)) {
00166                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00167                           "ExifMnoteDataFuji", "Short MakerNote");
00168                 return;
00169         }
00170 
00171         n->order = EXIF_BYTE_ORDER_INTEL;
00172         datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
00173         if ((datao + 2 < datao) || (datao + 2 < 2) ||
00174             (datao + 2 > buf_size)) {
00175                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00176                           "ExifMnoteDataFuji", "Short MakerNote");
00177                 return;
00178         }
00179 
00180         /* Read the number of tags */
00181         c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
00182         datao += 2;
00183 
00184         /* Remove any old entries */
00185         exif_mnote_data_fuji_clear (n);
00186 
00187         /* Reserve enough space for all the possible MakerNote tags */
00188         n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
00189         if (!n->entries) {
00190                 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
00191                 return;
00192         }
00193 
00194         /* Parse all c entries, storing ones that are successfully parsed */
00195         tcount = 0;
00196         for (i = c, o = datao; i; --i, o += 12) {
00197                 size_t s;
00198                 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
00199                         exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00200                                   "ExifMnoteDataFuji", "Short MakerNote");
00201                         break;
00202                 }
00203 
00204                 n->entries[tcount].tag        = exif_get_short (buf + o, n->order);
00205                 n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
00206                 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
00207                 n->entries[tcount].order      = n->order;
00208 
00209                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
00210                           "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
00211                           mnote_fuji_tag_get_name (n->entries[tcount].tag));
00212 
00213                 /*
00214                  * Size? If bigger than 4 bytes, the actual data is not
00215                  * in the entry but somewhere else (offset).
00216                  */
00217                 s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
00218                 n->entries[tcount].size = s;
00219                 if (s) {
00220                         size_t dataofs = o + 8;
00221                         if (s > 4)
00222                                 /* The data in this case is merely a pointer */
00223                                 dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
00224                         if ((dataofs + s < dataofs) || (dataofs + s < s) ||
00225                                 (dataofs + s >= buf_size)) {
00226                                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00227                                                   "ExifMnoteDataFuji", "Tag data past end of "
00228                                           "buffer (%u >= %u)", dataofs + s, buf_size);
00229                                 continue;
00230                         }
00231 
00232                         n->entries[tcount].data = exif_mem_alloc (en->mem, s);
00233                         if (!n->entries[tcount].data) {
00234                                 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
00235                                 continue;
00236                         }
00237                         memcpy (n->entries[tcount].data, buf + dataofs, s);
00238                 }
00239 
00240                 /* Tag was successfully parsed */
00241                 ++tcount;
00242         }
00243         /* Store the count of successfully parsed tags */
00244         n->count = tcount;
00245 }
00246 
00247 static unsigned int
00248 exif_mnote_data_fuji_count (ExifMnoteData *n)
00249 {
00250         return n ? ((ExifMnoteDataFuji *) n)->count : 0;
00251 }
00252 
00253 static unsigned int
00254 exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
00255 {
00256         ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
00257 
00258         if (!note) return 0;
00259         if (note->count <= n) return 0;
00260         return note->entries[n].tag;
00261 }
00262 
00263 static const char *
00264 exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
00265 {
00266         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
00267 
00268         if (!n) return NULL;
00269         if (i >= n->count) return NULL;
00270         return mnote_fuji_tag_get_name (n->entries[i].tag);
00271 }
00272 
00273 static const char *
00274 exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
00275 {
00276         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
00277         
00278         if (!n) return NULL;
00279         if (i >= n->count) return NULL;
00280         return mnote_fuji_tag_get_title (n->entries[i].tag);
00281 }
00282 
00283 static const char *
00284 exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
00285 {
00286         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
00287         
00288         if (!n) return NULL;
00289         if (i >= n->count) return NULL;
00290         return mnote_fuji_tag_get_description (n->entries[i].tag);
00291 }
00292 
00293 static void
00294 exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
00295 {
00296         ExifByteOrder o_orig;
00297         ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
00298         unsigned int i;
00299 
00300         if (!n) return;
00301 
00302         o_orig = n->order;
00303         n->order = o;
00304         for (i = 0; i < n->count; i++) {
00305                 n->entries[i].order = o;
00306                 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
00307                                 n->entries[i].components, o_orig, o);
00308         }
00309 }
00310 
00311 static void
00312 exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
00313 {
00314         if (n) ((ExifMnoteDataFuji *) n)->offset = o;
00315 }
00316 
00317 int
00318 exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
00319 {
00320         return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
00321 }
00322 
00323 ExifMnoteData *
00324 exif_mnote_data_fuji_new (ExifMem *mem)
00325 {
00326         ExifMnoteData *d;
00327 
00328         if (!mem) return NULL;
00329 
00330         d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
00331         if (!d) return NULL;
00332 
00333         exif_mnote_data_construct (d, mem);
00334 
00335         /* Set up function pointers */
00336         d->methods.free            = exif_mnote_data_fuji_free;
00337         d->methods.set_byte_order  = exif_mnote_data_fuji_set_byte_order;
00338         d->methods.set_offset      = exif_mnote_data_fuji_set_offset;
00339         d->methods.load            = exif_mnote_data_fuji_load;
00340         d->methods.save            = exif_mnote_data_fuji_save;
00341         d->methods.count           = exif_mnote_data_fuji_count;
00342         d->methods.get_id          = exif_mnote_data_fuji_get_id;
00343         d->methods.get_name        = exif_mnote_data_fuji_get_name;
00344         d->methods.get_title       = exif_mnote_data_fuji_get_title;
00345         d->methods.get_description = exif_mnote_data_fuji_get_description;
00346         d->methods.get_value       = exif_mnote_data_fuji_get_value;
00347 
00348         return d;
00349 }

SourceForge.net Logo Generated by doxygen