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>
33 /* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best
34 * not to in most cases because it seems to only affect the thumbnail tag
35 * which is duplicated in IFD 1, and fixing the offset could actually cause
36 * problems with other software that expects the broken form.
38 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
40 static enum OlympusVersion
41 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
42 unsigned int buf_size);
46 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
48 ExifMnoteData *d = (ExifMnoteData *) n;
54 for (i = 0; i < n->count; i++)
55 if (n->entries[i].data) {
56 exif_mem_free (d->mem, n->entries[i].data);
57 n->entries[i].data = NULL;
59 exif_mem_free (d->mem, n->entries);
66 exif_mnote_data_olympus_free (ExifMnoteData *n)
70 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
74 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
76 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
78 if (!d || !val) return NULL;
79 if (i > n->count -1) return NULL;
81 exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
82 "Querying value for tag '%s'...",
83 mnote_olympus_tag_get_name (n->entries[i].tag));
85 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
92 * @brief save the MnoteData from ne to buf
94 * @param ne extract the data from this structure
95 * @param *buf write the mnoteData to this buffer (buffer will be allocated)
96 * @param buf_size the size of the buffer
99 exif_mnote_data_olympus_save (ExifMnoteData *ne,
100 unsigned char **buf, unsigned int *buf_size)
102 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
103 size_t i, o, s, doff, base = 0, o2 = 6 + 2;
108 if (!n || !buf || !buf_size) return;
111 * Allocate enough memory for all entries and the number of entries.
113 *buf_size = 6 + 2 + 2 + n->count * 12;
114 switch (n->version) {
118 *buf = exif_mem_alloc (ne->mem, *buf_size);
120 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
124 /* Write the header and the number of entries. */
125 strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
126 (n->version==epsonV1?"EPSON":"OLYMP"));
127 exif_set_short (*buf + 6, n->order, (ExifShort) 1);
132 *buf_size += 8-6 + 4;
133 *buf = exif_mem_alloc (ne->mem, *buf_size);
135 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
139 /* Write the header and the number of entries. */
140 strcpy ((char *)*buf, "OLYMPUS");
141 exif_set_short (*buf + 8, n->order, (ExifShort) (
142 (n->order == EXIF_BYTE_ORDER_INTEL) ?
145 exif_set_short (*buf + 10, n->order, (ExifShort) 3);
150 base = MNOTE_NIKON1_TAG_BASE;
152 /* v1 has offsets based to main IFD, not makernote IFD */
153 datao += n->offset + 10;
154 /* subtract the size here, so the increment in the next case will not harm us */
156 /* Fall through to nikonV2 handler */
158 /* Write out V0 files in V2 format */
161 *buf_size += 4; /* Next IFD pointer */
162 *buf = exif_mem_alloc (ne->mem, *buf_size);
164 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
168 /* Write the header and the number of entries. */
169 strcpy ((char *)*buf, "Nikon");
170 (*buf)[6] = n->version;
172 if (n->version != nikonV1) {
173 exif_set_short (*buf + 10, n->order, (ExifShort) (
174 (n->order == EXIF_BYTE_ORDER_INTEL) ?
177 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
178 exif_set_long (*buf + 14, n->order, (ExifShort) 8);
182 /* Reset next IFD pointer */
183 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0);
190 exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
193 /* Save each entry */
194 for (i = 0; i < n->count; i++) {
196 exif_set_short (*buf + o + 0, n->order,
197 (ExifShort) (n->entries[i].tag - base));
198 exif_set_short (*buf + o + 2, n->order,
199 (ExifShort) n->entries[i].format);
200 exif_set_long (*buf + o + 4, n->order,
201 n->entries[i].components);
203 s = exif_format_get_size (n->entries[i].format) *
204 n->entries[i].components;
206 /* Corrupt data: EXIF data size is limited to the
207 * maximum size of a JPEG segment (64 kb).
214 t = exif_mem_realloc (ne->mem, *buf,
217 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
222 exif_set_long (*buf + o, n->order, datao + doff);
226 /* Write the data. */
227 if (n->entries[i].data) {
228 memcpy (*buf + doff, n->entries[i].data, s);
230 /* Most certainly damaged input file */
231 memset (*buf + doff, 0, s);
237 exif_mnote_data_olympus_load (ExifMnoteData *en,
238 const unsigned char *buf, unsigned int buf_size)
240 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
242 size_t i, tcount, o, o2, datao = 6, base = 0;
244 if (!n || !buf || !buf_size) {
245 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
246 "ExifMnoteDataOlympus", "Short MakerNote");
249 o2 = 6 + n->offset; /* Start of interesting data */
250 if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
251 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
252 "ExifMnoteDataOlympus", "Short MakerNote");
257 * Olympus headers start with "OLYMP" and need to have at least
258 * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
259 * number of entries, and 12 for one entry.
261 * Sanyo format is identical and uses identical tags except that
262 * header starts with "SANYO".
264 * Epson format is identical and uses identical tags except that
265 * header starts with "EPSON".
267 * Nikon headers start with "Nikon" (6 bytes including '\0'),
268 * version number (1 or 2).
270 * Version 1 continues with 0, 1, 0, number_of_tags,
271 * or just with number_of_tags (models D1H, D1X...).
273 * Version 2 continues with an unknown byte (0 or 10),
274 * two unknown bytes (0), "MM" or "II", another byte 0 and
277 n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2);
278 switch (n->version) {
282 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
283 "Parsing Olympus/Sanyo/Epson maker note v1...");
285 /* The number of entries is at position 8. */
286 if (buf[o2 + 6] == 1)
287 n->order = EXIF_BYTE_ORDER_INTEL;
288 else if (buf[o2 + 6 + 1] == 1)
289 n->order = EXIF_BYTE_ORDER_MOTOROLA;
291 if (o2 + 2 > buf_size) return;
292 c = exif_get_short (buf + o2, n->order);
293 if ((!(c & 0xFF)) && (c > 0x500)) {
294 if (n->order == EXIF_BYTE_ORDER_INTEL) {
295 n->order = EXIF_BYTE_ORDER_MOTOROLA;
297 n->order = EXIF_BYTE_ORDER_INTEL;
303 /* Olympus S760, S770 */
306 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
307 "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
308 buf[o2], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
310 if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
311 n->order = EXIF_BYTE_ORDER_INTEL;
312 else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M'))
313 n->order = EXIF_BYTE_ORDER_MOTOROLA;
315 /* The number of entries is at position 8+4. */
321 if (o2 >= buf_size) return;
322 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
323 "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, "
324 "%02x, %02x, %02x, %02x, %02x)...",
325 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
326 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
328 /* Skip version number */
331 /* Skip an unknown byte (00 or 0A). */
334 base = MNOTE_NIKON1_TAG_BASE;
335 /* Fix endianness, if needed */
336 if (o2 + 2 > buf_size) return;
337 c = exif_get_short (buf + o2, n->order);
338 if ((!(c & 0xFF)) && (c > 0x500)) {
339 if (n->order == EXIF_BYTE_ORDER_INTEL) {
340 n->order = EXIF_BYTE_ORDER_MOTOROLA;
342 n->order = EXIF_BYTE_ORDER_INTEL;
349 if (o2 >= buf_size) return;
350 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
351 "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
352 "%02x, %02x, %02x, %02x, %02x)...",
353 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
354 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
356 /* Skip version number */
359 /* Skip an unknown byte (00 or 0A). */
362 /* Skip 2 unknown bytes (00 00). */
366 * Byte order. From here the data offset
370 if (o2 >= buf_size) return;
371 if (!strncmp ((char *)&buf[o2], "II", 2))
372 n->order = EXIF_BYTE_ORDER_INTEL;
373 else if (!strncmp ((char *)&buf[o2], "MM", 2))
374 n->order = EXIF_BYTE_ORDER_MOTOROLA;
376 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
377 "ExifMnoteDataOlympus", "Unknown "
378 "byte order '%c%c'", buf[o2],
384 /* Skip 2 unknown bytes (00 2A). */
387 /* Go to where the number of entries is. */
388 if (o2 + 4 > buf_size) return;
389 o2 = datao + exif_get_long (buf + o2, n->order);
393 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
394 "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, "
395 "%02x, %02x, %02x, %02x, %02x)...",
396 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
397 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
398 /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
399 n->order = EXIF_BYTE_ORDER_MOTOROLA;
403 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
404 "Unknown Olympus variant %i.", n->version);
408 /* Sanity check the offset */
409 if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
410 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
411 "ExifMnoteOlympus", "Short MakerNote");
415 /* Read the number of tags */
416 c = exif_get_short (buf + o2, n->order);
419 /* Remove any old entries */
420 exif_mnote_data_olympus_clear (n);
422 /* Reserve enough space for all the possible MakerNote tags */
423 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
425 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
429 /* Parse all c entries, storing ones that are successfully parsed */
431 for (i = c, o = o2; i; --i, o += 12) {
433 if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
434 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
435 "ExifMnoteOlympus", "Short MakerNote");
439 n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base;
440 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
441 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
442 n->entries[tcount].order = n->order;
444 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
445 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
446 mnote_olympus_tag_get_name (n->entries[tcount].tag));
447 /* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
449 n->entries[tcount].tag,
450 n->entries[tcount].format,
451 n->entries[tcount].components,
452 (int)exif_format_get_size(n->entries[tcount].format)); */
455 * Size? If bigger than 4 bytes, the actual data is not
456 * in the entry but somewhere else (offset).
458 s = exif_format_get_size (n->entries[tcount].format) *
459 n->entries[tcount].components;
460 n->entries[tcount].size = s;
462 size_t dataofs = o + 8;
464 /* The data in this case is merely a pointer */
465 dataofs = exif_get_long (buf + dataofs, n->order) + datao;
466 #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
467 /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
468 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
469 * tag in its MakerNote. The offset is actually the absolute
470 * position in the file instead of the position within the IFD.
472 if (dataofs + s > buf_size && n->version == sanyoV1) {
474 dataofs -= datao + 6;
475 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
477 "Inconsistent thumbnail tag offset; attempting to recover");
481 if ((dataofs + s < dataofs) || (dataofs + s < s) ||
482 (dataofs + s > buf_size)) {
483 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
485 "Tag data past end of buffer (%u > %u)",
486 dataofs + s, buf_size);
490 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
491 if (!n->entries[tcount].data) {
492 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
495 memcpy (n->entries[tcount].data, buf + dataofs, s);
498 /* Tag was successfully parsed */
501 /* Store the count of successfully parsed tags */
506 exif_mnote_data_olympus_count (ExifMnoteData *n)
508 return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
512 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
514 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
517 if (note->count <= n) return 0;
518 return note->entries[n].tag;
522 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
524 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
527 if (i >= n->count) return NULL;
528 return mnote_olympus_tag_get_name (n->entries[i].tag);
532 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
534 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
537 if (i >= n->count) return NULL;
538 return mnote_olympus_tag_get_title (n->entries[i].tag);
542 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
544 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
547 if (i >= n->count) return NULL;
548 return mnote_olympus_tag_get_description (n->entries[i].tag);
552 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
554 ExifByteOrder o_orig;
555 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
562 for (i = 0; i < n->count; i++) {
563 n->entries[i].order = o;
564 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
565 n->entries[i].components, o_orig, o);
570 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
572 if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
575 static enum OlympusVersion
576 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
577 unsigned int buf_size)
579 /* Olympus, Nikon, Sanyo, Epson */
581 /* Match the terminating NUL character, too */
582 if (!memcmp (buf, "OLYMPUS", 8))
584 else if (!memcmp (buf, "OLYMP", 6))
586 else if (!memcmp (buf, "SANYO", 6))
588 else if (!memcmp (buf, "EPSON", 6))
590 else if (!memcmp (buf, "Nikon", 6)) {
592 case 1: return nikonV1;
593 case 2: return nikonV2;
594 default: return 0; /* Unrecognized Nikon variant */
599 /* Another variant of Nikon */
600 if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) {
608 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e)
610 int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size);
612 if (variant == nikonV0) {
613 /* This variant needs some extra checking with the Make */
615 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE);
616 variant = unrecognized;
619 const char *v = exif_entry_get_value (em, value, sizeof(value));
620 if (v && (!strncmp (v, "Nikon", sizeof(value)) ||
621 !strncmp (v, "NIKON", sizeof(value)) ))
622 /* When saved, this variant will be written out like the
623 * alternative nikonV2 form above instead
634 exif_mnote_data_olympus_new (ExifMem *mem)
638 if (!mem) return NULL;
640 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
643 exif_mnote_data_construct (d, mem);
645 /* Set up function pointers */
646 d->methods.free = exif_mnote_data_olympus_free;
647 d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
648 d->methods.set_offset = exif_mnote_data_olympus_set_offset;
649 d->methods.load = exif_mnote_data_olympus_load;
650 d->methods.save = exif_mnote_data_olympus_save;
651 d->methods.count = exif_mnote_data_olympus_count;
652 d->methods.get_id = exif_mnote_data_olympus_get_id;
653 d->methods.get_name = exif_mnote_data_olympus_get_name;
654 d->methods.get_title = exif_mnote_data_olympus_get_title;
655 d->methods.get_description = exif_mnote_data_olympus_get_description;
656 d->methods.get_value = exif_mnote_data_olympus_get_value;