exif-mnote-data-olympus.c

Go to the documentation of this file.
00001 /* exif-mnote-data-olympus.c
00002  *
00003  * Copyright (c) 2002, 2003 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 <config.h>
00022 #include "exif-mnote-data-olympus.h"
00023 
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <stdio.h>
00027 
00028 #include <libexif/exif-utils.h>
00029 #include <libexif/exif-data.h>
00030 
00031 #define DEBUG
00032 
00033 /* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best
00034  * not to in most cases because it seems to only affect the thumbnail tag
00035  * which is duplicated in IFD 1, and fixing the offset could actually cause
00036  * problems with other software that expects the broken form.
00037  */
00038 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
00039 
00040 static enum OlympusVersion
00041 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
00042                 unsigned int buf_size);
00043 
00044 
00045 static void
00046 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
00047 {
00048         ExifMnoteData *d = (ExifMnoteData *) n;
00049         unsigned int i;
00050 
00051         if (!n) return;
00052 
00053         if (n->entries) {
00054                 for (i = 0; i < n->count; i++)
00055                         if (n->entries[i].data) {
00056                                 exif_mem_free (d->mem, n->entries[i].data);
00057                                 n->entries[i].data = NULL;
00058                         }
00059                 exif_mem_free (d->mem, n->entries);
00060                 n->entries = NULL;
00061                 n->count = 0;
00062         }
00063 }
00064 
00065 static void
00066 exif_mnote_data_olympus_free (ExifMnoteData *n)
00067 {
00068         if (!n) return;
00069 
00070         exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
00071 }
00072 
00073 static char *
00074 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
00075 {
00076         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00077 
00078         if (!d || !val) return NULL;
00079         if (i > n->count -1) return NULL;
00080 /*
00081         exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00082                   "Querying value for tag '%s'...",
00083                   mnote_olympus_tag_get_name (n->entries[i].tag));
00084 */
00085         return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
00086 }
00087 
00088 
00089 
00090 
00098 static void
00099 exif_mnote_data_olympus_save (ExifMnoteData *ne,
00100                 unsigned char **buf, unsigned int *buf_size)
00101 {
00102         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
00103         size_t i, o, s, doff, base = 0, o2 = 6 + 2;
00104         size_t datao = 0;
00105         unsigned char *t;
00106         size_t ts;
00107 
00108         if (!n || !buf || !buf_size) return;
00109 
00110         /*
00111          * Allocate enough memory for all entries and the number of entries.
00112          */
00113         *buf_size = 6 + 2 + 2 + n->count * 12;
00114         switch (n->version) {
00115         case olympusV1:
00116         case sanyoV1:
00117         case epsonV1:
00118                 *buf = exif_mem_alloc (ne->mem, *buf_size);
00119                 if (!*buf) {
00120                         EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00121                         return;
00122                 }
00123 
00124                 /* Write the header and the number of entries. */
00125                 strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
00126                                         (n->version==epsonV1?"EPSON":"OLYMP"));
00127                 exif_set_short (*buf + 6, n->order, (ExifShort) 1);
00128                 datao = n->offset;
00129                 break;
00130 
00131         case olympusV2:
00132                 *buf_size += 8-6 + 4;
00133                 *buf = exif_mem_alloc (ne->mem, *buf_size);
00134                 if (!*buf) {
00135                         EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00136                         return;
00137                 }
00138 
00139                 /* Write the header and the number of entries. */
00140                 strcpy ((char *)*buf, "OLYMPUS");
00141                 exif_set_short (*buf + 8, n->order, (ExifShort) (
00142                         (n->order == EXIF_BYTE_ORDER_INTEL) ?
00143                         ('I' << 8) | 'I' :
00144                         ('M' << 8) | 'M'));
00145                 exif_set_short (*buf + 10, n->order, (ExifShort) 3);
00146                 o2 += 4;
00147                 break;
00148 
00149         case nikonV1: 
00150                 base = MNOTE_NIKON1_TAG_BASE;
00151 
00152                 /* v1 has offsets based to main IFD, not makernote IFD */
00153                 datao += n->offset + 10;
00154                 /* subtract the size here, so the increment in the next case will not harm us */
00155                 *buf_size -= 8 + 2;
00156         /* Fall through to nikonV2 handler */
00157         case nikonV2: 
00158         /* Write out V0 files in V2 format */
00159         case nikonV0: 
00160                 *buf_size += 8 + 2;
00161                 *buf_size += 4; /* Next IFD pointer */
00162                 *buf = exif_mem_alloc (ne->mem, *buf_size);
00163                 if (!*buf) {
00164                         EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
00165                         return;
00166                 }
00167 
00168                 /* Write the header and the number of entries. */
00169                 strcpy ((char *)*buf, "Nikon");
00170                 (*buf)[6] = n->version;
00171 
00172                 if (n->version != nikonV1) {
00173                         exif_set_short (*buf + 10, n->order, (ExifShort) (
00174                                 (n->order == EXIF_BYTE_ORDER_INTEL) ?
00175                                 ('I' << 8) | 'I' :
00176                                 ('M' << 8) | 'M'));
00177                         exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
00178                         exif_set_long (*buf + 14, n->order, (ExifShort) 8);
00179                         o2 += 2 + 8;
00180                 }
00181                 datao -= 10;
00182                 /* Reset next IFD pointer */
00183                 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
00184                 break;
00185 
00186         default:
00187                 return;
00188         }
00189 
00190         exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
00191         o2 += 2;
00192 
00193         /* Save each entry */
00194         for (i = 0; i < n->count; i++) {
00195                 o = o2 + i * 12;
00196                 exif_set_short (*buf + o + 0, n->order,
00197                                 (ExifShort) (n->entries[i].tag - base));
00198                 exif_set_short (*buf + o + 2, n->order,
00199                                 (ExifShort) n->entries[i].format);
00200                 exif_set_long  (*buf + o + 4, n->order,
00201                                 n->entries[i].components);
00202                 o += 8;
00203                 s = exif_format_get_size (n->entries[i].format) *
00204                                                 n->entries[i].components;
00205                 if (s > 65536) {
00206                         /* Corrupt data: EXIF data size is limited to the
00207                          * maximum size of a JPEG segment (64 kb).
00208                          */
00209                         continue;
00210                 }
00211                 if (s > 4) {
00212                         doff = *buf_size;
00213                         ts = *buf_size + s;
00214                         t = exif_mem_realloc (ne->mem, *buf,
00215                                                  sizeof (char) * ts);
00216                         if (!t) {
00217                                 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
00218                                 return;
00219                         }
00220                         *buf = t;
00221                         *buf_size = ts;
00222                         exif_set_long (*buf + o, n->order, datao + doff);
00223                 } else
00224                         doff = o;
00225 
00226                 /* Write the data. */
00227                 if (n->entries[i].data) {
00228                         memcpy (*buf + doff, n->entries[i].data, s);
00229                 } else {
00230                         /* Most certainly damaged input file */
00231                         memset (*buf + doff, 0, s);
00232                 }
00233         }
00234 }
00235 
00236 static void
00237 exif_mnote_data_olympus_load (ExifMnoteData *en,
00238                               const unsigned char *buf, unsigned int buf_size)
00239 {
00240         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
00241         ExifShort c;
00242         size_t i, tcount, o, o2, datao = 6, base = 0;
00243 
00244         if (!n || !buf || !buf_size) {
00245                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00246                           "ExifMnoteDataOlympus", "Short MakerNote");
00247                 return;
00248         }
00249         o2 = 6 + n->offset; /* Start of interesting data */
00250         if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
00251                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00252                           "ExifMnoteDataOlympus", "Short MakerNote");
00253                 return;
00254         }
00255 
00256         /*
00257          * Olympus headers start with "OLYMP" and need to have at least
00258          * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
00259          * number of entries, and 12 for one entry.
00260          *
00261          * Sanyo format is identical and uses identical tags except that
00262          * header starts with "SANYO".
00263          *
00264          * Epson format is identical and uses identical tags except that
00265          * header starts with "EPSON".
00266          *
00267          * Nikon headers start with "Nikon" (6 bytes including '\0'), 
00268          * version number (1 or 2).
00269          * 
00270          * Version 1 continues with 0, 1, 0, number_of_tags,
00271          * or just with number_of_tags (models D1H, D1X...).
00272          * 
00273          * Version 2 continues with an unknown byte (0 or 10),
00274          * two unknown bytes (0), "MM" or "II", another byte 0 and 
00275          * lastly 0x2A.
00276          */
00277         n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
00278         switch (n->version) {
00279         case olympusV1:
00280         case sanyoV1:
00281         case epsonV1:
00282                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00283                         "Parsing Olympus/Sanyo/Epson maker note v1...");
00284 
00285                 /* The number of entries is at position 8. */
00286                 if (buf[o2 + 6] == 1)
00287                         n->order = EXIF_BYTE_ORDER_INTEL;
00288                 else if (buf[o2 + 6 + 1] == 1)
00289                         n->order = EXIF_BYTE_ORDER_MOTOROLA;
00290                 o2 += 8;
00291                 if (o2 + 2 > buf_size) return;
00292                 c = exif_get_short (buf + o2, n->order);
00293                 if ((!(c & 0xFF)) && (c > 0x500)) {
00294                         if (n->order == EXIF_BYTE_ORDER_INTEL) {
00295                                 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00296                         } else {
00297                                 n->order = EXIF_BYTE_ORDER_INTEL;
00298                         }
00299                 }
00300                 break;
00301 
00302         case olympusV2:
00303                 /* Olympus S760, S770 */
00304                 datao = o2;
00305                 o2 += 8;
00306                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00307                         "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
00308                         buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
00309 
00310                 if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
00311                         n->order = EXIF_BYTE_ORDER_INTEL;
00312                 else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
00313                         n->order = EXIF_BYTE_ORDER_MOTOROLA;
00314 
00315                 /* The number of entries is at position 8+4. */
00316                 o2 += 4;
00317                 break;
00318 
00319         case nikonV1:
00320                 o2 += 6;
00321                 if (o2 >= buf_size) return;
00322                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00323                         "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
00324                         "%02x, %02x, %02x, %02x, %02x)...",
00325                         buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], 
00326                         buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00327 
00328                 /* Skip version number */
00329                 o2 += 1;
00330 
00331                 /* Skip an unknown byte (00 or 0A). */
00332                 o2 += 1;
00333 
00334                 base = MNOTE_NIKON1_TAG_BASE;
00335                 /* Fix endianness, if needed */
00336                 if (o2 + 2 > buf_size) return;
00337                 c = exif_get_short (buf + o2, n->order);
00338                 if ((!(c & 0xFF)) && (c > 0x500)) {
00339                         if (n->order == EXIF_BYTE_ORDER_INTEL) {
00340                                 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00341                         } else {
00342                                 n->order = EXIF_BYTE_ORDER_INTEL;
00343                         }
00344                 }
00345                 break;
00346 
00347         case nikonV2:
00348                 o2 += 6;
00349                 if (o2 >= buf_size) return;
00350                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00351                         "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
00352                         "%02x, %02x, %02x, %02x, %02x)...",
00353                         buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], 
00354                         buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00355 
00356                 /* Skip version number */
00357                 o2 += 1;
00358 
00359                 /* Skip an unknown byte (00 or 0A). */
00360                 o2 += 1;
00361 
00362                 /* Skip 2 unknown bytes (00 00). */
00363                 o2 += 2;
00364 
00365                 /*
00366                  * Byte order. From here the data offset
00367                  * gets calculated.
00368                  */
00369                 datao = o2;
00370                 if (o2 >= buf_size) return;
00371                 if (!strncmp ((char *)&buf[o2], "II", 2))
00372                         n->order = EXIF_BYTE_ORDER_INTEL;
00373                 else if (!strncmp ((char *)&buf[o2], "MM", 2))
00374                         n->order = EXIF_BYTE_ORDER_MOTOROLA;
00375                 else {
00376                         exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00377                                 "ExifMnoteDataOlympus", "Unknown "
00378                                 "byte order '%c%c'", buf[o2],
00379                                 buf[o2 + 1]);
00380                         return;
00381                 }
00382                 o2 += 2;
00383 
00384                 /* Skip 2 unknown bytes (00 2A). */
00385                 o2 += 2;
00386 
00387                 /* Go to where the number of entries is. */
00388                 if (o2 + 4 > buf_size) return;
00389                 o2 = datao + exif_get_long (buf + o2, n->order);
00390                 break;
00391 
00392         case nikonV0:
00393                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00394                         "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
00395                         "%02x, %02x, %02x, %02x, %02x)...",
00396                         buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], 
00397                         buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00398                 /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
00399                 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00400                 break;
00401         
00402         default:
00403                 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00404                         "Unknown Olympus variant %i.", n->version);
00405                 return;
00406         }
00407 
00408         /* Sanity check the offset */
00409         if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
00410                 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00411                           "ExifMnoteOlympus", "Short MakerNote");
00412                 return;
00413         }
00414 
00415         /* Read the number of tags */
00416         c = exif_get_short (buf + o2, n->order);
00417         o2 += 2;
00418 
00419         /* Remove any old entries */
00420         exif_mnote_data_olympus_clear (n);
00421 
00422         /* Reserve enough space for all the possible MakerNote tags */
00423         n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
00424         if (!n->entries) {
00425                 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
00426                 return;
00427         }
00428 
00429         /* Parse all c entries, storing ones that are successfully parsed */
00430         tcount = 0;
00431         for (i = c, o = o2; i; --i, o += 12) {
00432                 size_t s;
00433                 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
00434                         exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
00435                                   "ExifMnoteOlympus", "Short MakerNote");
00436                         break;
00437                 }
00438 
00439             n->entries[tcount].tag        = exif_get_short (buf + o, n->order) + base;
00440             n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
00441             n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
00442             n->entries[tcount].order      = n->order;
00443 
00444             exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
00445                       "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
00446                       mnote_olympus_tag_get_name (n->entries[tcount].tag));
00447 /*          exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
00448                             "0x%x %d %ld*(%d)",
00449                     n->entries[tcount].tag,
00450                     n->entries[tcount].format,
00451                     n->entries[tcount].components,
00452                     (int)exif_format_get_size(n->entries[tcount].format)); */
00453 
00454             /*
00455              * Size? If bigger than 4 bytes, the actual data is not
00456              * in the entry but somewhere else (offset).
00457              */
00458             s = exif_format_get_size (n->entries[tcount].format) *
00459                                          n->entries[tcount].components;
00460                 n->entries[tcount].size = s;
00461                 if (s) {
00462                         size_t dataofs = o + 8;
00463                         if (s > 4) {
00464                                 /* The data in this case is merely a pointer */
00465                                 dataofs = exif_get_long (buf + dataofs, n->order) + datao;
00466 #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
00467                                 /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
00468                                  * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
00469                                  * tag in its MakerNote. The offset is actually the absolute
00470                                  * position in the file instead of the position within the IFD.
00471                                  */
00472                             if (dataofs + s > buf_size && n->version == sanyoV1) {
00473                                         /* fix pointer */
00474                                         dataofs -= datao + 6;
00475                                         exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00476                                                   "ExifMnoteOlympus",
00477                                                   "Inconsistent thumbnail tag offset; attempting to recover");
00478                             }
00479 #endif
00480                         }
00481                         if ((dataofs + s < dataofs) || (dataofs + s < s) || 
00482                             (dataofs + s > buf_size)) {
00483                                 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00484                                           "ExifMnoteOlympus",
00485                                           "Tag data past end of buffer (%u > %u)",
00486                                           dataofs + s, buf_size);
00487                                 continue;
00488                         }
00489 
00490                         n->entries[tcount].data = exif_mem_alloc (en->mem, s);
00491                         if (!n->entries[tcount].data) {
00492                                 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
00493                                 continue;
00494                         }
00495                         memcpy (n->entries[tcount].data, buf + dataofs, s);
00496                 }
00497 
00498                 /* Tag was successfully parsed */
00499                 ++tcount;
00500         }
00501         /* Store the count of successfully parsed tags */
00502         n->count = tcount;
00503 }
00504 
00505 static unsigned int
00506 exif_mnote_data_olympus_count (ExifMnoteData *n)
00507 {
00508         return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
00509 }
00510 
00511 static unsigned int
00512 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
00513 {
00514         ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
00515 
00516         if (!note) return 0;
00517         if (note->count <= n) return 0;
00518         return note->entries[n].tag;
00519 }
00520 
00521 static const char *
00522 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
00523 {
00524         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00525 
00526         if (!n) return NULL;
00527         if (i >= n->count) return NULL;
00528         return mnote_olympus_tag_get_name (n->entries[i].tag);
00529 }
00530 
00531 static const char *
00532 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
00533 {
00534         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00535         
00536         if (!n) return NULL;
00537         if (i >= n->count) return NULL;
00538         return mnote_olympus_tag_get_title (n->entries[i].tag);
00539 }
00540 
00541 static const char *
00542 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
00543 {
00544         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00545         
00546         if (!n) return NULL;
00547         if (i >= n->count) return NULL;
00548         return mnote_olympus_tag_get_description (n->entries[i].tag);
00549 }
00550 
00551 static void
00552 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
00553 {
00554         ExifByteOrder o_orig;
00555         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00556         unsigned int i;
00557 
00558         if (!n) return;
00559 
00560         o_orig = n->order;
00561         n->order = o;
00562         for (i = 0; i < n->count; i++) {
00563                 n->entries[i].order = o;
00564                 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
00565                                 n->entries[i].components, o_orig, o);
00566         }
00567 }
00568 
00569 static void
00570 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
00571 {
00572         if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
00573 }
00574 
00575 static enum OlympusVersion
00576 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
00577                 unsigned int buf_size)
00578 {
00579         /* Olympus, Nikon, Sanyo, Epson */
00580         if (buf_size >= 8) {
00581                 /* Match the terminating NUL character, too */
00582                 if (!memcmp (buf, "OLYMPUS", 8))
00583                            return olympusV2;
00584                 else if (!memcmp (buf, "OLYMP", 6))
00585                            return olympusV1;
00586                 else if (!memcmp (buf, "SANYO", 6))
00587                            return sanyoV1;
00588                 else if (!memcmp (buf, "EPSON", 6))
00589                            return epsonV1;
00590                 else if (!memcmp (buf, "Nikon", 6)) {
00591                         switch (buf[6]) {
00592                                 case 1:  return nikonV1;
00593                                 case 2:  return nikonV2;
00594                                 default: return 0; /* Unrecognized Nikon variant */
00595                         }
00596                 }
00597         }
00598 
00599         /* Another variant of Nikon */
00600         if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
00601                 return nikonV0;
00602         }
00603 
00604         return unrecognized;
00605 }
00606 
00607 int
00608 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
00609 {
00610         int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
00611 
00612         if (variant == nikonV0) {
00613                 /* This variant needs some extra checking with the Make */
00614                 char value[5];
00615                 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
00616                 variant = unrecognized;
00617 
00618                 if (em) {
00619                         const char *v = exif_entry_get_value (em, value, sizeof(value));
00620                         if (v && (!strncmp (v, "Nikon", sizeof(value)) || 
00621                                           !strncmp (v, "NIKON", sizeof(value)) ))
00622                                 /* When saved, this variant will be written out like the
00623                                  * alternative nikonV2 form above instead
00624                                  */
00625                                 variant = nikonV0;
00626                 }
00627         }
00628 
00629         return variant;
00630 }
00631 
00632 
00633 ExifMnoteData *
00634 exif_mnote_data_olympus_new (ExifMem *mem)
00635 {
00636         ExifMnoteData *d;
00637 
00638         if (!mem) return NULL;
00639         
00640         d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
00641         if (!d) return NULL;
00642 
00643         exif_mnote_data_construct (d, mem);
00644 
00645         /* Set up function pointers */
00646         d->methods.free            = exif_mnote_data_olympus_free;
00647         d->methods.set_byte_order  = exif_mnote_data_olympus_set_byte_order;
00648         d->methods.set_offset      = exif_mnote_data_olympus_set_offset;
00649         d->methods.load            = exif_mnote_data_olympus_load;
00650         d->methods.save            = exif_mnote_data_olympus_save;
00651         d->methods.count           = exif_mnote_data_olympus_count;
00652         d->methods.get_id          = exif_mnote_data_olympus_get_id;
00653         d->methods.get_name        = exif_mnote_data_olympus_get_name;
00654         d->methods.get_title       = exif_mnote_data_olympus_get_title;
00655         d->methods.get_description = exif_mnote_data_olympus_get_description;
00656         d->methods.get_value       = exif_mnote_data_olympus_get_value;
00657 
00658         return d;
00659 }

SourceForge.net Logo Generated by doxygen