2003-07-30 Lutz Mueller <lutz@users.sourceforge.net>
[platform/upstream/libexif.git] / libexif / exif-data.c
1 /* exif-data.c
2  *
3  * Copyright © 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
21 #include "config.h"
22 #include "exif-data.h"
23 #include "exif-ifd.h"
24 #include "exif-utils.h"
25 #include "exif-loader.h"
26 #include "jpeg-marker.h"
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #undef MAX
33 #define MAX(a, b)  (((a) > (b)) ? (a) : (b))
34
35 //#define DEBUG
36
37 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
38
39 struct _ExifDataPrivate
40 {
41         ExifByteOrder order;
42
43         unsigned int ref_count;
44 };
45
46 ExifData *
47 exif_data_new (void)
48 {
49         ExifData *data;
50         unsigned int i;
51
52         data = malloc (sizeof (ExifData));
53         if (!data)
54                 return (NULL);
55         memset (data, 0, sizeof (ExifData));
56         data->priv = malloc (sizeof (ExifDataPrivate));
57         if (!data->priv) {
58                 free (data);
59                 return (NULL);
60         }
61         memset (data->priv, 0, sizeof (ExifDataPrivate));
62         data->priv->ref_count = 1;
63
64         for (i = 0; i < EXIF_IFD_COUNT; i++) {
65                 data->ifd[i] = exif_content_new ();
66                 if (!data->ifd[i]) {
67                         exif_data_free (data);
68                         return (NULL);
69                 }
70                 data->ifd[i]->parent = data;
71         }
72
73         return (data);
74 }
75
76 ExifData *
77 exif_data_new_from_data (const unsigned char *data, unsigned int size)
78 {
79         ExifData *edata;
80
81         edata = exif_data_new ();
82         exif_data_load_data (edata, data, size);
83         return (edata);
84 }
85
86 static void
87 exif_data_load_data_entry (ExifData *data, ExifEntry *entry,
88                            const unsigned char *d,
89                            unsigned int size, unsigned int offset)
90 {
91         unsigned int s, doff;
92
93         entry->tag        = exif_get_short (d + offset + 0, data->priv->order);
94         entry->format     = exif_get_short (d + offset + 2, data->priv->order);
95         entry->components = exif_get_long  (d + offset + 4, data->priv->order);
96
97         /*
98          * Size? If bigger than 4 bytes, the actual data is not
99          * in the entry but somewhere else (offset).
100          */
101         s = exif_format_get_size (entry->format) * entry->components;
102         if (!s)
103                 return;
104         if (s > 4)
105                 doff = exif_get_long (d + offset + 8, data->priv->order);
106         else
107                 doff = offset + 8;
108
109         /* Sanity check */
110         if (size < doff + s)
111                 return;
112
113         entry->data = malloc (sizeof (char) * s);
114         if (!entry->data)
115                 return;
116         entry->size = s;
117         memcpy (entry->data, d + doff, s);
118 }
119
120 static void
121 exif_data_save_data_entry (ExifData *data, ExifEntry *entry,
122                            unsigned char **d, unsigned int *ds,
123                            unsigned int offset)
124 {
125         unsigned int doff, s;
126
127         /*
128          * Each entry is 12 bytes long. The memory for the entry has
129          * already been allocated.
130          */
131         exif_set_short (*d + 6 + offset + 0,
132                         data->priv->order, entry->tag);
133         exif_set_short (*d + 6 + offset + 2,
134                         data->priv->order, entry->format);
135         exif_set_long  (*d + 6 + offset + 4,
136                         data->priv->order, entry->components);
137
138         /*
139          * Size? If bigger than 4 bytes, the actual data is not in
140          * the entry but somewhere else.
141          */
142         s = exif_format_get_size (entry->format) * entry->components;
143         if (!s)
144                 return;
145         if (s > 4) {
146                 *ds += entry->size;
147                 *d = realloc (*d, sizeof (char) * *ds);
148                 doff = *ds - 6 - entry->size;
149                 exif_set_long (*d + 6 + offset + 8,
150                                data->priv->order, doff);
151         } else
152                 doff = offset + 8;
153         memcpy (*d + 6 + doff, entry->data, entry->size);
154 }
155
156 static void
157 exif_data_load_data_thumbnail (ExifData *data, const unsigned char *d,
158                                unsigned int ds, ExifLong offset, ExifLong size)
159 {
160         if (ds < offset + size) {
161 #ifdef DEBUG
162                 printf ("Bogus thumbnail offset and size: %i < %i + %i.\n",
163                         (int) ds, (int) offset, (int) size);
164 #endif
165                 return;
166         }
167         if (data->data)
168                 free (data->data);
169         data->size = size;
170         data->data = malloc (sizeof (char) * data->size);
171         memcpy (data->data, d + offset, data->size);
172 }
173
174 static void
175 exif_data_load_data_content (ExifData *data, ExifContent *ifd,
176                              const unsigned char *d,
177                              unsigned int ds, unsigned int offset)
178 {
179         ExifLong o, thumbnail_offset = 0, thumbnail_length = 0;
180         ExifShort n;
181         ExifEntry *entry;
182         unsigned int i;
183         ExifTag tag;
184
185         /* Read the number of entries */
186         n = exif_get_short (d + offset, data->priv->order);
187 #ifdef DEBUG
188         printf ("Loading %i entries...\n", n);
189 #endif
190         offset += 2;
191         for (i = 0; i < n; i++) {
192
193                 tag = exif_get_short (d + offset + 12 * i, data->priv->order);
194 #ifdef DEBUG
195                 printf ("Loading entry '%s' (%i of %i)...\n",
196                         exif_tag_get_name (tag), i + 1, n);
197 #endif
198                 switch (tag) {
199                 case EXIF_TAG_EXIF_IFD_POINTER:
200                 case EXIF_TAG_GPS_INFO_IFD_POINTER:
201                 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
202                 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
203                 case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
204                         o = exif_get_long (d + offset + 12 * i + 8,
205                                            data->priv->order);
206                         switch (tag) {
207                         case EXIF_TAG_EXIF_IFD_POINTER:
208                                 exif_data_load_data_content (data,
209                                         data->ifd[EXIF_IFD_EXIF], d, ds, o);
210                                 break;
211                         case EXIF_TAG_GPS_INFO_IFD_POINTER:
212                                 exif_data_load_data_content (data,
213                                         data->ifd[EXIF_IFD_GPS], d, ds, o);
214                                 break;
215                         case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
216                                 exif_data_load_data_content (data,
217                                         data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds, o);
218                                 break;
219                         case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
220 #ifdef DEBUG
221                                 printf ("Thumbnail at %i.\n", (int) o);
222 #endif
223                                 thumbnail_offset = o;
224                                 if (thumbnail_offset && thumbnail_length)
225                                         exif_data_load_data_thumbnail (data, d,
226                                                 ds, thumbnail_offset,
227                                                 thumbnail_length);
228                                 break;
229                         case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
230 #ifdef DEBUG
231                                 printf ("Thumbnail size: %i.\n", (int) o);
232 #endif
233                                 thumbnail_length = o;
234                                 if (thumbnail_offset && thumbnail_length)
235                                         exif_data_load_data_thumbnail (data, d,
236                                                 ds, thumbnail_offset,
237                                                 thumbnail_length);
238                                 break;
239                         default:
240                                 return;
241                         }
242                         break;
243                 default:
244                         entry = exif_entry_new ();
245                         exif_content_add_entry (ifd, entry);
246                         exif_data_load_data_entry (data, entry, d, ds,
247                                                    offset + 12 * i);
248                         exif_entry_unref (entry);
249                         break;
250                 }
251         }
252 }
253
254 static void
255 exif_data_save_data_content (ExifData *data, ExifContent *ifd,
256                              unsigned char **d, unsigned int *ds,
257                              unsigned int offset)
258 {
259         unsigned int j, n_ptr = 0, n_thumb = 0;
260         ExifIfd i;
261
262         if (!data || !ifd || !d || !ds)
263                 return;
264
265         for (i = 0; i < EXIF_IFD_COUNT; i++)
266                 if (ifd == data->ifd[i])
267                         break;
268         if (i == EXIF_IFD_COUNT)
269                 return;
270
271         /*
272          * Check if we need some extra entries for pointers or the thumbnail.
273          */
274         switch (i) {
275         case EXIF_IFD_0:
276
277                 /*
278                  * The pointer to IFD_EXIF is in IFD_0. The pointer to
279                  * IFD_INTEROPERABILITY is in IFD_EXIF.
280                  */
281                 if (data->ifd[EXIF_IFD_EXIF]->count ||
282                     data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
283                         n_ptr++;
284
285                 /* The pointer to IFD_GPS is in IFD_0. */
286                 if (data->ifd[EXIF_IFD_GPS]->count)
287                         n_ptr++;
288
289                 break;
290         case EXIF_IFD_1:
291                 if (data->size)
292                         n_thumb = 2;
293                 break;
294         case EXIF_IFD_EXIF:
295                 if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
296                         n_ptr++;
297         default:
298                 break;
299         }
300
301         /*
302          * Allocate enough memory for all entries
303          * and the number of entries.
304          */
305         *ds += (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
306         *d = realloc (*d, sizeof (char) * *ds);
307
308         /* Save the number of entries */
309         exif_set_short (*d + 6 + offset, data->priv->order,
310                         ifd->count + n_ptr + n_thumb);
311         offset += 2;
312
313 #ifdef DEBUG
314         printf ("Saving %i entries (IFD '%s', offset: %i)...\n",
315                 ifd->count, exif_ifd_get_name (i), offset);
316 #endif
317
318         /* Save each entry */
319         for (j = 0; j < ifd->count; j++)
320                 exif_data_save_data_entry (data, ifd->entries[j],
321                                 d, ds, offset + 12 * j);
322         offset += 12 * ifd->count;
323
324         /* Now save special entries. */
325         switch (i) {
326         case EXIF_IFD_0:
327
328                 /*
329                  * The pointer to IFD_EXIF is in IFD_0.
330                  * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF,
331                  * therefore, if IFD_INTEROPERABILITY is not empty, we need
332                  * IFD_EXIF even if latter is empty.
333                  */
334                 if (data->ifd[EXIF_IFD_EXIF]->count ||
335                     data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
336                         exif_set_short (*d + 6 + offset + 0, data->priv->order,
337                                         EXIF_TAG_EXIF_IFD_POINTER);
338                         exif_set_short (*d + 6 + offset + 2, data->priv->order,
339                                         EXIF_FORMAT_LONG);
340                         exif_set_long  (*d + 6 + offset + 4, data->priv->order,
341                                         1);
342                         exif_set_long  (*d + 6 + offset + 8, data->priv->order,
343                                         *ds - 6);
344                         exif_data_save_data_content (data,
345                                 data->ifd[EXIF_IFD_EXIF], d, ds, *ds - 6);
346                         offset += 12;
347                 }
348
349                 /* The pointer to IFD_GPS is in IFD_0, too. */
350                 if (data->ifd[EXIF_IFD_GPS]->count) {
351                         exif_set_short (*d + 6 + offset + 0, data->priv->order,
352                                         EXIF_TAG_GPS_INFO_IFD_POINTER);
353                         exif_set_short (*d + 6 + offset + 2, data->priv->order,
354                                         EXIF_FORMAT_LONG);
355                         exif_set_long  (*d + 6 + offset + 4, data->priv->order,
356                                         1);
357                         exif_set_long  (*d + 6 + offset + 8, data->priv->order,
358                                         *ds - 6);
359                         exif_data_save_data_content (data,
360                                 data->ifd[EXIF_IFD_GPS], d, ds, *ds - 6);
361                         offset += 12;
362                 }
363
364                 break;
365         case EXIF_IFD_EXIF:
366
367                 /*
368                  * The pointer to IFD_INTEROPERABILITY is in IFD_EXIF.
369                  * See note above.
370                  */
371                 if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
372                         exif_set_short (*d + 6 + offset + 0, data->priv->order,
373                                         EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
374                         exif_set_short (*d + 6 + offset + 2, data->priv->order,
375                                         EXIF_FORMAT_LONG);
376                         exif_set_long  (*d + 6 + offset + 4, data->priv->order,
377                                         1);
378                         exif_set_long  (*d + 6 + offset + 8, data->priv->order,
379                                         *ds - 6);
380                         exif_data_save_data_content (data,
381                                 data->ifd[EXIF_IFD_INTEROPERABILITY], d, ds,
382                                 *ds - 6);
383                         offset += 12;
384                 }
385
386                 break;
387         case EXIF_IFD_1:
388
389                 /*
390                  * Information about the thumbnail (if any) is saved in
391                  * IFD_1.
392                  */
393                 if (data->size) {
394
395                         /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
396                         exif_set_short (*d + 6 + offset + 0, data->priv->order,
397                                         EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
398                         exif_set_short (*d + 6 + offset + 2, data->priv->order,
399                                         EXIF_FORMAT_LONG);
400                         exif_set_long  (*d + 6 + offset + 4, data->priv->order,
401                                         1);
402                         exif_set_long  (*d + 6 + offset + 8, data->priv->order,
403                                         *ds - 6);
404                         *ds += data->size;
405                         *d = realloc (*d, sizeof (char) * *ds);
406                         memcpy (*d + *ds - data->size, data->data, data->size);
407                         offset += 12;
408 #ifdef DEBUG
409                         printf ("Wrote %i bytes of thumbnail data at offset "
410                                 "%i.\n", data->size, *ds - data->size);
411                         printf ("We currently have %i bytes EXIF data.\n", *ds);
412 #endif
413
414                         /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
415                         exif_set_short (*d + 6 + offset + 0, data->priv->order,
416                                 EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
417                         exif_set_short (*d + 6 + offset + 2, data->priv->order,
418                                         EXIF_FORMAT_LONG);
419                         exif_set_long  (*d + 6 + offset + 4, data->priv->order,
420                                         1);
421                         exif_set_long  (*d + 6 + offset + 8, data->priv->order, 
422                                         data->size);
423                         offset += 12;
424                 }
425
426                 break;
427         default:
428                 break;
429         }
430
431         /* Correctly terminate the directory */
432         if (i == EXIF_IFD_0 && (data->ifd[EXIF_IFD_1]->count ||
433                                              data->size)) {
434
435                 /*
436                  * We are saving IFD 0. Tell where IFD 1 starts and save
437                  * IFD 1.
438                  */
439                 exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
440                 exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds,
441                                              *ds - 6);
442         } else
443                 exif_set_long (*d + 6 + offset, data->priv->order, 0);
444 }
445
446 void
447 exif_data_load_data (ExifData *data, const unsigned char *d, unsigned int size)
448 {
449         unsigned int l, len = size;
450         ExifLong offset;
451         ExifShort n;
452
453         if (!data)
454                 return;
455         if (!d || !size)
456                 return;
457
458 #ifdef DEBUG
459         printf ("Parsing %i byte(s) EXIF data...\n", size);
460 #endif
461
462         /*
463          * It can be that the data starts with the EXIF header. If it does
464          * not, search the EXIF marker.
465          */
466         if (size < 6) {
467 #ifdef DEBUG
468                 printf ("Size too small.\n");
469 #endif
470                 return;
471         }
472         if (!memcmp (d, ExifHeader, 6)) {
473 #ifdef DEBUG
474                 printf ("Found EXIF header.\n");
475 #endif
476         } else {
477 #ifdef DEBUG
478                 printf ("Data begins with 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
479                         "0x%x...\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6]);
480 #endif
481                 while (1) {
482                         while ((d[0] == 0xff) && size) {
483                                 d++;
484                                 size--;
485                         }
486
487                         /* JPEG_MARKER_SOI */
488                         if (d[0] == JPEG_MARKER_SOI) {
489                                 d++;
490                                 size--;
491                                 continue;
492                         }
493
494                         /* JPEG_MARKER_APP0 */
495                         if (d[0] == JPEG_MARKER_APP0) {
496                                 d++;
497                                 size--;
498                                 l = (d[0] << 8) | d[1];
499                                 if (l > size)
500                                         return;
501                                 d += l;
502                                 size -= l;
503                                 continue;
504                         }
505
506                         /* JPEG_MARKER_APP1 */
507                         if (d[0] == JPEG_MARKER_APP1)
508                                 break;
509
510                         /* Unknown marker or data. Give up. */
511 #ifdef DEBUG
512                         printf ("EXIF marker not found.\n");
513 #endif
514                         return;
515                 }
516                 d++;
517                 size--;
518                 if (size < 2) {
519 #ifdef DEBUG
520                         printf ("Size too small.\n");
521 #endif
522                         return;
523                 }
524                 len = (d[0] << 8) | d[1];
525 #ifdef DEBUG
526                 printf ("We have to deal with %i byte(s) of EXIF data.\n", len);
527 #endif
528                 d += 2;
529                 size -= 2;
530         }
531
532         /*
533          * Verify the exif header
534          * (offset 2, length 6).
535          */
536         if (size < 6) {
537 #ifdef DEBUG
538                 printf ("Size too small.\n");
539 #endif
540                 return;
541         }
542         if (memcmp (d, ExifHeader, 6)) {
543 #ifdef DEBUG
544                 printf ("EXIF header not found.\n");
545 #endif
546                 return;
547         }
548
549 #ifdef DEBUG
550         printf ("Found EXIF header.\n");
551 #endif
552
553         /* Byte order (offset 6, length 2) */
554         if (size < 12)
555                 return;
556         if (!memcmp (d + 6, "II", 2))
557                 data->priv->order = EXIF_BYTE_ORDER_INTEL;
558         else if (!memcmp (d + 6, "MM", 2))
559                 data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
560         else
561                 return;
562
563         /* Fixed value */
564         if (exif_get_short (d + 8, data->priv->order) != 0x002a)
565                 return;
566
567         /* IFD 0 offset */
568         offset = exif_get_long (d + 10, data->priv->order);
569 #ifdef DEBUG
570         printf ("IFD 0 at %i.\n", (int) offset);
571 #endif
572
573         /* Parse the actual exif data (offset 14) */
574         exif_data_load_data_content (data, data->ifd[EXIF_IFD_0], d + 6,
575                                      size - 6, offset);
576
577         /* IFD 1 offset */
578         n = exif_get_short (d + 6 + offset, data->priv->order);
579         offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
580         if (offset) {
581 #ifdef DEBUG
582                 printf ("IFD 1 at %i.\n", (int) offset);
583 #endif
584
585                 /* Sanity check. */
586                 if (offset > size - 6) {
587 #ifdef DEBUG
588                         printf ("Bogus offset!\n");
589 #endif
590                         return;
591                 }
592
593                 exif_data_load_data_content (data, data->ifd[EXIF_IFD_1], d + 6,
594                                              size - 6, offset);
595         }
596 }
597
598 void
599 exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
600 {
601         if (!data)
602                 return;
603         if (!d || !ds)
604                 return;
605
606         /* Header */
607         *ds = 6;
608         *d = malloc (sizeof (char) * *ds);
609         memcpy (*d, ExifHeader, 6);
610
611         /* Order (offset 6) */
612         *ds += 2;
613         *d = realloc (*d, sizeof (char) * *ds);
614         if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
615                 memcpy (*d + 6, "II", 2);
616         } else {
617                 memcpy (*d + 6, "MM", 2);
618         }
619
620         /* Fixed value (2 bytes, offset 8) */
621         *ds += 2;
622         *d = realloc (*d, sizeof (char) * *ds);
623         exif_set_short (*d + 8, data->priv->order, 0x002a);
624
625         /*
626          * IFD 0 offset (4 bytes, offset 10).
627          * We will start 8 bytes after the
628          * EXIF header (2 bytes for order, another 2 for the test, and 
629          * 4 bytes for the IFD 0 offset make 8 bytes together).
630          */
631         *ds += 4;
632         *d = realloc (*d, sizeof (char) * *ds);
633         exif_set_long (*d + 10, data->priv->order, 8);
634
635         /* Now save IFD 0. IFD 1 will be saved automatically. */
636 #ifdef DEBUG
637         printf ("Saving IFDs...\n");
638 #endif
639         exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds,
640                                      *ds - 6);
641
642 #ifdef DEBUG
643         printf ("Saved %i byte(s) EXIF data.\n", *ds);
644 #endif
645 }
646
647 ExifData *
648 exif_data_new_from_file (const char *path)
649 {
650         FILE *f;
651         int size;
652         ExifData *edata;
653         ExifLoader *loader;
654         unsigned char data[1024];
655
656         f = fopen (path, "rb");
657         if (!f)
658                 return (NULL);
659
660         loader = exif_loader_new ();
661         while (1) {
662                 size = fread (data, 1, 1024, f);
663                 if (size <= 0) break;
664                 if (!exif_loader_write (loader, data, size)) break;
665         }
666         fclose (f);
667
668         edata = exif_loader_get_data (loader);
669         exif_loader_unref (loader);
670
671         return (edata);
672 }
673
674 void
675 exif_data_ref (ExifData *data)
676 {
677         if (!data)
678                 return;
679
680         data->priv->ref_count++;
681 }
682
683 void
684 exif_data_unref (ExifData *data)
685 {
686         if (!data)
687                 return;
688
689         data->priv->ref_count--;
690         if (!data->priv->ref_count)
691                 exif_data_free (data);
692 }
693
694 void
695 exif_data_free (ExifData *data)
696 {
697         unsigned int i;
698
699         if (!data)
700                 return;
701
702         for (i = 0; i < EXIF_IFD_COUNT; i++) {
703                 if (data->ifd[i]) {
704                         exif_content_unref (data->ifd[i]);
705                         data->ifd[i] = NULL;
706                 }
707         }
708         if (data->data) {
709                 free (data->data);
710                 data->data = NULL;
711         }
712         if (data->priv) {
713                 free (data->priv);
714                 data->priv = NULL;
715         }
716         free (data);
717 }
718
719 void
720 exif_data_dump (ExifData *data)
721 {
722         unsigned int i;
723
724         if (!data)
725                 return;
726
727         for (i = 0; i < EXIF_IFD_COUNT; i++) {
728                 if (data->ifd[i] && data->ifd[i]->count) {
729                         printf ("Dumping IFD '%s'...\n",
730                                 exif_ifd_get_name (i));
731                         exif_content_dump (data->ifd[i], 0);
732                 }
733         }
734
735         if (data->data) {
736                 printf ("%i byte(s) thumbnail data available.", data->size);
737                 if (data->size >= 4) {
738                         printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n",
739                                 data->data[0], data->data[1],
740                                 data->data[data->size - 2],
741                                 data->data[data->size - 1]);
742                 }
743         }
744 }
745
746 ExifByteOrder
747 exif_data_get_byte_order (ExifData *data)
748 {
749         if (!data)
750                 return (0);
751
752         return (data->priv->order);
753 }
754
755 void
756 exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func,
757                            void *user_data)
758 {
759         unsigned int i;
760
761         if (!data || !func)
762                 return;
763
764         for (i = 0; i < EXIF_IFD_COUNT; i++)
765                 func (data->ifd[i], user_data);
766 }
767
768 typedef struct _ByteOrderChangeData ByteOrderChangeData;
769 struct _ByteOrderChangeData {
770         ExifByteOrder old, new;
771 };
772
773 static void
774 entry_set_byte_order (ExifEntry *e, void *data)
775 {
776         ByteOrderChangeData *d = data;
777         unsigned int i;
778         ExifShort s;
779         ExifLong l;
780         ExifSLong sl;
781         ExifRational r;
782         ExifSRational sr;
783
784         if (!e)
785                 return;
786
787         switch (e->format) {
788         case EXIF_FORMAT_SHORT:
789                 for (i = 0; i < e->components; i++) {
790                         s = exif_get_short (e->data +
791                                 (i * exif_format_get_size (e->format)),
792                                 d->old);
793                         exif_set_short (e->data + 
794                                 (i * exif_format_get_size (e->format)),
795                                 d->new, s);
796                 }
797                 break;
798         case EXIF_FORMAT_LONG:
799                 for (i = 0; i < e->components; i++) {
800                         l = exif_get_long (e->data +
801                                 (i * exif_format_get_size (e->format)),
802                                 d->old);
803                         exif_set_long (e->data +
804                                 (i * exif_format_get_size (e->format)),
805                                 d->new, l);
806                 }
807                 break;
808         case EXIF_FORMAT_RATIONAL:
809                 for (i = 0; i < e->components; i++) {
810                         r = exif_get_rational (e->data +
811                                 (i * exif_format_get_size (e->format)),
812                                 d->old);
813                         exif_set_rational (e->data +
814                                 (i * exif_format_get_size (e->format)),
815                                 d->new, r);
816                 }
817                 break;
818         case EXIF_FORMAT_SLONG:
819                 for (i = 0; i < e->components; i++) {
820                         sl = exif_get_slong (e->data +
821                                 (i * exif_format_get_size (e->format)),
822                                 d->old);
823                         exif_set_slong (e->data +
824                                 (i * exif_format_get_size (e->format)),
825                                 d->new, sl);
826                 }
827                 break;
828         case EXIF_FORMAT_SRATIONAL:
829                 for (i = 0; i < e->components; i++) {
830                         sr = exif_get_srational (e->data +
831                                 (i * exif_format_get_size (e->format)),
832                                 d->old);
833                         exif_set_srational (e->data +
834                                 (i * exif_format_get_size (e->format)),
835                                 d->new, sr);
836                 }
837                 break;
838         case EXIF_FORMAT_UNDEFINED:
839         case EXIF_FORMAT_BYTE:
840         case EXIF_FORMAT_ASCII:
841         default:
842                 /* Nothing here. */
843                 break;
844         }
845 }
846
847 static void
848 content_set_byte_order (ExifContent *content, void *data)
849 {
850         exif_content_foreach_entry (content, entry_set_byte_order, data);
851 }
852
853 void
854 exif_data_set_byte_order (ExifData *data, ExifByteOrder order)
855 {
856         ByteOrderChangeData d;
857
858         if (!data || (order == data->priv->order))
859                 return;
860
861         d.old = data->priv->order;
862         d.new = order;
863         exif_data_foreach_content (data, content_set_byte_order, &d);
864         data->priv->order = order;
865 }