exif-loader.c

Go to the documentation of this file.
00001 /* exif-loader.c
00002  *
00003  * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful, 
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details. 
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the
00017  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  * Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include <config.h>
00022 
00023 #include <libexif/exif-loader.h>
00024 #include <libexif/exif-utils.h>
00025 #include <libexif/i18n.h>
00026 
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <stdio.h>
00030 
00031 #undef JPEG_MARKER_SOI
00032 #define JPEG_MARKER_SOI  0xd8
00033 #undef JPEG_MARKER_APP0
00034 #define JPEG_MARKER_APP0 0xe0
00035 #undef JPEG_MARKER_APP1
00036 #define JPEG_MARKER_APP1 0xe1
00037 #undef JPEG_MARKER_APP2
00038 #define JPEG_MARKER_APP2 0xe2
00039 #undef JPEG_MARKER_APP13
00040 #define JPEG_MARKER_APP13 0xed
00041 #undef JPEG_MARKER_COM
00042 #define JPEG_MARKER_COM 0xfe
00043 
00044 typedef enum {
00045         EL_READ = 0,
00046         EL_READ_SIZE_BYTE_24,
00047         EL_READ_SIZE_BYTE_16,
00048         EL_READ_SIZE_BYTE_08,
00049         EL_READ_SIZE_BYTE_00,
00050         EL_SKIP_BYTES,
00051         EL_EXIF_FOUND,
00052 } ExifLoaderState;
00053 
00054 typedef enum {
00055         EL_DATA_FORMAT_UNKNOWN,
00056         EL_DATA_FORMAT_EXIF,
00057         EL_DATA_FORMAT_JPEG,
00058         EL_DATA_FORMAT_FUJI_RAW
00059 } ExifLoaderDataFormat;
00060 
00061 struct _ExifLoader {
00062         ExifLoaderState state;
00063         ExifLoaderDataFormat data_format;
00064 
00065         /* Small buffer used for detection of format */
00066         unsigned char b[12];
00067         unsigned char b_len;
00068 
00069         unsigned int size;
00070         unsigned char *buf;
00071         unsigned int bytes_read;
00072 
00073         unsigned int ref_count;
00074 
00075         ExifLog *log;
00076         ExifMem *mem;
00077 };
00078 
00079 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
00080 
00081 static void *
00082 exif_loader_alloc (ExifLoader *l, unsigned int i)
00083 {
00084         void *d;
00085 
00086         if (!l || !i) 
00087                 return NULL;
00088 
00089         d = exif_mem_alloc (l->mem, i);
00090         if (d) 
00091                 return d;
00092 
00093         EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
00094         return NULL;
00095 }
00096 
00097 #undef  MIN
00098 #define MIN(a, b)  (((a) < (b)) ? (a) : (b))
00099 
00100 void
00101 exif_loader_write_file (ExifLoader *l, const char *path)
00102 {
00103         FILE *f;
00104         int size;
00105         unsigned char data[1024];
00106 
00107         if (!l) 
00108                 return;
00109 
00110         f = fopen (path, "rb");
00111         if (!f) {
00112                 exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
00113                           _("The file '%s' could not be opened."), path);
00114                 return;
00115         }
00116         while (1) {
00117                 size = fread (data, 1, sizeof (data), f);
00118                 if (size <= 0) 
00119                         break;
00120                 if (!exif_loader_write (l, data, size)) 
00121                         break;
00122         }
00123         fclose (f);
00124 }
00125 
00126 static unsigned int
00127 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
00128 {
00129         if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) 
00130                 return 0;
00131 
00132         /* If needed, allocate the buffer. */
00133         if (!eld->buf) 
00134                 eld->buf = exif_loader_alloc (eld, eld->size);
00135         if (!eld->buf) 
00136                 return 0;
00137 
00138         /* Copy memory */
00139         len = MIN (len, eld->size - eld->bytes_read);
00140         memcpy (eld->buf + eld->bytes_read, buf, len);
00141         eld->bytes_read += len;
00142 
00143         return (eld->bytes_read >= eld->size) ? 0 : 1;
00144 }
00145 
00146 unsigned char
00147 exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
00148 {
00149         unsigned int i;
00150 
00151         if (!eld || (len && !buf)) 
00152                 return 0;
00153 
00154         switch (eld->state) {
00155         case EL_EXIF_FOUND:
00156                 return exif_loader_copy (eld, buf, len);
00157         case EL_SKIP_BYTES:
00158                 if (eld->size > len) { 
00159                         eld->size -= len; 
00160                         return 1; 
00161                 }
00162                 len -= eld->size;
00163                 buf += eld->size;
00164                 eld->size = 0;
00165                 eld->b_len = 0;
00166                 switch (eld->data_format) {
00167                 case EL_DATA_FORMAT_FUJI_RAW:
00168                         eld->state = EL_READ_SIZE_BYTE_24;
00169                         break;
00170                 default:
00171                         eld->state = EL_READ;
00172                         break;
00173                 }
00174                 break;
00175         default:
00176                 break;
00177         }
00178 
00179         if (!len)
00180                 return 1;
00181         exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
00182                   "Scanning %i byte(s) of data...", len);
00183 
00184         /*
00185          * First fill the small buffer. Only continue if the buffer
00186          * is filled. Note that EXIF data contains at least 12 bytes.
00187          */
00188         i = MIN (len, sizeof (eld->b) - eld->b_len);
00189         if (i) {
00190                 memcpy (&eld->b[eld->b_len], buf, i);
00191                 eld->b_len += i;
00192                 if (eld->b_len < sizeof (eld->b)) 
00193                         return 1;
00194                 buf += i;
00195                 len -= i;
00196         }
00197 
00198         switch (eld->data_format) {
00199         case EL_DATA_FORMAT_UNKNOWN:
00200 
00201                 /* Check the small buffer against known formats. */
00202                 if (!memcmp (eld->b, "FUJIFILM", 8)) {
00203 
00204                         /* Skip to byte 84. There is another offset there. */
00205                         eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
00206                         eld->size = 84;
00207                         eld->state = EL_SKIP_BYTES;
00208                         eld->size = 84;
00209 
00210                 } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
00211 
00212                         /* Read the size (2 bytes). */
00213                         eld->data_format = EL_DATA_FORMAT_EXIF;
00214                         eld->state = EL_READ_SIZE_BYTE_08;
00215                 }
00216         default:
00217                 break;
00218         }
00219 
00220         for (i = 0; i < sizeof (eld->b); i++)
00221                 switch (eld->state) {
00222                 case EL_EXIF_FOUND:
00223                         if (!exif_loader_copy (eld, eld->b + i,
00224                                         sizeof (eld->b) - i)) 
00225                                 return 0;
00226                         return exif_loader_copy (eld, buf, len);
00227                 case EL_SKIP_BYTES:
00228                         eld->size--;
00229                         if (!eld->size) 
00230                                 eld->state = EL_READ;
00231                         break;
00232 
00233                 case EL_READ_SIZE_BYTE_24:
00234                         eld->size |= eld->b[i] << 24;
00235                         eld->state = EL_READ_SIZE_BYTE_16;
00236                         break;
00237                 case EL_READ_SIZE_BYTE_16:
00238                         eld->size |= eld->b[i] << 16;
00239                         eld->state = EL_READ_SIZE_BYTE_08;
00240                         break;
00241                 case EL_READ_SIZE_BYTE_08:
00242                         eld->size |= eld->b[i] << 8;
00243                         eld->state = EL_READ_SIZE_BYTE_00;
00244                         break;
00245                 case EL_READ_SIZE_BYTE_00:
00246                         eld->size |= eld->b[i] << 0;
00247                         switch (eld->data_format) {
00248                         case EL_DATA_FORMAT_JPEG:
00249                                 eld->state = EL_SKIP_BYTES;
00250                                 eld->size -= 2;
00251                                 break;
00252                         case EL_DATA_FORMAT_FUJI_RAW:
00253                                 eld->data_format = EL_DATA_FORMAT_EXIF;
00254                                 eld->state = EL_SKIP_BYTES;
00255                                 eld->size -= 86;
00256                                 break;
00257                         case EL_DATA_FORMAT_EXIF:
00258                                 eld->state = EL_EXIF_FOUND;
00259                                 break;
00260                         default:
00261                                 break;
00262                         }
00263                         break;
00264 
00265                 default:
00266                         switch (eld->b[i]) {
00267                         case JPEG_MARKER_APP1:
00268                                 if (!memcmp (eld->b + i + 3, ExifHeader, MIN(sizeof (ExifHeader), MAX(0, sizeof (eld->b) - i - 3)))) {
00269                                         eld->data_format = EL_DATA_FORMAT_EXIF;
00270                                 } else {
00271                                         eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
00272                                 }
00273                                 eld->size = 0;
00274                                 eld->state = EL_READ_SIZE_BYTE_08;
00275                                 break;
00276                         case JPEG_MARKER_APP0:
00277                         case JPEG_MARKER_APP2:
00278                         case JPEG_MARKER_APP13:
00279                         case JPEG_MARKER_COM:
00280                                 eld->data_format = EL_DATA_FORMAT_JPEG;
00281                                 eld->size = 0;
00282                                 eld->state = EL_READ_SIZE_BYTE_08;
00283                                 break;
00284                         case 0xff:
00285                         case JPEG_MARKER_SOI:
00286                                 break;
00287                         default:
00288                                 exif_log (eld->log,
00289                                         EXIF_LOG_CODE_CORRUPT_DATA,
00290                                         "ExifLoader", _("The data supplied "
00291                                                 "does not seem to contain "
00292                                                 "EXIF data."));
00293                                 exif_loader_reset (eld);
00294                                 return 0;
00295                         }
00296                 }
00297 
00298         /*
00299          * If we reach this point, the buffer has not been big enough
00300          * to read all data we need. Fill it with new data.
00301          */
00302         eld->b_len = 0;
00303         return exif_loader_write (eld, buf, len);
00304 }
00305 
00306 ExifLoader *
00307 exif_loader_new (void)
00308 {
00309         ExifMem *mem = exif_mem_new_default ();
00310         ExifLoader *l = exif_loader_new_mem (mem);
00311 
00312         exif_mem_unref (mem);
00313 
00314         return l;
00315 }
00316 
00317 ExifLoader *
00318 exif_loader_new_mem (ExifMem *mem)
00319 {
00320         ExifLoader *loader;
00321 
00322         if (!mem) 
00323                 return NULL;
00324         
00325         loader = exif_mem_alloc (mem, sizeof (ExifLoader));
00326         if (!loader) 
00327                 return NULL;
00328         loader->ref_count = 1;
00329 
00330         loader->mem = mem;
00331         exif_mem_ref (mem);
00332 
00333         return loader;
00334 }
00335 
00336 void
00337 exif_loader_ref (ExifLoader *loader)
00338 {
00339         if (loader) 
00340                 loader->ref_count++;
00341 }
00342 
00343 static void
00344 exif_loader_free (ExifLoader *loader)
00345 {
00346         ExifMem *mem;
00347 
00348         if (!loader) 
00349                 return;
00350 
00351         mem = loader->mem;
00352         exif_loader_reset (loader);
00353         exif_mem_free (mem, loader);
00354         exif_mem_unref (mem);
00355 }
00356         
00357 void
00358 exif_loader_unref (ExifLoader *loader)
00359 {
00360         if (!loader) 
00361                 return;
00362         if (!--loader->ref_count)
00363                 exif_loader_free (loader);
00364 }
00365 
00366 void
00367 exif_loader_reset (ExifLoader *loader)
00368 {
00369         if (!loader) 
00370                 return;
00371         exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
00372         loader->size = 0;
00373         loader->bytes_read = 0;
00374         loader->state = 0;
00375         loader->b_len = 0;
00376         loader->data_format = EL_DATA_FORMAT_UNKNOWN;
00377 }
00378 
00379 ExifData *
00380 exif_loader_get_data (ExifLoader *loader)
00381 {
00382         ExifData *ed;
00383 
00384         if (!loader) 
00385                 return NULL;
00386 
00387         ed = exif_data_new_mem (loader->mem);
00388         exif_data_log (ed, loader->log);
00389         exif_data_load_data (ed, loader->buf, loader->bytes_read);
00390 
00391         return ed;
00392 }
00393 
00394 void
00395 exif_loader_log (ExifLoader *loader, ExifLog *log)
00396 {
00397         if (!loader) 
00398                 return;
00399         exif_log_unref (loader->log);
00400         loader->log = log;
00401         exif_log_ref (log);
00402 }

Generated on Wed Jan 9 15:07:35 2008 for EXIF library (libexif) Internals by  doxygen 1.5.0