1 /* exif-mnote-data-olympus.c
3 * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA.
22 #include "exif-mnote-data-olympus.h"
28 #include <libexif/exif-utils.h>
29 #include <libexif/exif-data.h>
31 /* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best
32 * not to in most cases because it seems to only affect the thumbnail tag
33 * which is duplicated in IFD 1, and fixing the offset could actually cause
34 * problems with other software that expects the broken form.
36 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
38 static enum OlympusVersion
39 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
40 unsigned int buf_size);
44 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
46 ExifMnoteData *d = (ExifMnoteData *) n;
52 for (i = 0; i < n->count; i++)
53 if (n->entries[i].data) {
54 exif_mem_free (d->mem, n->entries[i].data);
55 n->entries[i].data = NULL;
57 exif_mem_free (d->mem, n->entries);
64 exif_mnote_data_olympus_free (ExifMnoteData *n)
68 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
72 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
74 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
76 if (!d || !val) return NULL;
77 if (i > n->count -1) return NULL;
79 exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
80 "Querying value for tag '%s'...",
81 mnote_olympus_tag_get_name (n->entries[i].tag));
83 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
90 * @brief save the MnoteData from ne to buf
92 * @param ne extract the data from this structure
93 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
94 * @param buf_size the size of the buffer
97 exif_mnote_data_olympus_save (ExifMnoteData *ne,
98 unsigned char **buf, unsigned int *buf_size)
100 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
101 size_t i, o, s, doff, base = 0, o2 = 6 + 2;
106 if (!n || !buf || !buf_size) return;
109 * Allocate enough memory for all entries and the number of entries.
111 *buf_size = 6 + 2 + 2 + n->count * 12;
112 switch (n->version) {
116 *buf = exif_mem_alloc (ne->mem, *buf_size);
118 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
122 /* Write the header and the number of entries. */
123 strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
124 (n->version==epsonV1?"EPSON":"OLYMP"));
125 exif_set_short (*buf + 6, n->order, (ExifShort) 1);
130 *buf_size += 8-6 + 4;
131 *buf = exif_mem_alloc (ne->mem, *buf_size);
133 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
137 /* Write the header and the number of entries. */
138 strcpy ((char *)*buf, "OLYMPUS");
139 exif_set_short (*buf + 8, n->order, (ExifShort) (
140 (n->order == EXIF_BYTE_ORDER_INTEL) ?
143 exif_set_short (*buf + 10, n->order, (ExifShort) 3);
148 base = MNOTE_NIKON1_TAG_BASE;
150 /* v1 has offsets based to main IFD, not makernote IFD */
151 datao += n->offset + 10;
152 /* subtract the size here, so the increment in the next case will not harm us */
154 /* Fall through to nikonV2 handler */
156 /* Write out V0 files in V2 format */
159 *buf_size += 4; /* Next IFD pointer */
160 *buf = exif_mem_alloc (ne->mem, *buf_size);
162 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
166 /* Write the header and the number of entries. */
167 strcpy ((char *)*buf, "Nikon");
168 (*buf)[6] = n->version;
170 if (n->version != nikonV1) {
171 exif_set_short (*buf + 10, n->order, (ExifShort) (
172 (n->order == EXIF_BYTE_ORDER_INTEL) ?
175 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
176 exif_set_long (*buf + 14, n->order, (ExifShort) 8);
180 /* Reset next IFD pointer */
181 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
188 exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
191 /* Save each entry */
192 for (i = 0; i < n->count; i++) {
194 exif_set_short (*buf + o + 0, n->order,
195 (ExifShort) (n->entries[i].tag - base));
196 exif_set_short (*buf + o + 2, n->order,
197 (ExifShort) n->entries[i].format);
198 exif_set_long (*buf + o + 4, n->order,
199 n->entries[i].components);
201 s = exif_format_get_size (n->entries[i].format) *
202 n->entries[i].components;
204 /* Corrupt data: EXIF data size is limited to the
205 * maximum size of a JPEG segment (64 kb).
212 t = exif_mem_realloc (ne->mem, *buf,
215 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
220 exif_set_long (*buf + o, n->order, datao + doff);
224 /* Write the data. */
225 if (n->entries[i].data) {
226 memcpy (*buf + doff, n->entries[i].data, s);
228 /* Most certainly damaged input file */
229 memset (*buf + doff, 0, s);
235 exif_mnote_data_olympus_load (ExifMnoteData *en,
236 const unsigned char *buf, unsigned int buf_size)
238 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
240 size_t i, tcount, o, o2, datao = 6, base = 0;
242 if (!n || !buf || !buf_size) {
243 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
244 "ExifMnoteDataOlympus", "Short MakerNote");
247 o2 = 6 + n->offset; /* Start of interesting data */
248 if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
249 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
250 "ExifMnoteDataOlympus", "Short MakerNote");
255 * Olympus headers start with "OLYMP" and need to have at least
256 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
257 * number of entries, and 12 for one entry.
259 * Sanyo format is identical and uses identical tags except that
260 * header starts with "SANYO".
262 * Epson format is identical and uses identical tags except that
263 * header starts with "EPSON".
265 * Nikon headers start with "Nikon" (6 bytes including '\0'),
266 * version number (1 or 2).
268 * Version 1 continues with 0, 1, 0, number_of_tags,
269 * or just with number_of_tags (models D1H, D1X...).
271 * Version 2 continues with an unknown byte (0 or 10),
272 * two unknown bytes (0), "MM" or "II", another byte 0 and
275 n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
276 switch (n->version) {
280 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
281 "Parsing Olympus/Sanyo/Epson maker note v1...");
283 /* The number of entries is at position 8. */
284 if (buf[o2 + 6] == 1)
285 n->order = EXIF_BYTE_ORDER_INTEL;
286 else if (buf[o2 + 6 + 1] == 1)
287 n->order = EXIF_BYTE_ORDER_MOTOROLA;
289 if (o2 + 2 > buf_size) return;
290 c = exif_get_short (buf + o2, n->order);
291 if ((!(c & 0xFF)) && (c > 0x500)) {
292 if (n->order == EXIF_BYTE_ORDER_INTEL) {
293 n->order = EXIF_BYTE_ORDER_MOTOROLA;
295 n->order = EXIF_BYTE_ORDER_INTEL;
301 /* Olympus S760, S770 */
304 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
305 "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
306 buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
308 if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
309 n->order = EXIF_BYTE_ORDER_INTEL;
310 else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
311 n->order = EXIF_BYTE_ORDER_MOTOROLA;
313 /* The number of entries is at position 8+4. */
319 if (o2 >= buf_size) return;
320 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
321 "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
322 "%02x, %02x, %02x, %02x, %02x)...",
323 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
324 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
326 /* Skip version number */
329 /* Skip an unknown byte (00 or 0A). */
332 base = MNOTE_NIKON1_TAG_BASE;
333 /* Fix endianness, if needed */
334 if (o2 + 2 > buf_size) return;
335 c = exif_get_short (buf + o2, n->order);
336 if ((!(c & 0xFF)) && (c > 0x500)) {
337 if (n->order == EXIF_BYTE_ORDER_INTEL) {
338 n->order = EXIF_BYTE_ORDER_MOTOROLA;
340 n->order = EXIF_BYTE_ORDER_INTEL;
347 if (o2 >= buf_size) return;
348 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
349 "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
350 "%02x, %02x, %02x, %02x, %02x)...",
351 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
352 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
354 /* Skip version number */
357 /* Skip an unknown byte (00 or 0A). */
360 /* Skip 2 unknown bytes (00 00). */
364 * Byte order. From here the data offset
368 if (o2 >= buf_size) return;
369 if (!strncmp ((char *)&buf[o2], "II", 2))
370 n->order = EXIF_BYTE_ORDER_INTEL;
371 else if (!strncmp ((char *)&buf[o2], "MM", 2))
372 n->order = EXIF_BYTE_ORDER_MOTOROLA;
374 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
375 "ExifMnoteDataOlympus", "Unknown "
376 "byte order '%c%c'", buf[o2],
382 /* Skip 2 unknown bytes (00 2A). */
385 /* Go to where the number of entries is. */
386 if (o2 + 4 > buf_size) return;
387 o2 = datao + exif_get_long (buf + o2, n->order);
391 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
392 "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
393 "%02x, %02x, %02x, %02x, %02x)...",
394 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
395 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
396 /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
397 n->order = EXIF_BYTE_ORDER_MOTOROLA;
401 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
402 "Unknown Olympus variant %i.", n->version);
406 /* Sanity check the offset */
407 if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
408 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
409 "ExifMnoteOlympus", "Short MakerNote");
413 /* Read the number of tags */
414 c = exif_get_short (buf + o2, n->order);
417 /* Remove any old entries */
418 exif_mnote_data_olympus_clear (n);
420 /* Reserve enough space for all the possible MakerNote tags */
421 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
423 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
427 /* Parse all c entries, storing ones that are successfully parsed */
429 for (i = c, o = o2; i; --i, o += 12) {
431 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
432 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
433 "ExifMnoteOlympus", "Short MakerNote");
437 n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base;
438 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
439 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
440 n->entries[tcount].order = n->order;
442 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
443 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
444 mnote_olympus_tag_get_name (n->entries[tcount].tag));
445 /* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
447 n->entries[tcount].tag,
448 n->entries[tcount].format,
449 n->entries[tcount].components,
450 (int)exif_format_get_size(n->entries[tcount].format)); */
453 * Size? If bigger than 4 bytes, the actual data is not
454 * in the entry but somewhere else (offset).
456 s = exif_format_get_size (n->entries[tcount].format) *
457 n->entries[tcount].components;
458 n->entries[tcount].size = s;
460 size_t dataofs = o + 8;
462 /* The data in this case is merely a pointer */
463 dataofs = exif_get_long (buf + dataofs, n->order) + datao;
464 #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
465 /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
466 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
467 * tag in its MakerNote. The offset is actually the absolute
468 * position in the file instead of the position within the IFD.
470 if (dataofs + s > buf_size && n->version == sanyoV1) {
472 dataofs -= datao + 6;
473 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
475 "Inconsistent thumbnail tag offset; attempting to recover");
479 if ((dataofs + s < dataofs) || (dataofs + s < s) ||
480 (dataofs + s > buf_size)) {
481 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
483 "Tag data past end of buffer (%u > %u)",
484 (unsigned)(dataofs + s), buf_size);
488 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
489 if (!n->entries[tcount].data) {
490 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
493 memcpy (n->entries[tcount].data, buf + dataofs, s);
496 /* Tag was successfully parsed */
499 /* Store the count of successfully parsed tags */
504 exif_mnote_data_olympus_count (ExifMnoteData *n)
506 return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
510 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
512 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
515 if (note->count <= n) return 0;
516 return note->entries[n].tag;
520 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
522 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
525 if (i >= n->count) return NULL;
526 return mnote_olympus_tag_get_name (n->entries[i].tag);
530 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
532 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
535 if (i >= n->count) return NULL;
536 return mnote_olympus_tag_get_title (n->entries[i].tag);
540 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
542 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
545 if (i >= n->count) return NULL;
546 return mnote_olympus_tag_get_description (n->entries[i].tag);
550 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
552 ExifByteOrder o_orig;
553 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
560 for (i = 0; i < n->count; i++) {
561 n->entries[i].order = o;
562 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
563 n->entries[i].components, o_orig, o);
568 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
570 if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
573 static enum OlympusVersion
574 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
575 unsigned int buf_size)
577 /* Olympus, Nikon, Sanyo, Epson */
579 /* Match the terminating NUL character, too */
580 if (!memcmp (buf, "OLYMPUS", 8))
582 else if (!memcmp (buf, "OLYMP", 6))
584 else if (!memcmp (buf, "SANYO", 6))
586 else if (!memcmp (buf, "EPSON", 6))
588 else if (!memcmp (buf, "Nikon", 6)) {
590 case 1: return nikonV1;
591 case 2: return nikonV2;
592 default: return 0; /* Unrecognized Nikon variant */
597 /* Another variant of Nikon */
598 if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
606 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
608 int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
610 if (variant == nikonV0) {
611 /* This variant needs some extra checking with the Make */
613 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
614 variant = unrecognized;
617 const char *v = exif_entry_get_value (em, value, sizeof(value));
618 if (v && (!strncmp (v, "Nikon", sizeof(value)) ||
619 !strncmp (v, "NIKON", sizeof(value)) ))
620 /* When saved, this variant will be written out like the
621 * alternative nikonV2 form above instead
632 exif_mnote_data_olympus_new (ExifMem *mem)
636 if (!mem) return NULL;
638 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
641 exif_mnote_data_construct (d, mem);
643 /* Set up function pointers */
644 d->methods.free = exif_mnote_data_olympus_free;
645 d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
646 d->methods.set_offset = exif_mnote_data_olympus_set_offset;
647 d->methods.load = exif_mnote_data_olympus_load;
648 d->methods.save = exif_mnote_data_olympus_save;
649 d->methods.count = exif_mnote_data_olympus_count;
650 d->methods.get_id = exif_mnote_data_olympus_get_id;
651 d->methods.get_name = exif_mnote_data_olympus_get_name;
652 d->methods.get_title = exif_mnote_data_olympus_get_title;
653 d->methods.get_description = exif_mnote_data_olympus_get_description;
654 d->methods.get_value = exif_mnote_data_olympus_get_value;