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