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