2002-08-29 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 #include <libexif/exif-utils.h>
30 #include <libexif/exif-ifd.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 i, n_ptr = 0, n_thumb = 0;
260
261         /*
262          * Check if we need some extra entries for pointers or the thumbnail.
263          */
264         if (ifd == data->ifd[EXIF_IFD_0]) {
265
266                 /*
267                  * The pointer to IFD_EXIF is in IFD_0. The pointer to
268                  * IFD_INTEROPERABILITY is in IFD_EXIF.
269                  */
270                 if (data->ifd[EXIF_IFD_EXIF]->count || data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
271                         n_ptr++;
272
273                 /* The pointer to IFD_GPS is in IFD_0. */
274                 if (data->ifd[EXIF_IFD_GPS]->count)
275                         n_ptr++;
276         } else if ((ifd == data->ifd[EXIF_IFD_1]) && data->size) {
277                 n_thumb = 2;
278         } else if (ifd == data->ifd[EXIF_IFD_EXIF]) {
279                 if (data->ifd[EXIF_IFD_INTEROPERABILITY]->count)
280                         n_ptr++;
281         }
282
283         /*
284          * Allocate enough memory for all entries
285          * and the number of entries.
286          */
287         *ds += (2 + (ifd->count + n_ptr + n_thumb) * 12 + 4);
288         *d = realloc (*d, sizeof (char) * *ds);
289
290         /* Save the number of entries */
291         exif_set_short (*d + 6 + offset, data->priv->order,
292                         ifd->count + n_ptr + n_thumb);
293         offset += 2;
294 #ifdef DEBUG
295         printf ("Saving %i entries (offset: %i)...\n", ifd->count, offset);
296 #endif
297
298         /* Save each entry */
299         for (i = 0; i < ifd->count; i++)
300                 exif_data_save_data_entry (data, ifd->entries[i],
301                                 d, ds, offset + 12 * i);
302         offset += 12 * ifd->count;
303
304         /*
305          * The pointer to IFD_EXIF is in IFD_0.
306          * However, the pointer to IFD_INTEROPERABILITY is in IFD_EXIF,
307          * therefore, if IFD_INTEROPERABILITY is not empty, we need
308          * IFD_EXIF even if latter is empty.
309          */
310         if (ifd == data->ifd[EXIF_IFD_0] && (
311                         data->ifd[EXIF_IFD_EXIF]->count ||
312                         data->ifd[EXIF_IFD_INTEROPERABILITY]->count)) {
313                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
314                                 EXIF_TAG_EXIF_IFD_POINTER);
315                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
316                                 EXIF_FORMAT_LONG);
317                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
318                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
319                                 *ds - 6);
320                 exif_data_save_data_content (data, data->ifd[EXIF_IFD_EXIF], d,
321                                              ds, *ds - 6);
322                 offset += 12;
323         }
324
325         /* The pointer to IFD_GPS is in IFD_0. */
326         if (ifd == data->ifd[EXIF_IFD_0] && data->ifd[EXIF_IFD_GPS]->count) {
327                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
328                                 EXIF_TAG_GPS_INFO_IFD_POINTER);
329                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
330                                 EXIF_FORMAT_LONG);
331                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
332                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
333                                 *ds - 6);
334                 exif_data_save_data_content (data, data->ifd[EXIF_IFD_GPS], d, ds,
335                                              *ds - 6);
336                 offset += 12;
337         }
338
339         /* The pointer to IFD_INTEROPERABILITY is in IFD_EXIF. See above. */
340         if (ifd == data->ifd[EXIF_IFD_EXIF] && data->ifd[EXIF_IFD_INTEROPERABILITY]->count) {
341                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
342                                 EXIF_TAG_INTEROPERABILITY_IFD_POINTER);
343                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
344                                 EXIF_FORMAT_LONG);
345                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
346                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
347                                 *ds - 6);
348                 exif_data_save_data_content (data, data->ifd[EXIF_IFD_INTEROPERABILITY],
349                                              d, ds, *ds - 6);
350                 offset += 12;
351         }
352
353         /* Information about the thumbnail (if any) is saved in IFD_1. */
354         if ((ifd == data->ifd[EXIF_IFD_1]) && data->size) {
355
356                 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT */
357                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
358                                 EXIF_TAG_JPEG_INTERCHANGE_FORMAT);
359                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
360                                 EXIF_FORMAT_LONG);
361                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
362                 exif_set_long  (*d + 6 + offset + 8, data->priv->order,
363                                 *ds - 6);
364                 *ds += data->size;
365                 *d = realloc (*d, sizeof (char) * *ds);
366                 memcpy (*d + *ds - data->size, data->data, data->size);
367                 offset += 12;
368
369                 /* EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH */
370                 exif_set_short (*d + 6 + offset + 0, data->priv->order,
371                                 EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
372                 exif_set_short (*d + 6 + offset + 2, data->priv->order,
373                                 EXIF_FORMAT_LONG);
374                 exif_set_long  (*d + 6 + offset + 4, data->priv->order, 1);
375                 exif_set_long  (*d + 6 + offset + 8, data->priv->order, 
376                                 data->size);
377                 offset += 12;
378         }
379
380         if (ifd == data->ifd[EXIF_IFD_0] && (data->ifd[EXIF_IFD_1]->count ||
381                                              data->size)) {
382
383                 /*
384                  * We are saving IFD 0. Tell where IFD 1 starts and save
385                  * IFD 1.
386                  */
387                 exif_set_long (*d + 6 + offset, data->priv->order, *ds - 6);
388                 exif_data_save_data_content (data, data->ifd[EXIF_IFD_1], d, ds,
389                                              *ds - 6);
390         } else
391                 exif_set_long (*d + 6 + offset, data->priv->order, 0);
392 }
393
394 void
395 exif_data_load_data (ExifData *data, const unsigned char *d, unsigned int size)
396 {
397         unsigned int l, len = size;
398         ExifLong offset;
399         ExifShort n;
400
401         if (!data)
402                 return;
403         if (!d || !size)
404                 return;
405
406 #ifdef DEBUG
407         printf ("Parsing %i byte(s) EXIF data...\n", size);
408 #endif
409
410         /*
411          * It can be that the data starts with the EXIF header. If it does
412          * not, search the EXIF marker.
413          */
414         if (size < 6) {
415 #ifdef DEBUG
416                 printf ("Size too small.\n");
417 #endif
418                 return;
419         }
420         if (!memcmp (d, ExifHeader, 6)) {
421 #ifdef DEBUG
422                 printf ("Found EXIF header.\n");
423 #endif
424         } else {
425 #ifdef DEBUG
426                 printf ("Data begins with 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
427                         "0x%x...\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6]);
428 #endif
429                 while (1) {
430                         while ((d[0] == 0xff) && size) {
431                                 d++;
432                                 size--;
433                         }
434
435                         /* JPEG_MARKER_SOI */
436                         if (d[0] == JPEG_MARKER_SOI) {
437                                 d++;
438                                 size--;
439                                 continue;
440                         }
441
442                         /* JPEG_MARKER_APP0 */
443                         if (d[0] == JPEG_MARKER_APP0) {
444                                 d++;
445                                 size--;
446                                 l = (d[0] << 8) | d[1];
447                                 if (l > size)
448                                         return;
449                                 d += l;
450                                 size -= l;
451                                 continue;
452                         }
453
454                         /* JPEG_MARKER_APP1 */
455                         if (d[0] == JPEG_MARKER_APP1)
456                                 break;
457
458                         /* Unknown marker or data. Give up. */
459 #ifdef DEBUG
460                         printf ("EXIF marker not found.\n");
461 #endif
462                         return;
463                 }
464                 d++;
465                 size--;
466                 if (size < 2) {
467 #ifdef DEBUG
468                         printf ("Size too small.\n");
469 #endif
470                         return;
471                 }
472                 len = (d[0] << 8) | d[1];
473 #ifdef DEBUG
474                 printf ("We have to deal with %i byte(s) of EXIF data.\n", len);
475 #endif
476                 d += 2;
477                 size -= 2;
478         }
479
480         /*
481          * Verify the exif header
482          * (offset 2, length 6).
483          */
484         if (size < 6) {
485 #ifdef DEBUG
486                 printf ("Size too small.\n");
487 #endif
488                 return;
489         }
490         if (memcmp (d, ExifHeader, 6)) {
491 #ifdef DEBUG
492                 printf ("EXIF header not found.\n");
493 #endif
494                 return;
495         }
496
497 #ifdef DEBUG
498         printf ("Found EXIF header.\n");
499 #endif
500
501         /* Byte order (offset 6, length 2) */
502         if (size < 12)
503                 return;
504         if (!memcmp (d + 6, "II", 2))
505                 data->priv->order = EXIF_BYTE_ORDER_INTEL;
506         else if (!memcmp (d + 6, "MM", 2))
507                 data->priv->order = EXIF_BYTE_ORDER_MOTOROLA;
508         else
509                 return;
510
511         /* Fixed value */
512         if (exif_get_short (d + 8, data->priv->order) != 0x002a)
513                 return;
514
515         /* IFD 0 offset */
516         offset = exif_get_long (d + 10, data->priv->order);
517 #ifdef DEBUG
518         printf ("IFD 0 at %i.\n", (int) offset);
519 #endif
520
521         /* Parse the actual exif data (offset 14) */
522         exif_data_load_data_content (data, data->ifd[EXIF_IFD_0], d + 6,
523                                      size - 6, offset);
524
525         /* IFD 1 offset */
526         n = exif_get_short (d + 6 + offset, data->priv->order);
527         offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
528         if (offset) {
529 #ifdef DEBUG
530                 printf ("IFD 1 at %i.\n", (int) offset);
531 #endif
532
533                 /* Sanity check. */
534                 if (offset > size - 6) {
535 #ifdef DEBUG
536                         printf ("Bogus offset!\n");
537 #endif
538                         return;
539                 }
540
541                 exif_data_load_data_content (data, data->ifd[EXIF_IFD_1], d + 6,
542                                              size - 6, offset);
543         }
544 }
545
546 void
547 exif_data_save_data (ExifData *data, unsigned char **d, unsigned int *ds)
548 {
549         if (!data)
550                 return;
551         if (!d || !ds)
552                 return;
553
554         /* Header */
555         *ds = 6;
556         *d = malloc (sizeof (char) * *ds);
557         memcpy (*d, ExifHeader, 6);
558
559         /* Order (offset 6) */
560         *ds += 2;
561         *d = realloc (*d, sizeof (char) * *ds);
562         if (data->priv->order == EXIF_BYTE_ORDER_INTEL) {
563                 memcpy (*d + 6, "II", 2);
564         } else {
565                 memcpy (*d + 6, "MM", 2);
566         }
567
568         /* Fixed value (2 bytes, offset 8) */
569         *ds += 2;
570         *d = realloc (*d, sizeof (char) * *ds);
571         exif_set_short (*d + 8, data->priv->order, 0x002a);
572
573         /*
574          * IFD 0 offset (4 bytes, offset 10).
575          * We will start 8 bytes after the
576          * EXIF header (2 bytes for order, another 2 for the test, and 
577          * 4 bytes for the IFD 0 offset make 8 bytes together).
578          */
579         *ds += 4;
580         *d = realloc (*d, sizeof (char) * *ds);
581         exif_set_long (*d + 10, data->priv->order, 8);
582
583         /* Now save IFD 0. IFD 1 will be saved automatically. */
584 #ifdef DEBUG
585         printf ("Saving IFDs...\n");
586 #endif
587         exif_data_save_data_content (data, data->ifd[EXIF_IFD_0], d, ds, *ds - 6);
588
589 #ifdef DEBUG
590         printf ("Saved %i byte(s) EXIF data.\n", *ds);
591 #endif
592 }
593
594 ExifData *
595 exif_data_new_from_file (const char *path)
596 {
597         FILE *f;
598         unsigned int size;
599         unsigned char *data;
600         ExifData *edata;
601         int marker, ll, lh;
602
603         f = fopen (path, "rb");
604         if (!f)
605                 return (NULL);
606
607         while (1) {
608                 while ((marker = fgetc (f)) == 0xff);
609
610                 /* JPEG_MARKER_SOI */
611                 if (marker == JPEG_MARKER_SOI)
612                         continue;
613
614                 /* JPEG_MARKER_APP0 */
615                 if (marker == JPEG_MARKER_APP0) {
616                         lh = fgetc (f);
617                         ll = fgetc (f);
618                         size = (lh << 8) | ll;
619                         if (fseek (f, size - 2, SEEK_CUR) < 0)
620                                 return (NULL);
621                         continue;
622                 }
623
624                 /* JPEG_MARKER_APP1 */
625                 if (marker == JPEG_MARKER_APP1)
626                         break;
627
628                 /* Unknown marker or data. Give up. */
629                 return (NULL);
630         }
631
632         /* EXIF data found. Allocate the necessary memory and read the data. */
633         lh = fgetc (f);
634         ll = fgetc (f);
635         size = (lh << 8) | ll;
636         data = malloc (sizeof (char) * size);
637         if (!data)
638                 return (NULL);
639         if (fread (data, 1, size, f) != size) {
640                 free (data);
641                 return (NULL);
642         }
643
644         edata = exif_data_new_from_data (data, size);
645         free (data);
646
647         fclose (f);
648
649         return (edata);
650 }
651
652 void
653 exif_data_ref (ExifData *data)
654 {
655         if (!data)
656                 return;
657
658         data->priv->ref_count++;
659 }
660
661 void
662 exif_data_unref (ExifData *data)
663 {
664         if (!data)
665                 return;
666
667         data->priv->ref_count--;
668         if (!data->priv->ref_count)
669                 exif_data_free (data);
670 }
671
672 void
673 exif_data_free (ExifData *data)
674 {
675         unsigned int i;
676
677         if (!data)
678                 return;
679
680         for (i = 0; i < EXIF_IFD_COUNT; i++) {
681                 if (data->ifd[i]) {
682                         exif_content_unref (data->ifd[i]);
683                         data->ifd[i] = NULL;
684                 }
685         }
686         if (data->data) {
687                 free (data->data);
688                 data->data = NULL;
689         }
690         if (data->priv) {
691                 free (data->priv);
692                 data->priv = NULL;
693         }
694         free (data);
695 }
696
697 void
698 exif_data_dump (ExifData *data)
699 {
700         unsigned int i;
701
702         if (!data)
703                 return;
704
705         for (i = 0; i < EXIF_IFD_COUNT; i++) {
706                 if (data->ifd[i] && data->ifd[i]->count) {
707                         printf ("Dumping IFD '%s'...\n",
708                                 exif_ifd_get_name (i));
709                         exif_content_dump (data->ifd[i], 0);
710                 }
711         }
712
713         if (data->data) {
714                 printf ("%i byte(s) thumbnail data available.", data->size);
715                 if (data->size >= 4) {
716                         printf ("0x%02x 0x%02x ... 0x%02x 0x%02x\n",
717                                 data->data[0], data->data[1],
718                                 data->data[data->size - 2],
719                                 data->data[data->size - 1]);
720                 }
721         }
722 }
723
724 ExifByteOrder
725 exif_data_get_byte_order (ExifData *data)
726 {
727         if (!data)
728                 return (0);
729
730         return (data->priv->order);
731 }
732
733 void
734 exif_data_foreach_content (ExifData *data, ExifDataForeachContentFunc func,
735                            void *user_data)
736 {
737         unsigned int i;
738
739         if (!data || !func)
740                 return;
741
742         for (i = 0; i < EXIF_IFD_COUNT; i++)
743                 func (data->ifd[i], user_data);
744 }
745
746 typedef struct _ByteOrderChangeData ByteOrderChangeData;
747 struct _ByteOrderChangeData {
748         ExifByteOrder old, new;
749 };
750
751 static void
752 entry_set_byte_order (ExifEntry *e, void *data)
753 {
754         ByteOrderChangeData *d = data;
755         unsigned int i;
756         ExifShort s;
757         ExifLong l;
758         ExifSLong sl;
759         ExifRational r;
760         ExifSRational sr;
761
762         if (!e)
763                 return;
764
765         switch (e->format) {
766         case EXIF_FORMAT_SHORT:
767                 for (i = 0; i < e->components; i++) {
768                         s = exif_get_short (e->data +
769                                 (i * exif_format_get_size (e->format)),
770                                 d->old);
771                         exif_set_short (e->data + 
772                                 (i * exif_format_get_size (e->format)),
773                                 d->new, s);
774                 }
775                 break;
776         case EXIF_FORMAT_LONG:
777                 for (i = 0; i < e->components; i++) {
778                         l = exif_get_long (e->data +
779                                 (i * exif_format_get_size (e->format)),
780                                 d->old);
781                         exif_set_long (e->data +
782                                 (i * exif_format_get_size (e->format)),
783                                 d->new, l);
784                 }
785                 break;
786         case EXIF_FORMAT_RATIONAL:
787                 for (i = 0; i < e->components; i++) {
788                         r = exif_get_rational (e->data +
789                                 (i * exif_format_get_size (e->format)),
790                                 d->old);
791                         exif_set_rational (e->data +
792                                 (i * exif_format_get_size (e->format)),
793                                 d->new, r);
794                 }
795                 break;
796         case EXIF_FORMAT_SLONG:
797                 for (i = 0; i < e->components; i++) {
798                         sl = exif_get_slong (e->data +
799                                 (i * exif_format_get_size (e->format)),
800                                 d->old);
801                         exif_set_slong (e->data +
802                                 (i * exif_format_get_size (e->format)),
803                                 d->new, sl);
804                 }
805                 break;
806         case EXIF_FORMAT_SRATIONAL:
807                 for (i = 0; i < e->components; i++) {
808                         sr = exif_get_srational (e->data +
809                                 (i * exif_format_get_size (e->format)),
810                                 d->old);
811                         exif_set_srational (e->data +
812                                 (i * exif_format_get_size (e->format)),
813                                 d->new, sr);
814                 }
815                 break;
816         case EXIF_FORMAT_UNDEFINED:
817         case EXIF_FORMAT_BYTE:
818         case EXIF_FORMAT_ASCII:
819         default:
820                 /* Nothing here. */
821                 break;
822         }
823 }
824
825 static void
826 content_set_byte_order (ExifContent *content, void *data)
827 {
828         exif_content_foreach_entry (content, entry_set_byte_order, data);
829 }
830
831 void
832 exif_data_set_byte_order (ExifData *data, ExifByteOrder order)
833 {
834         ByteOrderChangeData d;
835
836         if (!data || (order == data->priv->order))
837                 return;
838
839         d.old = data->priv->order;
840         d.new = order;
841         exif_data_foreach_content (data, content_set_byte_order, &d);
842         data->priv->order = order;
843 }