1 /* exif-loader.c 2 * 3 * Copyright (c) 2002 Lutz Mueller <lutz (at) 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., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301 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 <sys/types.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <stdio.h> 31 32 #undef JPEG_MARKER_DHT 33 #define JPEG_MARKER_DHT 0xc4 34 #undef JPEG_MARKER_SOI 35 #define JPEG_MARKER_SOI 0xd8 36 #undef JPEG_MARKER_DQT 37 #define JPEG_MARKER_DQT 0xdb 38 #undef JPEG_MARKER_APP0 39 #define JPEG_MARKER_APP0 0xe0 40 #undef JPEG_MARKER_APP1 41 #define JPEG_MARKER_APP1 0xe1 42 #undef JPEG_MARKER_APP2 43 #define JPEG_MARKER_APP2 0xe2 44 #undef JPEG_MARKER_APP13 45 #define JPEG_MARKER_APP13 0xed 46 #undef JPEG_MARKER_COM 47 #define JPEG_MARKER_COM 0xfe 48 49 typedef enum { 50 EL_READ = 0, 51 EL_READ_SIZE_BYTE_24, 52 EL_READ_SIZE_BYTE_16, 53 EL_READ_SIZE_BYTE_08, 54 EL_READ_SIZE_BYTE_00, 55 EL_SKIP_BYTES, 56 EL_EXIF_FOUND, 57 } ExifLoaderState; 58 59 typedef enum { 60 EL_DATA_FORMAT_UNKNOWN, 61 EL_DATA_FORMAT_EXIF, 62 EL_DATA_FORMAT_JPEG, 63 EL_DATA_FORMAT_FUJI_RAW 64 } ExifLoaderDataFormat; 65 66 /*! \internal */ 67 struct _ExifLoader { 68 ExifLoaderState state; 69 ExifLoaderDataFormat data_format; 70 71 /*! Small buffer used for detection of format */ 72 unsigned char b[12]; 73 74 /*! Number of bytes in the small buffer \c b */ 75 unsigned char b_len; 76 77 unsigned int size; 78 unsigned char *buf; 79 unsigned int bytes_read; 80 81 unsigned int ref_count; 82 83 ExifLog *log; 84 ExifMem *mem; 85 }; 86 87 /*! Magic number for EXIF header */ 88 static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; 89 90 static void * 91 exif_loader_alloc (ExifLoader *l, unsigned int i) 92 { 93 void *d; 94 95 if (!l || !i) 96 return NULL; 97 98 d = exif_mem_alloc (l->mem, i); 99 if (d) 100 return d; 101 102 EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i); 103 return NULL; 104 } 105 106 void 107 exif_loader_write_file (ExifLoader *l, const char *path) 108 { 109 FILE *f; 110 int size; 111 unsigned char data[1024]; 112 113 if (!l) 114 return; 115 116 f = fopen (path, "rb"); 117 if (!f) { 118 exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader", 119 _("The file '%s' could not be opened."), path); 120 return; 121 } 122 while (1) { 123 size = fread (data, 1, sizeof (data), f); 124 if (size <= 0) 125 break; 126 if (!exif_loader_write (l, data, size)) 127 break; 128 } 129 fclose (f); 130 } 131 132 static unsigned int 133 exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len) 134 { 135 if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) 136 return 0; 137 138 /* If needed, allocate the buffer. */ 139 if (!eld->buf) 140 eld->buf = exif_loader_alloc (eld, eld->size); 141 if (!eld->buf) 142 return 0; 143 144 /* Copy memory */ 145 len = MIN (len, eld->size - eld->bytes_read); 146 memcpy (eld->buf + eld->bytes_read, buf, len); 147 eld->bytes_read += len; 148 149 return (eld->bytes_read >= eld->size) ? 0 : 1; 150 } 151 152 unsigned char 153 exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len) 154 { 155 unsigned int i; 156 157 if (!eld || (len && !buf)) 158 return 0; 159 160 switch (eld->state) { 161 case EL_EXIF_FOUND: 162 return exif_loader_copy (eld, buf, len); 163 case EL_SKIP_BYTES: 164 if (eld->size > len) { 165 eld->size -= len; 166 return 1; 167 } 168 len -= eld->size; 169 buf += eld->size; 170 eld->size = 0; 171 eld->b_len = 0; 172 switch (eld->data_format) { 173 case EL_DATA_FORMAT_FUJI_RAW: 174 eld->state = EL_READ_SIZE_BYTE_24; 175 break; 176 default: 177 eld->state = EL_READ; 178 break; 179 } 180 break; 181 182 case EL_READ: 183 default: 184 break; 185 } 186 187 if (!len) 188 return 1; 189 exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader", 190 "Scanning %i byte(s) of data...", len); 191 192 /* 193 * First fill the small buffer. Only continue if the buffer 194 * is filled. Note that EXIF data contains at least 12 bytes. 195 */ 196 i = MIN (len, sizeof (eld->b) - eld->b_len); 197 if (i) { 198 memcpy (&eld->b[eld->b_len], buf, i); 199 eld->b_len += i; 200 if (eld->b_len < sizeof (eld->b)) 201 return 1; 202 buf += i; 203 len -= i; 204 } 205 206 switch (eld->data_format) { 207 case EL_DATA_FORMAT_UNKNOWN: 208 209 /* Check the small buffer against known formats. */ 210 if (!memcmp (eld->b, "FUJIFILM", 8)) { 211 212 /* Skip to byte 84. There is another offset there. */ 213 eld->data_format = EL_DATA_FORMAT_FUJI_RAW; 214 eld->size = 84; 215 eld->state = EL_SKIP_BYTES; 216 eld->size = 84; 217 218 } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) { 219 220 /* Read the size (2 bytes). */ 221 eld->data_format = EL_DATA_FORMAT_EXIF; 222 eld->state = EL_READ_SIZE_BYTE_08; 223 } 224 default: 225 break; 226 } 227 228 for (i = 0; i < sizeof (eld->b); i++) 229 switch (eld->state) { 230 case EL_EXIF_FOUND: 231 if (!exif_loader_copy (eld, eld->b + i, 232 sizeof (eld->b) - i)) 233 return 0; 234 return exif_loader_copy (eld, buf, len); 235 case EL_SKIP_BYTES: 236 eld->size--; 237 if (!eld->size) 238 eld->state = EL_READ; 239 break; 240 241 case EL_READ_SIZE_BYTE_24: 242 eld->size |= eld->b[i] << 24; 243 eld->state = EL_READ_SIZE_BYTE_16; 244 break; 245 case EL_READ_SIZE_BYTE_16: 246 eld->size |= eld->b[i] << 16; 247 eld->state = EL_READ_SIZE_BYTE_08; 248 break; 249 case EL_READ_SIZE_BYTE_08: 250 eld->size |= eld->b[i] << 8; 251 eld->state = EL_READ_SIZE_BYTE_00; 252 break; 253 case EL_READ_SIZE_BYTE_00: 254 eld->size |= eld->b[i] << 0; 255 switch (eld->data_format) { 256 case EL_DATA_FORMAT_JPEG: 257 eld->state = EL_SKIP_BYTES; 258 eld->size -= 2; 259 break; 260 case EL_DATA_FORMAT_FUJI_RAW: 261 eld->data_format = EL_DATA_FORMAT_EXIF; 262 eld->state = EL_SKIP_BYTES; 263 eld->size -= 86; 264 break; 265 case EL_DATA_FORMAT_EXIF: 266 eld->state = EL_EXIF_FOUND; 267 break; 268 default: 269 break; 270 } 271 break; 272 273 default: 274 switch (eld->b[i]) { 275 case JPEG_MARKER_APP1: 276 if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) { 277 eld->data_format = EL_DATA_FORMAT_EXIF; 278 } else { 279 eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/ 280 } 281 eld->size = 0; 282 eld->state = EL_READ_SIZE_BYTE_08; 283 break; 284 case JPEG_MARKER_DHT: 285 case JPEG_MARKER_DQT: 286 case JPEG_MARKER_APP0: 287 case JPEG_MARKER_APP2: 288 case JPEG_MARKER_APP13: 289 case JPEG_MARKER_COM: 290 eld->data_format = EL_DATA_FORMAT_JPEG; 291 eld->size = 0; 292 eld->state = EL_READ_SIZE_BYTE_08; 293 break; 294 case 0xff: 295 case JPEG_MARKER_SOI: 296 break; 297 default: 298 exif_log (eld->log, 299 EXIF_LOG_CODE_CORRUPT_DATA, 300 "ExifLoader", _("The data supplied " 301 "does not seem to contain " 302 "EXIF data.")); 303 exif_loader_reset (eld); 304 return 0; 305 } 306 } 307 308 /* 309 * If we reach this point, the buffer has not been big enough 310 * to read all data we need. Fill it with new data. 311 */ 312 eld->b_len = 0; 313 return exif_loader_write (eld, buf, len); 314 } 315 316 ExifLoader * 317 exif_loader_new (void) 318 { 319 ExifMem *mem = exif_mem_new_default (); 320 ExifLoader *l = exif_loader_new_mem (mem); 321 322 exif_mem_unref (mem); 323 324 return l; 325 } 326 327 ExifLoader * 328 exif_loader_new_mem (ExifMem *mem) 329 { 330 ExifLoader *loader; 331 332 if (!mem) 333 return NULL; 334 335 loader = exif_mem_alloc (mem, sizeof (ExifLoader)); 336 if (!loader) 337 return NULL; 338 loader->ref_count = 1; 339 340 loader->mem = mem; 341 exif_mem_ref (mem); 342 343 return loader; 344 } 345 346 void 347 exif_loader_ref (ExifLoader *loader) 348 { 349 if (loader) 350 loader->ref_count++; 351 } 352 353 static void 354 exif_loader_free (ExifLoader *loader) 355 { 356 ExifMem *mem; 357 358 if (!loader) 359 return; 360 361 mem = loader->mem; 362 exif_loader_reset (loader); 363 exif_log_unref (loader->log); 364 exif_mem_free (mem, loader); 365 exif_mem_unref (mem); 366 } 367 368 void 369 exif_loader_unref (ExifLoader *loader) 370 { 371 if (!loader) 372 return; 373 if (!--loader->ref_count) 374 exif_loader_free (loader); 375 } 376 377 void 378 exif_loader_reset (ExifLoader *loader) 379 { 380 if (!loader) 381 return; 382 exif_mem_free (loader->mem, loader->buf); loader->buf = NULL; 383 loader->size = 0; 384 loader->bytes_read = 0; 385 loader->state = 0; 386 loader->b_len = 0; 387 loader->data_format = EL_DATA_FORMAT_UNKNOWN; 388 } 389 390 ExifData * 391 exif_loader_get_data (ExifLoader *loader) 392 { 393 ExifData *ed; 394 395 if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) || 396 !loader->bytes_read) 397 return NULL; 398 399 ed = exif_data_new_mem (loader->mem); 400 exif_data_log (ed, loader->log); 401 exif_data_load_data (ed, loader->buf, loader->bytes_read); 402 403 return ed; 404 } 405 406 void 407 exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf, 408 unsigned int *buf_size) 409 { 410 const unsigned char* b = NULL; 411 unsigned int s = 0; 412 413 if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN)) { 414 exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader", 415 "Loader format unknown"); 416 } else { 417 b = loader->buf; 418 s = loader->bytes_read; 419 } 420 if (buf) 421 *buf = b; 422 if (buf_size) 423 *buf_size = s; 424 } 425 426 void 427 exif_loader_log (ExifLoader *loader, ExifLog *log) 428 { 429 if (!loader) 430 return; 431 exif_log_unref (loader->log); 432 loader->log = log; 433 exif_log_ref (log); 434 } 435