exif-loader.c

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

SourceForge.net Logo Generated by doxygen