2007-12-14 Lutz Mueller <lutz@users.sourceforge.net>
[platform/upstream/libexif.git] / libexif / exif-loader.c
1 /* exif-loader.c
2  *
3  * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful, 
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details. 
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include <libexif/exif-loader.h>
24 #include <libexif/exif-utils.h>
25 #include <libexif/i18n.h>
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdio.h>
30
31 #undef JPEG_MARKER_SOI
32 #define JPEG_MARKER_SOI  0xd8
33 #undef JPEG_MARKER_APP0
34 #define JPEG_MARKER_APP0 0xe0
35 #undef JPEG_MARKER_APP1
36 #define JPEG_MARKER_APP1 0xe1
37 #undef JPEG_MARKER_APP2
38 #define JPEG_MARKER_APP2 0xe2
39 #undef JPEG_MARKER_APP13
40 #define JPEG_MARKER_APP13 0xed
41 #undef JPEG_MARKER_COM
42 #define JPEG_MARKER_COM 0xfe
43
44 typedef enum {
45         EL_READ = 0,
46         EL_READ_SIZE_BYTE_24,
47         EL_READ_SIZE_BYTE_16,
48         EL_READ_SIZE_BYTE_08,
49         EL_READ_SIZE_BYTE_00,
50         EL_SKIP_BYTES,
51         EL_EXIF_FOUND,
52 } ExifLoaderState;
53
54 typedef enum {
55         EL_DATA_FORMAT_UNKNOWN,
56         EL_DATA_FORMAT_EXIF,
57         EL_DATA_FORMAT_JPEG,
58         EL_DATA_FORMAT_FUJI_RAW
59 } ExifLoaderDataFormat;
60
61 struct _ExifLoader {
62         ExifLoaderState state;
63         ExifLoaderDataFormat data_format;
64
65         /* Small buffer used for detection of format */
66         unsigned char b[12];
67         unsigned char b_len;
68
69         unsigned int size;
70         unsigned char *buf;
71         unsigned int bytes_read;
72
73         unsigned int ref_count;
74
75         ExifLog *log;
76         ExifMem *mem;
77 };
78
79 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
80
81 static void *
82 exif_loader_alloc (ExifLoader *l, unsigned int i)
83 {
84         void *d;
85
86         if (!l || !i) 
87                 return NULL;
88
89         d = exif_mem_alloc (l->mem, i);
90         if (d) 
91                 return d;
92
93         EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
94         return NULL;
95 }
96
97 #undef  MIN
98 #define MIN(a, b)  (((a) < (b)) ? (a) : (b))
99
100 void
101 exif_loader_write_file (ExifLoader *l, const char *path)
102 {
103         FILE *f;
104         int size;
105         unsigned char data[1024];
106
107         if (!l) 
108                 return;
109
110         f = fopen (path, "rb");
111         if (!f) {
112                 exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
113                           _("The file '%s' could not be opened."), path);
114                 return;
115         }
116         while (1) {
117                 size = fread (data, 1, sizeof (data), f);
118                 if (size <= 0) 
119                         break;
120                 if (!exif_loader_write (l, data, size)) 
121                         break;
122         }
123         fclose (f);
124 }
125
126 static unsigned int
127 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
128 {
129         if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) 
130                 return 0;
131
132         /* If needed, allocate the buffer. */
133         if (!eld->buf) 
134                 eld->buf = exif_loader_alloc (eld, eld->size);
135         if (!eld->buf) 
136                 return 0;
137
138         /* Copy memory */
139         len = MIN (len, eld->size - eld->bytes_read);
140         memcpy (eld->buf + eld->bytes_read, buf, len);
141         eld->bytes_read += len;
142
143         return (eld->bytes_read >= eld->size) ? 0 : 1;
144 }
145
146 unsigned char
147 exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
148 {
149         unsigned int i;
150
151         if (!eld || (len && !buf)) 
152                 return 0;
153
154         switch (eld->state) {
155         case EL_EXIF_FOUND:
156                 return exif_loader_copy (eld, buf, len);
157         case EL_SKIP_BYTES:
158                 if (eld->size > len) { 
159                         eld->size -= len; 
160                         return 1; 
161                 }
162                 len -= eld->size;
163                 buf += eld->size;
164                 eld->size = 0;
165                 eld->b_len = 0;
166                 switch (eld->data_format) {
167                 case EL_DATA_FORMAT_FUJI_RAW:
168                         eld->state = EL_READ_SIZE_BYTE_24;
169                         break;
170                 default:
171                         eld->state = EL_READ;
172                         break;
173                 }
174                 break;
175         default:
176                 break;
177         }
178
179         if (!len)
180                 return 1;
181         exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
182                   "Scanning %i byte(s) of data...", len);
183
184         /*
185          * First fill the small buffer. Only continue if the buffer
186          * is filled. Note that EXIF data contains at least 12 bytes.
187          */
188         i = MIN (len, sizeof (eld->b) - eld->b_len);
189         if (i) {
190                 memcpy (&eld->b[eld->b_len], buf, i);
191                 eld->b_len += i;
192                 if (eld->b_len < sizeof (eld->b)) 
193                         return 1;
194                 buf += i;
195                 len -= i;
196         }
197
198         switch (eld->data_format) {
199         case EL_DATA_FORMAT_UNKNOWN:
200
201                 /* Check the small buffer against known formats. */
202                 if (!memcmp (eld->b, "FUJIFILM", 8)) {
203
204                         /* Skip to byte 84. There is another offset there. */
205                         eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
206                         eld->size = 84;
207                         eld->state = EL_SKIP_BYTES;
208                         eld->size = 84;
209
210                 } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
211
212                         /* Read the size (2 bytes). */
213                         eld->data_format = EL_DATA_FORMAT_EXIF;
214                         eld->state = EL_READ_SIZE_BYTE_08;
215                 }
216         default:
217                 break;
218         }
219
220         for (i = 0; i < sizeof (eld->b); i++)
221                 switch (eld->state) {
222                 case EL_EXIF_FOUND:
223                         if (!exif_loader_copy (eld, eld->b + i,
224                                         sizeof (eld->b) - i)) 
225                                 return 0;
226                         return exif_loader_copy (eld, buf, len);
227                 case EL_SKIP_BYTES:
228                         eld->size--;
229                         if (!eld->size) 
230                                 eld->state = EL_READ;
231                         break;
232
233                 case EL_READ_SIZE_BYTE_24:
234                         eld->size |= eld->b[i] << 24;
235                         eld->state = EL_READ_SIZE_BYTE_16;
236                         break;
237                 case EL_READ_SIZE_BYTE_16:
238                         eld->size |= eld->b[i] << 16;
239                         eld->state = EL_READ_SIZE_BYTE_08;
240                         break;
241                 case EL_READ_SIZE_BYTE_08:
242                         eld->size |= eld->b[i] << 8;
243                         eld->state = EL_READ_SIZE_BYTE_00;
244                         break;
245                 case EL_READ_SIZE_BYTE_00:
246                         eld->size |= eld->b[i] << 0;
247                         switch (eld->data_format) {
248                         case EL_DATA_FORMAT_JPEG:
249                                 eld->state = EL_SKIP_BYTES;
250                                 eld->size -= 2;
251                                 break;
252                         case EL_DATA_FORMAT_FUJI_RAW:
253                                 eld->data_format = EL_DATA_FORMAT_EXIF;
254                                 eld->state = EL_SKIP_BYTES;
255                                 eld->size -= 86;
256                                 break;
257                         case EL_DATA_FORMAT_EXIF:
258                                 eld->state = EL_EXIF_FOUND;
259                                 break;
260                         default:
261                                 break;
262                         }
263                         break;
264
265                 default:
266                         switch (eld->b[i]) {
267                         case JPEG_MARKER_APP1:
268                           if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
269                                         eld->data_format = EL_DATA_FORMAT_EXIF;
270                                 } else {
271                                         eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
272                                 }
273                                 eld->size = 0;
274                                 eld->state = EL_READ_SIZE_BYTE_08;
275                                 break;
276                         case JPEG_MARKER_APP0:
277                         case JPEG_MARKER_APP2:
278                         case JPEG_MARKER_APP13:
279                         case JPEG_MARKER_COM:
280                                 eld->data_format = EL_DATA_FORMAT_JPEG;
281                                 eld->size = 0;
282                                 eld->state = EL_READ_SIZE_BYTE_08;
283                                 break;
284                         case 0xff:
285                         case JPEG_MARKER_SOI:
286                                 break;
287                         default:
288                                 exif_log (eld->log,
289                                         EXIF_LOG_CODE_CORRUPT_DATA,
290                                         "ExifLoader", _("The data supplied "
291                                                 "does not seem to contain "
292                                                 "EXIF data."));
293                                 exif_loader_reset (eld);
294                                 return 0;
295                         }
296                 }
297
298         /*
299          * If we reach this point, the buffer has not been big enough
300          * to read all data we need. Fill it with new data.
301          */
302         eld->b_len = 0;
303         return exif_loader_write (eld, buf, len);
304 }
305
306 ExifLoader *
307 exif_loader_new (void)
308 {
309         ExifMem *mem = exif_mem_new_default ();
310         ExifLoader *l = exif_loader_new_mem (mem);
311
312         exif_mem_unref (mem);
313
314         return l;
315 }
316
317 ExifLoader *
318 exif_loader_new_mem (ExifMem *mem)
319 {
320         ExifLoader *loader;
321
322         if (!mem) 
323                 return NULL;
324         
325         loader = exif_mem_alloc (mem, sizeof (ExifLoader));
326         if (!loader) 
327                 return NULL;
328         loader->ref_count = 1;
329
330         loader->mem = mem;
331         exif_mem_ref (mem);
332
333         return loader;
334 }
335
336 void
337 exif_loader_ref (ExifLoader *loader)
338 {
339         if (loader) 
340                 loader->ref_count++;
341 }
342
343 static void
344 exif_loader_free (ExifLoader *loader)
345 {
346         ExifMem *mem;
347
348         if (!loader) 
349                 return;
350
351         mem = loader->mem;
352         exif_loader_reset (loader);
353         exif_mem_free (mem, loader);
354         exif_mem_unref (mem);
355 }
356         
357 void
358 exif_loader_unref (ExifLoader *loader)
359 {
360         if (!loader) 
361                 return;
362         if (!--loader->ref_count)
363                 exif_loader_free (loader);
364 }
365
366 void
367 exif_loader_reset (ExifLoader *loader)
368 {
369         if (!loader) 
370                 return;
371         exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
372         loader->size = 0;
373         loader->bytes_read = 0;
374         loader->state = 0;
375         loader->b_len = 0;
376         loader->data_format = EL_DATA_FORMAT_UNKNOWN;
377 }
378
379 ExifData *
380 exif_loader_get_data (ExifLoader *loader)
381 {
382         ExifData *ed;
383
384         if (!loader) 
385                 return NULL;
386
387         ed = exif_data_new_mem (loader->mem);
388         exif_data_log (ed, loader->log);
389         exif_data_load_data (ed, loader->buf, loader->bytes_read);
390
391         return ed;
392 }
393
394 void
395 exif_loader_log (ExifLoader *loader, ExifLog *log)
396 {
397         if (!loader) 
398                 return;
399         exif_log_unref (loader->log);
400         loader->log = log;
401         exif_log_ref (log);
402 }