2004-05-25 Lutz Mueller <lutz@users.sourceforge.net>
[platform/upstream/libexif.git] / libexif / olympus / exif-mnote-data-olympus.c
1 /* exif-mnote-data-olympus.c
2  *
3  * Copyright © 2002, 2003 Lutz Mueller <lutz@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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, 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 static void
34 exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n)
35 {
36         unsigned int i;
37
38         if (!n) return;
39
40         if (n->entries) {
41                 for (i = 0; i < n->count; i++)
42                         if (n->entries[i].data) {
43                                 free (n->entries[i].data);
44                                 n->entries[i].data = NULL;
45                         }
46                 free (n->entries);
47                 n->entries = NULL;
48                 n->count = 0;
49         }
50 }
51
52 static void
53 exif_mnote_data_olympus_free (ExifMnoteData *n)
54 {
55         if (!n) return;
56
57         exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n);
58 }
59
60 static char *
61 exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
62 {
63         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
64
65         if (!d) return NULL;
66         if (n->count <= i) return NULL;
67         exif_log (d->log, EXIF_LOG_CODE_DEBUG, "MnoteDataOlympus",
68                   "Querying value for tag '%s'...",
69                   mnote_olympus_tag_get_name (n->entries[i].tag));
70         return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen);
71 }
72
73 static void
74 exif_mnote_data_olympus_save (ExifMnoteData *ne,
75                 unsigned char **buf, unsigned int *buf_size)
76 {
77         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne;
78         unsigned int i, o, s, doff, base = 0, o2 = 6;
79         int datao = 0;
80
81         if (!n || !buf || !buf_size) return;
82
83         /*
84          * Allocate enough memory for all entries and the number of entries.
85          */
86         *buf_size = 6 + 2 + 2 + n->count * 12;
87         switch (n->version) {
88         case 0: /* Olympus */
89                 *buf = malloc (*buf_size);
90                 if (!*buf) return;
91                 memset (*buf, 0, *buf_size);
92
93                 /* Write the header and the number of entries. */
94                 strcpy (*buf, "OLYMP");
95                 o2 += 2;
96                 datao = n->offset;
97                 break;
98         case 1: /* Nikon v1 */
99                 base = MNOTE_NIKON1_TAG_BASE;
100                 *buf_size -= 8;
101                 /* Fall through */
102         case 2: /* Nikon v2 */
103                 *buf_size += 8;
104                 *buf = malloc (*buf_size);
105                 if (!*buf) return;
106                 memset (*buf, 0, *buf_size);
107
108                 /* Write the header and the number of entries. */
109                 strcpy (*buf, "Nikon");
110                 (*buf)[6] = n->version;
111                 o2 += 2; *buf_size += 2;
112                 if (n->version == 2) {
113                         exif_set_short (*buf + 10, n->order, (ExifShort) ((n->order == EXIF_BYTE_ORDER_INTEL) ? 'II' : 'MM'));
114                         exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A);
115                         exif_set_long (*buf + 14, n->order, (ExifShort) 8);
116                         o2 += 2 + 8;
117                 }
118                 datao = -10;
119                 break;
120         }
121
122         exif_set_short (*buf + o2, n->order, (ExifShort) n->count);
123         o2 += 2;
124
125         /* Save each entry */
126         for (i = 0; i < n->count; i++) {
127                 o = o2 + i * 12;
128                 exif_set_short (*buf + o + 0, n->order,
129                                 (ExifShort) (n->entries[i].tag - base));
130                 exif_set_short (*buf + o + 2, n->order,
131                                 (ExifShort) n->entries[i].format);
132                 exif_set_long  (*buf + o + 4, n->order,
133                                 n->entries[i].components);
134                 o += 8;
135                 s = exif_format_get_size (n->entries[i].format) *
136                                                 n->entries[i].components;
137                 if (s > 4) {
138                         doff = *buf_size;
139                         *buf_size += s;
140                         *buf = realloc (*buf, *buf_size);
141                         if (!*buf) return;
142                         exif_set_long (*buf + o, n->order, datao + doff);
143                 } else
144                         doff = o;
145
146                 /* Write the data. */
147                 if (n->entries[i].data) {
148                         memcpy (*buf + doff, n->entries[i].data, s);
149                 } else {
150                         /* Most certainly damaged input file */
151                         memset (*buf + doff, 0, s);
152                 }
153         }
154 }
155
156 static void
157 exif_mnote_data_olympus_load (ExifMnoteData *en,
158                               const unsigned char *buf, unsigned int buf_size)
159 {
160         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
161         ExifShort c;
162         unsigned int i, s, o, o2, datao = 6, base = 0;
163
164         if (!n || !buf) return;
165
166         exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
167                   "Trying to parse Olympus/Nikon maker note...");
168
169         /*
170          * Olympus headers start with "OLYMP" and need to have at least
171          * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the
172          * number of entries, and 12 for one entry.
173          *
174          * Nikon v1 headers start with "Nikon", 0, 1, 0, number_of_tags,
175          * or just with number_of_tags (models D1H, D1X...).
176          * Nikon v2 headers start with "Nikon", 0, 2, 0, 0, 0, "MM", 0, 0x2A
177          * or "Nikon", 0, 2, 0, 0, 0, "II", 0x2A, 0.
178          */
179         if (buf_size - n->offset < 22) return;
180         if (!memcmp (buf + 6 + n->offset, "OLYMP", 5)) {
181                 o2 = 6 + n->offset + 8 + 2;
182                 c = exif_get_short (buf + 6 + n->offset + 8, n->order);
183                 n->version = 0;
184         } else if (!memcmp (buf + 6 + n->offset, "Nikon", 5)) {
185                 o2 = 6 + n->offset + 8 + 2;
186                 datao = o2;
187                 if (!memcmp(buf + o2 - 4, "\2\0\0\0II\x2A\0", 8)) {
188                         n->order = EXIF_BYTE_ORDER_INTEL;
189                         o2 += exif_get_long(buf + o2 + 4, n->order);
190                         n->version = 2;
191                 } else if (!memcmp(buf + o2 - 4, "\2\0\0\0MM\0\x2A", 8)) {
192                         n->order = EXIF_BYTE_ORDER_MOTOROLA;
193                         o2 += exif_get_long(buf + o2 + 4, n->order);
194                         n->version = 2;
195                 } else if (!memcmp(buf + o2 - 4, "\1\0", 2)) {
196                         o2 -= 2;
197                         base = MNOTE_NIKON1_TAG_BASE;
198                         n->version = 1;
199                 } else {
200                         return;
201                 }
202                 if (o2 + 2 > buf_size) return;
203                 c = exif_get_short (buf + o2, n->order);
204                 o2 += 2;
205         } else if (!memcmp (buf + 6 + n->offset, "\0\x1b", 2)) {
206                 o2 = 6 + n->offset;
207                 c = exif_get_short (buf + o2, n->order);
208                 o2 += 2;
209                 n->version = 2;
210         } else {
211                 return;
212         }
213
214         /* Read the number of entries and remove old ones. */
215         exif_mnote_data_olympus_clear (n);
216
217         n->entries = malloc (sizeof (MnoteOlympusEntry) * c);
218         memset (n->entries, 0, sizeof (MnoteOlympusEntry) * c);
219
220         /* Parse the entries */
221         for (i = 0; i < c; i++) {
222             o = o2 + 12 * i;
223             if (o + 12 > buf_size) return;
224
225             n->count = i + 1;
226             n->entries[i].tag        = exif_get_short (buf + o, n->order) + base;
227             n->entries[i].format     = exif_get_short (buf + o + 2, n->order);
228             n->entries[i].components = exif_get_long (buf + o + 4, n->order);
229             n->entries[i].order      = n->order;
230
231             exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
232                       "Loading entry 0x%x ('%s')...", n->entries[i].tag,
233                       mnote_olympus_tag_get_name (n->entries[i].tag));
234
235             /*
236              * Size? If bigger than 4 bytes, the actual data is not
237              * in the entry but somewhere else (offset).
238              */
239             s = exif_format_get_size (n->entries[i].format) *
240                                          n->entries[i].components;
241             if (!s) continue;
242             o += 8;
243             if (s > 4) o = exif_get_long (buf + o, n->order) + datao;
244             if (o + s > buf_size) continue;
245
246             /* Sanity check */
247             n->entries[i].data = malloc (s);
248             if (!n->entries[i].data) continue;
249             n->entries[i].size = s;
250             memcpy (n->entries[i].data, buf + o, s);
251         }
252 }
253
254 static unsigned int
255 exif_mnote_data_olympus_count (ExifMnoteData *n)
256 {
257         return n ? ((ExifMnoteDataOlympus *) n)->count : 0;
258 }
259
260 static const char *
261 exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i)
262 {
263         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
264
265         if (!n) return NULL;
266         if (i >= n->count) return NULL;
267         return mnote_olympus_tag_get_title (n->entries[i].tag);
268 }
269
270 static const char *
271 exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i)
272 {
273         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
274         
275         if (!n) return NULL;
276         if (i >= n->count) return NULL;
277         return mnote_olympus_tag_get_title (n->entries[i].tag);
278 }
279
280 static const char *
281 exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i)
282 {
283         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
284         
285         if (!n) return NULL;
286         if (i >= n->count) return NULL;
287         return mnote_olympus_tag_get_title (n->entries[i].tag);
288 }
289
290 static void
291 exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
292 {
293         ExifByteOrder o_orig;
294         ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d;
295         unsigned int i, fs;
296         ExifShort s;
297         ExifLong l;
298         ExifSLong sl;
299         ExifRational r;
300         ExifSRational sr;
301
302         if (!n) return;
303
304         o_orig = n->order;
305         n->order = o;
306         for (i = 0; i < n->count; i++) {
307                 n->entries[i].order = o;
308                 fs = exif_format_get_size (n->entries[i].format);
309                 switch (n->entries[i].format) {
310                 case EXIF_FORMAT_SHORT:
311                         for (i = 0; i < n->entries[i].components; i++) {
312                                 s = exif_get_short (n->entries[i].data + (i*fs),
313                                                 o_orig);
314                                 exif_set_short (n->entries[i].data + (i * fs),
315                                                 o, s);
316                         }
317                         break;
318                 case EXIF_FORMAT_LONG:
319                         for (i = 0; i < n->entries[i].components; i++) {
320                                 l = exif_get_long (n->entries[i].data + (i*fs),
321                                                 o_orig);
322                                 exif_set_long (n->entries[i].data + (i * fs),
323                                                 o, l);
324                         }
325                         break;
326                 case EXIF_FORMAT_RATIONAL:
327                         for (i = 0; i < n->entries[i].components; i++) {
328                                 r = exif_get_rational (n->entries[i].data +
329                                                 (i * fs), o_orig);
330                                 exif_set_rational (n->entries[i].data +
331                                                 (i * fs), o, r);
332                         }
333                         break;
334                 case EXIF_FORMAT_SLONG:
335                         for (i = 0; i < n->entries[i].components; i++) {
336                                 sl = exif_get_slong (n->entries[i].data +
337                                                 (i * fs), o_orig);
338                                 exif_set_slong (n->entries[i].data +
339                                                 (i * fs), o, sl);
340                         }
341                         break;
342                 case EXIF_FORMAT_SRATIONAL:
343                         for (i = 0; i < n->entries[i].components; i++) {
344                                 sr = exif_get_srational (n->entries[i].data +
345                                                 (i * fs), o_orig);
346                                 exif_set_srational (n->entries[i].data +
347                                                 (i * fs), o, sr);
348                         }
349                         break;
350                 case EXIF_FORMAT_UNDEFINED:
351                 case EXIF_FORMAT_BYTE:
352                 case EXIF_FORMAT_ASCII:
353                 default:
354                         /* Nothing here. */
355                         break;
356                 }
357         }
358 }
359
360 static void
361 exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o)
362 {
363         if (n) ((ExifMnoteDataOlympus *) n)->offset = o;
364 }
365
366 ExifMnoteData *
367 exif_mnote_data_olympus_new (void)
368 {
369         ExifMnoteData *n;
370
371         n = malloc (sizeof (ExifMnoteDataOlympus));
372         if (!n) return NULL;
373         memset (n, 0, sizeof (ExifMnoteDataOlympus));
374
375         exif_mnote_data_construct (n);
376
377         /* Set up the function pointers */
378         n->methods.free            = exif_mnote_data_olympus_free;
379         n->methods.set_byte_order  = exif_mnote_data_olympus_set_byte_order;
380         n->methods.set_offset      = exif_mnote_data_olympus_set_offset;
381         n->methods.load            = exif_mnote_data_olympus_load;
382         n->methods.save            = exif_mnote_data_olympus_save;
383         n->methods.count           = exif_mnote_data_olympus_count;
384         n->methods.get_name        = exif_mnote_data_olympus_get_name;
385         n->methods.get_title       = exif_mnote_data_olympus_get_title;
386         n->methods.get_description = exif_mnote_data_olympus_get_description;
387         n->methods.get_value       = exif_mnote_data_olympus_get_value;
388
389         return n;
390 }