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