00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 static void
00034 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
00035 {
00036 ExifMnoteData *d = (ExifMnoteData *) n;
00037 unsigned int i;
00038
00039 if (!n) return;
00040
00041 if (n->entries) {
00042 for (i = 0; i < n->count; i++)
00043 if (n->entries[i].data) {
00044 exif_mem_free (d->mem, n->entries[i].data);
00045 n->entries[i].data = NULL;
00046 }
00047 exif_mem_free (d->mem, n->entries);
00048 n->entries = NULL;
00049 n->count = 0;
00050 }
00051 }
00052
00053 static void
00054 exif_mnote_data_olympus_free (ExifMnoteData *n)
00055 {
00056 if (!n) return;
00057
00058 exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
00059 }
00060
00061 static char *
00062 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
00063 {
00064 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00065
00066 if (!d || !val) return NULL;
00067 if (i > n->count -1) return NULL;
00068 exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00069 "Querying value for tag '%s'...",
00070 mnote_olympus_tag_get_name (n->entries[i].tag));
00071 return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
00072 }
00073
00074
00075
00076
00084 static void
00085 exif_mnote_data_olympus_save (ExifMnoteData *ne,
00086 unsigned char **buf, unsigned int *buf_size)
00087 {
00088 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
00089 unsigned int i, o, s, doff, base = 0, o2 = 6;
00090 int datao = 0;
00091
00092 if (!n || !buf || !buf_size) return;
00093
00094
00095
00096
00097 *buf_size = 6 + 2 + 2 + n->count * 12;
00098 o2 += 2;
00099 switch (n->version) {
00100 case olympus:
00101 *buf = exif_mem_alloc (ne->mem, *buf_size);
00102 if (!*buf) return;
00103
00104
00105 strcpy ((char *)*buf, "OLYMP");
00106 datao = n->offset;
00107 break;
00108 case nikonV1:
00109 base = MNOTE_NIKON1_TAG_BASE;
00110
00111
00112 *buf_size -= 8;
00113
00114 case nikonV2:
00115 *buf_size += 8;
00116 *buf = exif_mem_alloc (ne->mem, *buf_size);
00117 if (!*buf) return;
00118
00119
00120 strcpy ((char *)*buf, "Nikon");
00121 (*buf)[6] = n->version;
00122
00123 *buf_size += 2;
00124 if (n->version == nikonV2) {
00125 exif_set_short (*buf + 10, n->order, (ExifShort) (
00126 (n->order == EXIF_BYTE_ORDER_INTEL) ?
00127 ('I' << 8) | 'I' :
00128 ('M' << 8) | 'M'));
00129 exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
00130 exif_set_long (*buf + 14, n->order, (ExifShort) 8);
00131 o2 += 2 + 8;
00132 }
00133 datao = -10;
00134 break;
00135
00136 default:
00137 return;
00138 }
00139
00140 exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
00141 o2 += 2;
00142
00143
00144 for (i = 0; i < n->count; i++) {
00145 o = o2 + i * 12;
00146 exif_set_short (*buf + o + 0, n->order,
00147 (ExifShort) (n->entries[i].tag - base));
00148 exif_set_short (*buf + o + 2, n->order,
00149 (ExifShort) n->entries[i].format);
00150 exif_set_long (*buf + o + 4, n->order,
00151 n->entries[i].components);
00152 o += 8;
00153 s = exif_format_get_size (n->entries[i].format) *
00154 n->entries[i].components;
00155 if (s > 4) {
00156 doff = *buf_size;
00157 *buf_size += s;
00158 *buf = exif_mem_realloc (ne->mem, *buf,
00159 sizeof (char) * *buf_size);
00160 if (!*buf) return;
00161 exif_set_long (*buf + o, n->order, datao + doff);
00162 } else
00163 doff = o;
00164
00165
00166 if (n->entries[i].data) {
00167 memcpy (*buf + doff, n->entries[i].data, s);
00168 } else {
00169
00170 memset (*buf + doff, 0, s);
00171 }
00172 }
00173 }
00174
00175 static void
00176 exif_mnote_data_olympus_load (ExifMnoteData *en,
00177 const unsigned char *buf, unsigned int buf_size)
00178 {
00179 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
00180 ExifShort c;
00181 unsigned int i, s, o, o2 = 0, datao = 6, base = 0;
00182
00183 if (!n || !buf) return;
00184
00185
00186 o2 = 6 + n->offset;
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 if (buf_size - n->offset < 22) return;
00204 if (!memcmp (buf + o2, "OLYMP", 5)) {
00205 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00206 "Parsing Olympus maker note...");
00207
00208
00209 n->version = olympus;
00210 o2 += 8;
00211
00212 } else if (!memcmp (buf + o2, "Nikon", 6)) {
00213 o2 += 6;
00214 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
00215 "Parsing Nikon maker note (0x%02x, %02x, %02x, "
00216 "%02x, %02x, %02x, %02x, %02x)...",
00217 buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
00218 buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
00219
00220 if (o2 >= buf_size) return;
00221 n->version = buf[o2];
00222 o2 += 1;
00223
00224
00225 o2 += 1;
00226
00227 switch (n->version) {
00228 case nikonV1:
00229
00230 base = MNOTE_NIKON1_TAG_BASE;
00231 break;
00232
00233 case nikonV2:
00234
00235
00236 o2 += 2;
00237
00238
00239
00240
00241
00242 datao = o2;
00243 if (o2 >= buf_size) return;
00244 if (!strncmp ((char *)&buf[o2], "II", 2))
00245 n->order = EXIF_BYTE_ORDER_INTEL;
00246 else if (!strncmp ((char *)&buf[o2], "MM", 2))
00247 n->order = EXIF_BYTE_ORDER_MOTOROLA;
00248 else {
00249 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00250 "ExifMnoteDatalympus", "Unknown "
00251 "byte order '%c%c'", buf[o2],
00252 buf[o2 + 1]);
00253 return;
00254 }
00255 o2 += 2;
00256
00257
00258 o2 += 2;
00259
00260
00261 if (o2 >= buf_size) return;
00262 o2 = datao + exif_get_long (buf + o2, n->order);
00263 break;
00264
00265 default:
00266 exif_log (en->log, EXIF_LOG_CODE_DEBUG,
00267 "ExifMnoteDataOlympus", "Unknown version "
00268 "number %i.", n->version);
00269 return;
00270 }
00271 } else if (!memcmp (buf + o2, "\0\x1b", 2)) {
00272 n->version = nikonV2;
00273 } else {
00274 return;
00275 }
00276
00277
00278 if (o2 >= buf_size) return;
00279 c = exif_get_short (buf + o2, n->order);
00280 o2 += 2;
00281
00282
00283 exif_mnote_data_olympus_clear (n);
00284
00285 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
00286 if (!n->entries) return;
00287
00288
00289 for (i = 0; i < c; i++) {
00290 o = o2 + 12 * i;
00291 if (o + 12 > buf_size) return;
00292
00293 n->count = i + 1;
00294 n->entries[i].tag = exif_get_short (buf + o, n->order) + base;
00295 n->entries[i].format = exif_get_short (buf + o + 2, n->order);
00296 n->entries[i].components = exif_get_long (buf + o + 4, n->order);
00297 n->entries[i].order = n->order;
00298
00299 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
00300 "Loading entry 0x%x ('%s')...", n->entries[i].tag,
00301 mnote_olympus_tag_get_name (n->entries[i].tag));
00302
00303
00304
00305
00306
00307 s = exif_format_get_size (n->entries[i].format) *
00308 n->entries[i].components;
00309 if (!s) continue;
00310 o += 8;
00311 if (s > 4) o = exif_get_long (buf + o, n->order) + datao;
00312 if (o + s > buf_size) continue;
00313
00314
00315 n->entries[i].data = exif_mem_alloc (en->mem, s);
00316 if (!n->entries[i].data) continue;
00317 n->entries[i].size = s;
00318 memcpy (n->entries[i].data, buf + o, s);
00319 }
00320 }
00321
00322 static unsigned int
00323 exif_mnote_data_olympus_count (ExifMnoteData *n)
00324 {
00325 return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
00326 }
00327
00328 static unsigned int
00329 exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n)
00330 {
00331 ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d;
00332
00333 if (!note) return 0;
00334 if (note->count <= n) return 0;
00335 return note->entries[n].tag;
00336 }
00337
00338 static const char *
00339 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
00340 {
00341 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00342
00343 if (!n) return NULL;
00344 if (i >= n->count) return NULL;
00345 return mnote_olympus_tag_get_name (n->entries[i].tag);
00346 }
00347
00348 static const char *
00349 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
00350 {
00351 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00352
00353 if (!n) return NULL;
00354 if (i >= n->count) return NULL;
00355 return mnote_olympus_tag_get_title (n->entries[i].tag);
00356 }
00357
00358 static const char *
00359 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
00360 {
00361 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00362
00363 if (!n) return NULL;
00364 if (i >= n->count) return NULL;
00365 return mnote_olympus_tag_get_title (n->entries[i].tag);
00366 }
00367
00368 static void
00369 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
00370 {
00371 ExifByteOrder o_orig;
00372 ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
00373 unsigned int i;
00374
00375 if (!n) return;
00376
00377 o_orig = n->order;
00378 n->order = o;
00379 for (i = 0; i < n->count; i++) {
00380 n->entries[i].order = o;
00381 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
00382 n->entries[i].components, o_orig, o);
00383 }
00384 }
00385
00386 static void
00387 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
00388 {
00389 if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
00390 }
00391
00392 ExifMnoteData *
00393 exif_mnote_data_olympus_new (ExifMem *mem)
00394 {
00395 ExifMnoteData *d;
00396
00397 if (!mem) return NULL;
00398
00399 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus));
00400 if (!d) return NULL;
00401
00402 exif_mnote_data_construct (d, mem);
00403
00404
00405 d->methods.free = exif_mnote_data_olympus_free;
00406 d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order;
00407 d->methods.set_offset = exif_mnote_data_olympus_set_offset;
00408 d->methods.load = exif_mnote_data_olympus_load;
00409 d->methods.save = exif_mnote_data_olympus_save;
00410 d->methods.count = exif_mnote_data_olympus_count;
00411 d->methods.get_id = exif_mnote_data_olympus_get_id;
00412 d->methods.get_name = exif_mnote_data_olympus_get_name;
00413 d->methods.get_title = exif_mnote_data_olympus_get_title;
00414 d->methods.get_description = exif_mnote_data_olympus_get_description;
00415 d->methods.get_value = exif_mnote_data_olympus_get_value;
00416
00417 return d;
00418 }