2002-02-05 Lutz Müller <lutz@users.sourceforge.net>
[platform/upstream/libexif.git] / libexif / exif-data.c
1 /* exif-data.c
2  *
3  * Copyright (C) 2001 Lutz Müller <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 #include <config.h>
21 #include "exif-data.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #include <libjpeg/jpeg-marker.h>
28
29 #undef MAX
30 #define MAX(a, b)  (((a) > (b)) ? (a) : (b))
31
32 //#define DEBUG
33
34 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
35
36 struct _ExifDataPrivate
37 {
38         ExifByteOrder order;
39
40         unsigned int ref_count;
41 };
42
43 ExifData *
44 exif_data_new (void)
45 {
46         ExifData *data;
47
48         data = malloc (sizeof (ExifData));
49         if (!data)
50                 return (NULL);
51         memset (data, 0, sizeof (ExifData));
52         data->priv = malloc (sizeof (ExifDataPrivate));
53         if (!data->priv) {
54                 free (data);
55                 return (NULL);
56         }
57         memset (data->priv, 0, sizeof (ExifDataPrivate));
58         data->priv->ref_count = 1;
59
60         data->ifd0                 = exif_content_new ();
61         data->ifd1                 = exif_content_new ();
62         data->ifd_exif             = exif_content_new ();
63         data->ifd_gps              = exif_content_new ();
64         data->ifd_interoperability = exif_content_new ();
65         if (!data->ifd_exif || !data->ifd_gps || !data->ifd_interoperability ||
66             !data->ifd0 || !data->ifd1) {
67                 exif_data_free (data);
68                 return (NULL);
69         }
70
71         return (data);
72 }
73
74 ExifData *
75 exif_data_new_from_data (const unsigned char *data, unsigned int size)
76 {
77         ExifData *edata;
78
79         edata = exif_data_new ();
80         exif_data_load_data (edata, data, size);
81         return (edata);
82 }
83
84 static void
85 exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
86                            const unsigned char *d,
87                            unsigned int size, unsigned int offset)
88 {
89         unsigned int s, doff;
90
91         entry->order = data->priv->order;
92         entry->tag        = exif_get_short (d + offset + 0, data->priv->order);
93         entry->format     = exif_get_short (d + offset + 2, data->priv->order);
94         entry->components = exif_get_long  (d + offset + 4, data->priv->order);
95
96         /*
97          * Size? If bigger than 4 bytes, the actual data is not
98          * in the entry but somewhere else (offset).
99          */
100         s = exif_format_get_size (entry->format) * entry->components;
101         if (!s)
102                 return;
103         if (s > 4)
104                 doff = exif_get_long (d + offset + 8, data->priv->order);
105         else
106                 doff = offset + 8;
107
108         /* Sanity check */
109         if (size < doff + s)
110                 return;
111
112         entry->data = malloc (sizeof (char) * s);
113         if (!entry->data)
114                 return;
115         entry->size = s;
116         memcpy (entry->data, d + doff, s);
117 }
118
119 static void
120 exif_data_save_data_entry (ExifData *data, ExifEntry *entry,
121                            unsigned char **d, unsigned int *ds,
122                            unsigned int offset)
123 {
124         unsigned int doff, s;
125
126         /*
127          * Each entry is 12 bytes long. The memory for the entry has
128          * already been allocated.
129          */
130         exif_set_short (*d + 6 + offset + 0,
131                         data->priv->order, entry->tag);
132         exif_set_short (*d + 6 + offset + 2,
133                         data->priv->order, entry->format);
134         exif_set_long  (*d + 6 + offset + 4,
135                         data->priv->order, entry->components);
136
137         /*
138          * Size? If bigger than 4 bytes, the actual data is not in
139          * the entry but somewhere else.
140          */
141         s = exif_format_get_size (entry->format) * entry->components;
142         if (!s)
143                 return;
144         if (s > 4) {
145                 *ds += entry->size;
146                 *d = realloc (*d, sizeof (char) * *ds);
147                 doff = *ds - 6 - entry->size;
148                 exif_set_long (*d + 6 + offset + 8,
149                                data->priv->order, doff);
150         } else
151                 doff = offset + 8;
152         memcpy (*d + 6 + doff, entry->data, entry->size);
153 }
154
155 static void
156 exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,
157                                unsigned int ds, ExifLong offset, ExifLong size)
158 {
159         if (ds < offset + size) {
160 #ifdef DEBUG
161                 printf ("Bogus thumbnail offset and size: %i < %i + %i.\n",
162                         (int) ds, (int) offset, (int) size);
163 #endif
164                 return;
165         }
166         if (data->data)
167                 free (data->data);
168         data->size = size;
169         data->data = malloc (sizeof (char) * data->size);
170         memcpy (data->data, d + offset, data->size);
171 }
172
173 static void
174 exif_data_load_data_content (ExifData *data, ExifContent *ifd,
175                              const unsigned char *d,
176                              unsigned int ds, unsigned int offset)
177 {
178         ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
179         ExifShort n;
180         ExifEntry *entry;
181         unsigned int i;
182         ExifTag tag;
183
184         ifd->order = data->priv->order;
185
186         /* Read the number of entries */
187         n = exif_get_short (d + offset, data->priv->order);
188 #ifdef DEBUG
189         printf ("Loading %i entries...\n", n);
190 #endif
191         offset += 2;
192         for (i = 0; i < n; i++) {
193
194                 tag = exif_get_short (d + offset + 12 * i, data->priv->order);
195 #ifdef DEBUG
196                 printf ("Loading entry '%s' (%i of %i)...\n",
197                         exif_tag_get_name (tag), i + 1, n);
198 #endif
199                 switch (tag) {
200                 case EXIF_TAG_EXIF_IFD_POINTER:
201                 case EXIF_TAG_GPS_INFO_IFD_POINTER:
202                 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
203                 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
204                 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
205                         o = exif_get_long (d + offset + 12 * i + 8,
206                                            data->priv->order);
207                         switch (tag) {
208                         case EXIF_TAG_EXIF_IFD_POINTER:
209                                 exif_data_load_data_content (data,
210                                         data->ifd_exif, d, ds, o);
211                                 break;
212                         case EXIF_TAG_GPS_INFO_IFD_POINTER:
213                                 exif_data_load_data_content (data,
214                                         data->ifd_gps, d, ds, o);
215                                 break;
216                         case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
217                                 exif_data_load_data_content (data,
218                                         data->ifd_interoperability, d, ds, o);
219                                 break;
220                         case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
221 #ifdef DEBUG
222                                 printf ("Thumbnail at %i.\n", (int) o);
223 #endif
224                                 thumbnail_offset = o;
225                                 if (thumbnail_offset && thumbnail_length)
226                                         exif_data_load_data_thumbnail (data, d,
227                                                 ds, thumbnail_offset,
228                                                 thumbnail_length);
229                                 break;
230                         case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
231 #ifdef DEBUG
232                                 printf ("Thumbnail size: %i.\n", (int) o);
233 #endif
234                                 thumbnail_length = o;
235                                 if (thumbnail_offset && thumbnail_length)
236                                         exif_data_load_data_thumbnail (data, d,
237                                                 ds, thumbnail_offset,
238                                                 thumbnail_length);
239                                 break;
240                         default:
241                                 return;
242                         }
243                         break;
244                 default:
245                         entry = exif_entry_new ();
246                         exif_content_add_entry (ifd, entry);
247                         exif_data_load_data_entry (data, entry, d, ds,
248                                                    offset + 12 * i);
249                         exif_entry_unref (entry);
250                         break;
251                 }
252         }
253 }
254
255 static void
256 exif_data_save_data_content (ExifData *data, ExifContent *ifd,
257                              unsigned char **d, unsigned int *ds,
258                              unsigned int offset)
259 {
260         unsigned int i, n_ptr = 0, n_thumb = 0;
261
262         /* If we are to save IFD 0, we need some extra entries. */
263         if (ifd == data->ifd0)
264                 n_ptr = 3;
265
266         /*
267          * If we are to save IFD 1, we can point to the thumbnail if it
268          * exists.
269          */
270         if ((ifd == data->ifd1) && data->data)
271                 n_thumb = 2;
272
273         /*
274          * Allocate enough memory for all entries
275          * and the number of entries.
276          */
277         *ds += (2 + (ifd->count + n_ptr + n_thumb) * 12 + (n_ptr ? 4 : 0));
278         *d = realloc (*d, sizeof (char) * *ds);
279
280         /* Save the number of entries */
281         exif_set_short (*d + 6 + offset, data->priv->order,
282                         ifd->count + n_ptr + n_thumb);
283         offset += 2;
284 #ifdef DEBUG
285         printf ("Saving %i entries (offset: %i)...\n", ifd->count, offset);
286 #endif
287
288         /* Save each entry */
289         for (i = 0; i < ifd->count; i++)
290                 exif_data_save_data_entry (data, ifd->entries[i],
291                                 d, ds, offset + 12 * i);
292         offset += 12 * ifd->count;
293
294         /* Save special entries */
295         if (n_ptr) {
296
297                 /* EXIF_TAG_EXIF_IFD_POINTER */
298                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
299                                 EXIF_TAG_EXIF_IFD_POINTER);
300                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
301                                 EXIF_FORMAT_LONG);
302                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
303                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
304                                 *ds - 6);
305                 exif_data_save_data_content (data, data->ifd_exif, d, ds,
306                                              *ds - 6);
307                 offset += 12;
308
309                 /* EXIF_TAG_GPS_INFO_IFD_POINTER */
310                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
311                                 EXIF_TAG_GPS_INFO_IFD_POINTER);
312                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
313                                 EXIF_FORMAT_LONG);
314                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
315                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
316                                 *ds - 6);
317                 exif_data_save_data_content (data, data->ifd_gps, d, ds,
318                                              *ds - 6);
319                 offset += 12;
320
321                 /* EXIF_TAG_INTEROPERABILITY_IFD_POINTER */
322                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
323                                 EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
324                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
325                                 EXIF_FORMAT_LONG);
326                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
327                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
328                                 *ds - 6);
329                 exif_data_save_data_content (data, data->ifd_interoperability,
330                                              d, ds, *ds - 6);
331                 offset += 12;
332
333                 /*
334                  * We are saving IFD 0. Tell where IFD 1 starts and save
335                  * IFD 1.
336                  */
337                 exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
338                 exif_data_save_data_content (data, data->ifd1, d, ds,
339                                              *ds - 6);
340         }
341
342         if (n_thumb) {
343
344                 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
345                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
346                                 EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
347                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
348                                 EXIF_FORMAT_LONG);
349                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
350                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
351                                 data->size);
352                 offset += 12;
353                 
354                 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
355                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
356                                 EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
357                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
358                                 EXIF_FORMAT_LONG);
359                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
360                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
361                                 *ds - 6);
362                 *ds += data->size;
363                 *d = realloc (*d, sizeof (char) * *ds);
364                 memcpy (*d + *ds - data->size, data->data, data->size);
365         }
366 }
367
368 void
369 exif_data_load_data (ExifData *data, const unsigned char *d, unsigned int size)
370 {
371         unsigned int l, len = size;
372         ExifLong offset;
373         ExifShort n;
374
375         if (!data)
376                 return;
377         if (!d || !size)
378                 return;
379
380 #ifdef DEBUG
381         printf ("Parsing %i byte(s) EXIF data...\n", size);
382 #endif
383
384         /*
385          * It can be that the data starts with the EXIF header. If it does
386          * not, search the EXIF marker.
387          */
388         if (size < 6) {
389 #ifdef DEBUG
390                 printf ("Size too small.\n");
391                 return;
392 #endif
393         }
394         if (!memcmp (d, ExifHeader, 6)) {
395 #ifdef DEBUG
396                 printf ("Found EXIF header.\n");
397 #endif
398         } else {
399 #ifdef DEBUG
400                 printf ("Data begins with 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
401                         "0x%x...\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6]);
402 #endif
403                 while (1) {
404                         while ((d[0] == 0xff) && size) {
405                                 d++;
406                                 size--;
407                         }
408
409                         /* JPEG_MARKER_SOI */
410                         if (d[0] == JPEG_MARKER_SOI) {
411                                 d++;
412                                 size--;
413                                 continue;
414                         }
415
416                         /* JPEG_MARKER_APP0 */
417                         if (d[0] == JPEG_MARKER_APP0) {
418                                 d++;
419                                 size--;
420                                 l = (d[0] << 8) | d[1];
421                                 if (l > size)
422                                         return;
423                                 d += l;
424                                 size -= l;
425                                 continue;
426                         }
427
428                         /* JPEG_MARKER_APP1 */
429                         if (d[0] == JPEG_MARKER_APP1)
430                                 break;
431
432                         /* Unknown marker or data. Give up. */
433                         printf ("EXIF marker not found.\n");
434                         return;
435                 }
436                 d++;
437                 size--;
438                 if (size < 2) {
439 #ifdef DEBUG
440                         printf ("Size too small.\n");
441 #endif
442                         return;
443                 }
444                 len = (d[0] << 8) | d[1];
445 #ifdef DEBUG
446                 printf ("We have to deal with %i byte(s) of EXIF data.\n", len);
447 #endif
448                 d += 2;
449                 size -= 2;
450         }
451
452         /*
453          * Verify the exif header
454          * (offset 2, length 6).
455          */
456         if (size < 6) {
457 #ifdef DEBUG
458                 printf ("Size too small.\n");
459                 return;
460 #endif
461         }
462         if (memcmp (d, ExifHeader, 6)) {
463 #ifdef DEBUG
464                 printf ("EXIF header not found.\n");
465                 return;
466 #endif
467         }
468
469 #ifdef DEBUG
470         printf ("Found EXIF header.\n");
471 #endif
472
473         /* Byte order (offset 6, length 2) */
474         if (size < 12)
475                 return;
476         if (!memcmp (d + 6, "II", 2))
477                 data->priv->order = EXIF_BYTE_ORDER_INTEL;
478         else if (!memcmp (d + 6, "MM", 2))
479                 data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
480         else
481                 return;
482
483         /* Fixed value */
484         if (exif_get_short (d + 8, data->priv->order) != 0x002a)
485                 return;
486
487         /* IFD 0 offset */
488         offset = exif_get_long (d + 10, data->priv->order);
489 #ifdef DEBUG
490         printf ("IFD 0 at %i.\n", (int) offset);
491 #endif
492
493         /* Parse the actual exif data (offset 14) */
494         exif_data_load_data_content (data, data->ifd0, d + 6,
495                                      size - 6, offset);
496
497         /* IFD 1 offset */
498         n = exif_get_short (d + 6 + offset, data->priv->order);
499         offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
500         if (offset) {
501 #ifdef DEBUG
502                 printf ("IFD 1 at %i.\n", (int) offset);
503 #endif
504                 exif_data_load_data_content (data, data->ifd1, d + 6,
505                                              size - 6, offset);
506         }
507 }
508
509 void
510 exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
511 {
512         if (!data)
513                 return;
514         if (!d || !ds)
515                 return;
516
517         /* Header */
518         *ds = 6;
519         *d = malloc (sizeof (char) * *ds);
520         memcpy (*d, ExifHeader, 6);
521
522         /* Order (offset 6) */
523         *ds += 2;
524         *d = realloc (*d, sizeof (char) * *ds);
525         if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
526                 memcpy (*d + 6, "II", 2);
527         } else {
528                 memcpy (*d + 6, "MM", 2);
529         }
530
531         /* Fixed value (2 bytes, offset 8) */
532         *ds += 2;
533         *d = realloc (*d, sizeof (char) * *ds);
534         exif_set_short (*d + 8, data->priv->order, 0x002a);
535
536         /*
537          * IFD 0 offset (4 bytes, offset 10).
538          * We will start 8 bytes after the
539          * EXIF header (2 bytes for order, another 2 for the test, and 
540          * 4 bytes for the IFD 0 offset make 8 bytes together).
541          */
542         *ds += 4;
543         *d = realloc (*d, sizeof (char) * *ds);
544         exif_set_long (*d + 10, data->priv->order, 8);
545
546         /* Now save IFD 0. IFD 1 will be saved automatically. */
547 #ifdef DEBUG
548         printf ("Saving IFDs...\n");
549 #endif
550         exif_data_save_data_content (data, data->ifd0, d, ds, *ds - 6);
551
552 #ifdef DEBUG
553         printf ("Saved %i byte(s) EXIF data.\n", *ds);
554 #endif
555 }
556
557 ExifData *
558 exif_data_new_from_file (const char *path)
559 {
560         FILE *f;
561         unsigned int size;
562         unsigned char *data;
563         ExifData *edata;
564
565         f = fopen (path, "r");
566         if (!f)
567                 return (NULL);
568
569         /* For now, we read the data into memory. Patches welcome... */
570         fseek (f, 0, SEEK_END);
571         size = ftell (f);
572         fseek (f, 0, SEEK_SET);
573         data = malloc (sizeof (char) * size);
574         if (!data)
575                 return (NULL);
576         if (fread (data, 1, size, f) != size) {
577                 free (data);
578                 return (NULL);
579         }
580
581         edata = exif_data_new_from_data (data, size);
582         free (data);
583
584         fclose (f);
585
586         return (edata);
587 }
588
589 void
590 exif_data_ref (ExifData *data)
591 {
592         if (!data)
593                 return;
594
595         data->priv->ref_count++;
596 }
597
598 void
599 exif_data_unref (ExifData *data)
600 {
601         if (!data)
602                 return;
603
604         data->priv->ref_count--;
605         if (!data->priv->ref_count)
606                 exif_data_free (data);
607 }
608
609 void
610 exif_data_free (ExifData *data)
611 {
612         if (data->ifd0)
613                 exif_content_unref (data->ifd0);
614         if (data->ifd1)
615                 exif_content_unref (data->ifd1);
616         if (data->data)
617                 free (data->data);
618         free (data->priv);
619         free (data);
620 }
621
622 void
623 exif_data_dump (ExifData *data)
624 {
625         if (!data)
626                 return;
627
628         if (data->ifd0->count) {
629                 printf ("Dumping IFD 0...\n");
630                 exif_content_dump (data->ifd0, 0);
631         }
632
633         if (data->ifd1->count) {
634                 printf ("Dumping IFD 1...\n");
635                 exif_content_dump (data->ifd1, 0);
636         }
637
638         if (data->ifd_exif->count) {
639                 printf ("Dumping IFD EXIF...\n");
640                 exif_content_dump (data->ifd_exif, 0);
641         }
642
643         if (data->ifd_gps->count) {
644                 printf ("Dumping IFD GPS...\n");
645                 exif_content_dump (data->ifd_gps, 0);
646         }
647
648         if (data->ifd_interoperability->count) {
649                 printf ("Dumping IFD Interoperability...\n");
650                 exif_content_dump (data->ifd_interoperability, 0);
651         }
652
653         if (data->data) {
654                 printf ("%i byte(s) thumbnail data available.", data->size);
655                 if (data->size >= 4) {
656                         printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n",
657                                 data->data[0], data->data[1],
658                                 data->data[data->size - 2],
659                                 data->data[data->size - 1]);
660                 }
661         }
662 }