1 /* exif-mnote-data-olympus.c 2 * 3 * Copyright (c) 2002, 2003 Lutz Mueller <lutz (at) users.sourceforge.net> 4 * 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. 9 * 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. 14 * 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. 19 */ 20 21 #include <config.h> 22 #include "exif-mnote-data-olympus.h" 23 24 #include <stdlib.h> 25 #include <string.h> 26 #include <stdio.h> 27 28 #include <libexif/exif-utils.h> 29 #include <libexif/exif-data.h> 30 31 #define DEBUG 32 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. 37 */ 38 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */ 39 40 static enum OlympusVersion 41 exif_mnote_data_olympus_identify_variant (const unsigned char *buf, 42 unsigned int buf_size); 43 44 45 static void 46 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n) 47 { 48 ExifMnoteData *d = (ExifMnoteData *) n; 49 unsigned int i; 50 51 if (!n) return; 52 53 if (n->entries) { 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; 58 } 59 exif_mem_free (d->mem, n->entries); 60 n->entries = NULL; 61 n->count = 0; 62 } 63 } 64 65 static void 66 exif_mnote_data_olympus_free (ExifMnoteData *n) 67 { 68 if (!n) return; 69 70 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n); 71 } 72 73 static char * 74 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) 75 { 76 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; 77 78 if (!d || !val) return NULL; 79 if (i > n->count -1) return NULL; 80 /* 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)); 84 */ 85 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen); 86 } 87 88 89 90 91 /** 92 * @brief save the MnoteData from ne to buf 93 * 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 97 */ 98 static void 99 exif_mnote_data_olympus_save (ExifMnoteData *ne, 100 unsigned char **buf, unsigned int *buf_size) 101 { 102 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne; 103 size_t i, o, s, doff, base = 0, o2 = 6 + 2; 104 size_t datao = 0; 105 unsigned char *t; 106 size_t ts; 107 108 if (!n || !buf || !buf_size) return; 109 110 /* 111 * Allocate enough memory for all entries and the number of entries. 112 */ 113 *buf_size = 6 + 2 + 2 + n->count * 12; 114 switch (n->version) { 115 case olympusV1: 116 case sanyoV1: 117 case epsonV1: 118 *buf = exif_mem_alloc (ne->mem, *buf_size); 119 if (!*buf) { 120 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); 121 return; 122 } 123 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); 128 datao = n->offset; 129 break; 130 131 case olympusV2: 132 *buf_size += 8-6 + 4; 133 *buf = exif_mem_alloc (ne->mem, *buf_size); 134 if (!*buf) { 135 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); 136 return; 137 } 138 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) ? 143 ('I' << 8) | 'I' : 144 ('M' << 8) | 'M')); 145 exif_set_short (*buf + 10, n->order, (ExifShort) 3); 146 o2 += 4; 147 break; 148 149 case nikonV1: 150 base = MNOTE_NIKON1_TAG_BASE; 151 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 */ 155 *buf_size -= 8 + 2; 156 /* Fall through to nikonV2 handler */ 157 case nikonV2: 158 /* Write out V0 files in V2 format */ 159 case nikonV0: 160 *buf_size += 8 + 2; 161 *buf_size += 4; /* Next IFD pointer */ 162 *buf = exif_mem_alloc (ne->mem, *buf_size); 163 if (!*buf) { 164 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); 165 return; 166 } 167 168 /* Write the header and the number of entries. */ 169 strcpy ((char *)*buf, "Nikon"); 170 (*buf)[6] = n->version; 171 172 if (n->version != nikonV1) { 173 exif_set_short (*buf + 10, n->order, (ExifShort) ( 174 (n->order == EXIF_BYTE_ORDER_INTEL) ? 175 ('I' << 8) | 'I' : 176 ('M' << 8) | 'M')); 177 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A); 178 exif_set_long (*buf + 14, n->order, (ExifShort) 8); 179 o2 += 2 + 8; 180 } 181 datao -= 10; 182 /* Reset next IFD pointer */ 183 exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0); 184 break; 185 186 default: 187 return; 188 } 189 190 exif_set_short (*buf + o2, n->order, (ExifShort) n->count); 191 o2 += 2; 192 193 /* Save each entry */ 194 for (i = 0; i < n->count; i++) { 195 o = o2 + i * 12; 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); 202 o += 8; 203 s = exif_format_get_size (n->entries[i].format) * 204 n->entries[i].components; 205 if (s > 65536) { 206 /* Corrupt data: EXIF data size is limited to the 207 * maximum size of a JPEG segment (64 kb). 208 */ 209 continue; 210 } 211 if (s > 4) { 212 doff = *buf_size; 213 ts = *buf_size + s; 214 t = exif_mem_realloc (ne->mem, *buf, 215 sizeof (char) * ts); 216 if (!t) { 217 EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts); 218 return; 219 } 220 *buf = t; 221 *buf_size = ts; 222 exif_set_long (*buf + o, n->order, datao + doff); 223 } else 224 doff = o; 225 226 /* Write the data. */ 227 if (n->entries[i].data) { 228 memcpy (*buf + doff, n->entries[i].data, s); 229 } else { 230 /* Most certainly damaged input file */ 231 memset (*buf + doff, 0, s); 232 } 233 } 234 } 235 236 static void 237 exif_mnote_data_olympus_load (ExifMnoteData *en, 238 const unsigned char *buf, unsigned int buf_size) 239 { 240 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en; 241 ExifShort c; 242 size_t i, tcount, o, o2, datao = 6, base = 0; 243 244 if (!n || !buf || !buf_size) { 245 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, 246 "ExifMnoteDataOlympus", "Short MakerNote"); 247 return; 248 } 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"); 253 return; 254 } 255 256 /* 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. 260 * 261 * Sanyo format is identical and uses identical tags except that 262 * header starts with "SANYO". 263 * 264 * Epson format is identical and uses identical tags except that 265 * header starts with "EPSON". 266 * 267 * Nikon headers start with "Nikon" (6 bytes including '\0'), 268 * version number (1 or 2). 269 * 270 * Version 1 continues with 0, 1, 0, number_of_tags, 271 * or just with number_of_tags (models D1H, D1X...). 272 * 273 * Version 2 continues with an unknown byte (0 or 10), 274 * two unknown bytes (0), "MM" or "II", another byte 0 and 275 * lastly 0x2A. 276 */ 277 n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2); 278 switch (n->version) { 279 case olympusV1: 280 case sanyoV1: 281 case epsonV1: 282 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", 283 "Parsing Olympus/Sanyo/Epson maker note v1..."); 284 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; 290 o2 += 8; 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; 296 } else { 297 n->order = EXIF_BYTE_ORDER_INTEL; 298 } 299 } 300 break; 301 302 case olympusV2: 303 /* Olympus S760, S770 */ 304 datao = o2; 305 o2 += 8; 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]); 309 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; 314 315 /* The number of entries is at position 8+4. */ 316 o2 += 4; 317 break; 318 319 case nikonV1: 320 o2 += 6; 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]); 327 328 /* Skip version number */ 329 o2 += 1; 330 331 /* Skip an unknown byte (00 or 0A). */ 332 o2 += 1; 333 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; 341 } else { 342 n->order = EXIF_BYTE_ORDER_INTEL; 343 } 344 } 345 break; 346 347 case nikonV2: 348 o2 += 6; 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]); 355 356 /* Skip version number */ 357 o2 += 1; 358 359 /* Skip an unknown byte (00 or 0A). */ 360 o2 += 1; 361 362 /* Skip 2 unknown bytes (00 00). */ 363 o2 += 2; 364 365 /* 366 * Byte order. From here the data offset 367 * gets calculated. 368 */ 369 datao = o2; 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; 375 else { 376 exif_log (en->log, EXIF_LOG_CODE_DEBUG, 377 "ExifMnoteDataOlympus", "Unknown " 378 "byte order '%c%c'", buf[o2], 379 buf[o2 + 1]); 380 return; 381 } 382 o2 += 2; 383 384 /* Skip 2 unknown bytes (00 2A). */ 385 o2 += 2; 386 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); 390 break; 391 392 case nikonV0: 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; 400 break; 401 402 default: 403 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", 404 "Unknown Olympus variant %i.", n->version); 405 return; 406 } 407 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"); 412 return; 413 } 414 415 /* Read the number of tags */ 416 c = exif_get_short (buf + o2, n->order); 417 o2 += 2; 418 419 /* Remove any old entries */ 420 exif_mnote_data_olympus_clear (n); 421 422 /* Reserve enough space for all the possible MakerNote tags */ 423 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c); 424 if (!n->entries) { 425 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c); 426 return; 427 } 428 429 /* Parse all c entries, storing ones that are successfully parsed */ 430 tcount = 0; 431 for (i = c, o = o2; i; --i, o += 12) { 432 size_t s; 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"); 436 break; 437 } 438 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; 443 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", 448 "0x%x %d %ld*(%d)", 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)); */ 453 454 /* 455 * Size? If bigger than 4 bytes, the actual data is not 456 * in the entry but somewhere else (offset). 457 */ 458 s = exif_format_get_size (n->entries[tcount].format) * 459 n->entries[tcount].components; 460 n->entries[tcount].size = s; 461 if (s) { 462 size_t dataofs = o + 8; 463 if (s > 4) { 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. 471 */ 472 if (dataofs + s > buf_size && n->version == sanyoV1) { 473 /* fix pointer */ 474 dataofs -= datao + 6; 475 exif_log (en->log, EXIF_LOG_CODE_DEBUG, 476 "ExifMnoteOlympus", 477 "Inconsistent thumbnail tag offset; attempting to recover"); 478 } 479 #endif 480 } 481 if ((dataofs + s < dataofs) || (dataofs + s < s) || 482 (dataofs + s > buf_size)) { 483 exif_log (en->log, EXIF_LOG_CODE_DEBUG, 484 "ExifMnoteOlympus", 485 "Tag data past end of buffer (%zu > %u)", 486 dataofs + s, buf_size); 487 continue; 488 } 489 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); 493 continue; 494 } 495 memcpy (n->entries[tcount].data, buf + dataofs, s); 496 } 497 498 /* Tag was successfully parsed */ 499 ++tcount; 500 } 501 /* Store the count of successfully parsed tags */ 502 n->count = tcount; 503 } 504 505 static unsigned int 506 exif_mnote_data_olympus_count (ExifMnoteData *n) 507 { 508 return n ? ((ExifMnoteDataOlympus *) n)->count : 0; 509 } 510 511 static unsigned int 512 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n) 513 { 514 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d; 515 516 if (!note) return 0; 517 if (note->count <= n) return 0; 518 return note->entries[n].tag; 519 } 520 521 static const char * 522 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i) 523 { 524 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; 525 526 if (!n) return NULL; 527 if (i >= n->count) return NULL; 528 return mnote_olympus_tag_get_name (n->entries[i].tag); 529 } 530 531 static const char * 532 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i) 533 { 534 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; 535 536 if (!n) return NULL; 537 if (i >= n->count) return NULL; 538 return mnote_olympus_tag_get_title (n->entries[i].tag); 539 } 540 541 static const char * 542 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i) 543 { 544 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; 545 546 if (!n) return NULL; 547 if (i >= n->count) return NULL; 548 return mnote_olympus_tag_get_description (n->entries[i].tag); 549 } 550 551 static void 552 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o) 553 { 554 ExifByteOrder o_orig; 555 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; 556 unsigned int i; 557 558 if (!n) return; 559 560 o_orig = n->order; 561 n->order = o; 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); 566 } 567 } 568 569 static void 570 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o) 571 { 572 if (n) ((ExifMnoteDataOlympus *) n)->offset = o; 573 } 574 575 static enum OlympusVersion 576 exif_mnote_data_olympus_identify_variant (const unsigned char *buf, 577 unsigned int buf_size) 578 { 579 /* Olympus, Nikon, Sanyo, Epson */ 580 if (buf_size >= 8) { 581 /* Match the terminating NUL character, too */ 582 if (!memcmp (buf, "OLYMPUS", 8)) 583 return olympusV2; 584 else if (!memcmp (buf, "OLYMP", 6)) 585 return olympusV1; 586 else if (!memcmp (buf, "SANYO", 6)) 587 return sanyoV1; 588 else if (!memcmp (buf, "EPSON", 6)) 589 return epsonV1; 590 else if (!memcmp (buf, "Nikon", 6)) { 591 switch (buf[6]) { 592 case 1: return nikonV1; 593 case 2: return nikonV2; 594 default: return 0; /* Unrecognized Nikon variant */ 595 } 596 } 597 } 598 599 /* Another variant of Nikon */ 600 if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) { 601 return nikonV0; 602 } 603 604 return unrecognized; 605 } 606 607 int 608 exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e) 609 { 610 int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size); 611 612 if (variant == nikonV0) { 613 /* This variant needs some extra checking with the Make */ 614 char value[5]; 615 ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); 616 variant = unrecognized; 617 618 if (em) { 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 624 */ 625 variant = nikonV0; 626 } 627 } 628 629 return variant; 630 } 631 632 633 ExifMnoteData * 634 exif_mnote_data_olympus_new (ExifMem *mem) 635 { 636 ExifMnoteData *d; 637 638 if (!mem) return NULL; 639 640 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus)); 641 if (!d) return NULL; 642 643 exif_mnote_data_construct (d, mem); 644 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; 657 658 return d; 659 } 660