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

Generated on Tue Dec 19 14:33:53 2006 for EXIF library (libexif) Internals by  doxygen 1.5.1