00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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) return NULL;
00084
00085 d = exif_mem_alloc (l->mem, i);
00086 if (d) return d;
00087
00088 EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
00089 return NULL;
00090 }
00091
00092 #undef MIN
00093 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
00094
00095 void
00096 exif_loader_write_file (ExifLoader *l, const char *path)
00097 {
00098 FILE *f;
00099 int size;
00100 unsigned char data[1024];
00101
00102 if (!l) return;
00103
00104 f = fopen (path, "rb");
00105 if (!f) {
00106 exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
00107 _("The file '%s' could not be opened."), path);
00108 return;
00109 }
00110 while (1) {
00111 size = fread (data, 1, sizeof (data), f);
00112 if (size <= 0) break;
00113 if (!exif_loader_write (l, data, size)) break;
00114 }
00115 fclose (f);
00116 }
00117
00118 static unsigned int
00119 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
00120 {
00121 if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) return 0;
00122
00123
00124 if (!eld->buf) eld->buf = exif_loader_alloc (eld, eld->size);
00125 if (!eld->buf) return 0;
00126
00127
00128 len = MIN (len, eld->size - eld->bytes_read);
00129 memcpy (eld->buf + eld->bytes_read, buf, len);
00130 eld->bytes_read += len;
00131
00132 return (eld->bytes_read >= eld->size) ? 0 : 1;
00133 }
00134
00135 unsigned char
00136 exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
00137 {
00138 unsigned int i;
00139
00140 if (!eld || (len && !buf)) return 0;
00141
00142 switch (eld->state) {
00143 case EL_EXIF_FOUND:
00144 return exif_loader_copy (eld, buf, len);
00145 case EL_SKIP_BYTES:
00146 if (eld->size > len) { eld->size -= len; return 1; }
00147 len -= eld->size;
00148 buf += eld->size;
00149 eld->size = 0;
00150 eld->b_len = 0;
00151 switch (eld->data_format) {
00152 case EL_DATA_FORMAT_FUJI_RAW:
00153 eld->state = EL_READ_SIZE_BYTE_24;
00154 break;
00155 default:
00156 eld->state = EL_READ;
00157 break;
00158 }
00159 break;
00160 default:
00161 break;
00162 }
00163
00164 exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
00165 "Scanning %i byte(s) of data...", len);
00166
00167
00168
00169
00170
00171 i = MIN (len, sizeof (eld->b) - eld->b_len);
00172 if (i) {
00173 memcpy (&eld->b[eld->b_len], buf, i);
00174 eld->b_len += i;
00175 if (eld->b_len < sizeof (eld->b)) return 1;
00176 buf += i;
00177 len -= i;
00178 }
00179
00180 switch (eld->data_format) {
00181 case EL_DATA_FORMAT_UNKNOWN:
00182
00183
00184 if (!memcmp (eld->b, "FUJIFILM", 8)) {
00185
00186
00187 eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
00188 eld->size = 84;
00189 eld->state = EL_SKIP_BYTES;
00190 eld->size = 84;
00191
00192 } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
00193
00194
00195 eld->data_format = EL_DATA_FORMAT_EXIF;
00196 eld->state = EL_READ_SIZE_BYTE_08;
00197 }
00198 default:
00199 break;
00200 }
00201
00202 for (i = 0; i < sizeof (eld->b); i++)
00203 switch (eld->state) {
00204 case EL_EXIF_FOUND:
00205 if (!exif_loader_copy (eld, eld->b + i,
00206 sizeof (eld->b) - i)) return 0;
00207 return exif_loader_copy (eld, buf, len);
00208 case EL_SKIP_BYTES:
00209 eld->size--;
00210 if (!eld->size) eld->state = EL_READ;
00211 break;
00212
00213 case EL_READ_SIZE_BYTE_24:
00214 eld->size |= eld->b[i] << 24;
00215 eld->state = EL_READ_SIZE_BYTE_16;
00216 break;
00217 case EL_READ_SIZE_BYTE_16:
00218 eld->size |= eld->b[i] << 16;
00219 eld->state = EL_READ_SIZE_BYTE_08;
00220 break;
00221 case EL_READ_SIZE_BYTE_08:
00222 eld->size |= eld->b[i] << 8;
00223 eld->state = EL_READ_SIZE_BYTE_00;
00224 break;
00225 case EL_READ_SIZE_BYTE_00:
00226 eld->size |= eld->b[i] << 0;
00227 switch (eld->data_format) {
00228 case EL_DATA_FORMAT_JPEG:
00229 eld->state = EL_SKIP_BYTES;
00230 eld->size -= 2;
00231 break;
00232 case EL_DATA_FORMAT_FUJI_RAW:
00233 eld->data_format = EL_DATA_FORMAT_EXIF;
00234 eld->state = EL_SKIP_BYTES;
00235 eld->size -= 86;
00236 break;
00237 case EL_DATA_FORMAT_EXIF:
00238 eld->state = EL_EXIF_FOUND;
00239 break;
00240 default:
00241 break;
00242 }
00243 break;
00244
00245 default:
00246 switch (eld->b[i]) {
00247 case JPEG_MARKER_APP1:
00248 eld->data_format = EL_DATA_FORMAT_EXIF;
00249 eld->size = 0;
00250 eld->state = EL_READ_SIZE_BYTE_08;
00251 break;
00252 case JPEG_MARKER_APP0:
00253 case JPEG_MARKER_APP13:
00254 case JPEG_MARKER_COM:
00255 eld->data_format = EL_DATA_FORMAT_JPEG;
00256 eld->size = 0;
00257 eld->state = EL_READ_SIZE_BYTE_08;
00258 break;
00259 case 0xff:
00260 case JPEG_MARKER_SOI:
00261 break;
00262 default:
00263 exif_log (eld->log,
00264 EXIF_LOG_CODE_CORRUPT_DATA,
00265 "ExifLoader", _("The data supplied "
00266 "does not seem to contain "
00267 "EXIF data."));
00268 exif_loader_reset (eld);
00269 return 0;
00270 }
00271 }
00272
00273
00274
00275
00276
00277 eld->b_len = 0;
00278 return exif_loader_write (eld, buf, len);
00279 }
00280
00281 ExifLoader *
00282 exif_loader_new (void)
00283 {
00284 ExifMem *mem = exif_mem_new_default ();
00285 ExifLoader *l = exif_loader_new_mem (mem);
00286
00287 exif_mem_unref (mem);
00288
00289 return l;
00290 }
00291
00292 ExifLoader *
00293 exif_loader_new_mem (ExifMem *mem)
00294 {
00295 ExifLoader *loader;
00296
00297 if (!mem) return NULL;
00298
00299 loader = exif_mem_alloc (mem, sizeof (ExifLoader));
00300 if (!loader) return NULL;
00301 loader->ref_count = 1;
00302
00303 loader->mem = mem;
00304 exif_mem_ref (mem);
00305
00306 return loader;
00307 }
00308
00309 void
00310 exif_loader_ref (ExifLoader *loader)
00311 {
00312 if (loader) loader->ref_count++;
00313 }
00314
00315 static void
00316 exif_loader_free (ExifLoader *loader)
00317 {
00318 ExifMem *mem;
00319
00320 if (!loader) return;
00321
00322 mem = loader->mem;
00323 exif_loader_reset (loader);
00324 exif_mem_free (mem, loader);
00325 exif_mem_unref (mem);
00326 }
00327
00328 void
00329 exif_loader_unref (ExifLoader *loader)
00330 {
00331 if (!loader) return;
00332 if (!--loader->ref_count)
00333 exif_loader_free (loader);
00334 }
00335
00336 void
00337 exif_loader_reset (ExifLoader *loader)
00338 {
00339 if (!loader) return;
00340 exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
00341 loader->size = 0;
00342 loader->bytes_read = 0;
00343 loader->state = 0;
00344 loader->b_len = 0;
00345 loader->data_format = EL_DATA_FORMAT_UNKNOWN;
00346 }
00347
00348 ExifData *
00349 exif_loader_get_data (ExifLoader *loader)
00350 {
00351 ExifData *ed;
00352
00353 if (!loader) return NULL;
00354
00355 ed = exif_data_new_mem (loader->mem);
00356 exif_data_log (ed, loader->log);
00357 exif_data_load_data (ed, loader->buf, loader->bytes_read);
00358
00359 return ed;
00360 }
00361
00362 void
00363 exif_loader_log (ExifLoader *loader, ExifLog *log)
00364 {
00365 if (!loader) return;
00366 exif_log_unref (loader->log);
00367 loader->log = log;
00368 exif_log_ref (log);
00369 }