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