replaced gchar* path with FileData *fd
[geeqie.git] / src / format_raw.c
1 /*
2  *  GQView
3  *  (C) 2006 John Ellis
4  *
5  *  Authors:
6  *    Original version 2005 Lars Ellenberg, base on dcraw by David coffin.
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13 #ifdef HAVE_CONFIG_H
14 #  include "config.h"
15 #endif
16
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24
25 #include <glib.h>
26
27 #include "intl.h"
28
29 #include "gqview.h"
30 #include "format_raw.h"
31
32 #include "format_canon.h"
33 #include "format_fuji.h"
34 #include "format_nikon.h"
35 #include "format_olympus.h"
36
37
38 /* so that debugging is honored */
39 extern gint debug;
40
41
42 typedef struct _FormatRawEntry FormatRawEntry;
43 struct _FormatRawEntry {
44         const gchar *extension;
45         FormatRawMatchType magic_type;
46         const guint magic_offset;
47         const void *magic_pattern;
48         const guint magic_length;
49         const FormatRawExifType exif_type;
50         FormatRawExifParseFunc exif_func;
51         const gchar *description;
52         FormatRawParseFunc func_parse;
53 };
54
55 static FormatRawEntry format_raw_list[] = {
56 #if DEBUG_RAW_TIFF
57         FORMAT_RAW_DEBUG_TIFF,
58 #endif
59         FORMAT_RAW_CANON,
60         FORMAT_RAW_FUJI,
61         FORMAT_RAW_NIKON,
62         FORMAT_RAW_OLYMPUS,
63         FORMAT_RAW_PENTAX,
64         { NULL, 0, 0, NULL, 0, 0, NULL, NULL, NULL }
65 };
66
67
68 typedef struct _FormatExifEntry FormatExifEntry;
69 struct _FormatExifEntry {
70         FormatExifMatchType header_type;
71         const void *header_pattern;
72         const guint header_length;
73         const gchar *description;
74         FormatExifParseFunc func_parse;
75 };
76
77 static FormatExifEntry format_exif_list[] = {
78         FORMAT_EXIF_CANON,
79         FORMAT_EXIF_FUJI,
80         FORMAT_EXIF_NIKON,
81         FORMAT_EXIF_OLYMPUS,
82         { 0, NULL, 0, NULL }
83 };
84
85
86 static guint tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
87                         guint tag, ExifFormatType type,
88                         guint *result_offset, guint *result_count)
89 {
90         guint count;
91         guint i;
92
93         if (len < offset + 2) return 0;
94         if (type < 0 || type > EXIF_FORMAT_COUNT) return 0;
95
96         count = exif_byte_get_int16(data + offset, bo);
97         offset += 2;
98         if (len < offset + count * 12 + 4) return 0;
99
100         for (i = 0; i < count; i++)
101                 {
102                 guint segment;
103
104                 segment = offset + i * 12;
105                 if (exif_byte_get_int16(data + segment, bo) == tag &&
106                     exif_byte_get_int16(data + segment + 2, bo) == type)
107                         {
108                         guint chunk_count;
109                         guint chunk_offset;
110                         guint chunk_length;
111
112                         chunk_count = exif_byte_get_int32(data + segment + 4, bo);
113                         chunk_length = ExifFormatList[type].size * chunk_count;
114
115                         if (chunk_length > 4)
116                                 {
117                                 chunk_offset = exif_byte_get_int32(data + segment + 8, bo);
118                                 }
119                         else
120                                 {
121                                 chunk_offset = segment + 8;
122                                 }
123
124                         if (chunk_offset + chunk_length <= len)
125                                 {
126                                 *result_offset = chunk_offset;
127                                 *result_count = chunk_count;
128                                 }
129
130                         return 0;
131                         }
132                 }
133
134         return exif_byte_get_int32(data + offset + count * 12, bo);
135 }
136
137 static gint format_tiff_find_tag_data(unsigned char *data, const guint len,
138                                       guint tag, ExifFormatType type,
139                                       guint *result_offset, guint *result_count)
140 {
141         ExifByteOrder bo;
142         guint offset;
143
144         if (len < 8) return FALSE;
145
146         if (memcmp(data, "II", 2) == 0)
147                 {
148                 bo = EXIF_BYTE_ORDER_INTEL;
149                 }
150         else if (memcmp(data, "MM", 2) == 0)
151                 {
152                 bo = EXIF_BYTE_ORDER_MOTOROLA;
153                 }
154         else
155                 {
156                 return FALSE;
157                 }
158
159         if (exif_byte_get_int16(data + 2, bo) != 0x002A)
160                 {
161                 return FALSE;
162                 }
163
164         offset = exif_byte_get_int32(data + 4, bo);
165
166         while (offset != 0)
167                 {
168                 guint ro = 0;
169                 guint rc = 0;
170
171                 offset = tiff_table(data, len, offset, bo, tag, type, &ro, &rc);
172                 if (ro != 0)
173                         {
174                         *result_offset = ro;
175                         *result_count = rc;
176                         return TRUE;
177                         }
178                 }
179
180         return FALSE;
181 }
182
183 static FormatRawEntry *format_raw_find(unsigned char *data, const guint len)
184 {
185         gint n;
186         gint tiff;
187         guint make_count = 0;
188         guint make_offset = 0;
189
190         tiff = (len > 8 &&
191                 (memcmp(data, "II\x2a\x00", 4) == 0 ||
192                  memcmp(data, "MM\x00\x2a", 4) == 0));
193
194         n = 0;
195         while (format_raw_list[n].magic_pattern)
196                 {
197                 FormatRawEntry *entry = &format_raw_list[n];
198
199                 switch (entry->magic_type)
200                         {
201                         case FORMAT_RAW_MATCH_MAGIC:
202                                 if (entry->magic_length + entry->magic_offset <= len &&
203                                     memcmp(data + entry->magic_offset,
204                                            entry->magic_pattern, entry->magic_length) == 0)
205                                         {
206                                         return entry;
207                                         }
208                                 break;
209                         case FORMAT_RAW_MATCH_TIFF_MAKE:
210                                 if (tiff &&
211                                     make_offset == 0 &&
212                                     !format_tiff_find_tag_data(data, len, 0x10f, EXIF_FORMAT_STRING,
213                                                                &make_offset, &make_count))
214                                         {
215                                         tiff = FALSE;
216                                         }
217                                 if (make_offset != 0 &&
218                                     make_count >= entry->magic_offset + entry->magic_length &&
219                                     memcmp(entry->magic_pattern,
220                                            data + make_offset + entry->magic_offset, entry->magic_length) == 0)
221                                         {
222                                         return entry;
223                                         }
224                                 break;
225                         default:
226                                 break;
227                         }
228                 n++;
229                 }
230
231         return NULL;
232 }
233
234 static gint format_raw_parse(FormatRawEntry *entry,
235                              unsigned char *data, const guint len,
236                              guint *image_offset, guint *exif_offset)
237 {
238         guint io = 0;
239         guint eo = 0;
240         gint found;
241
242         if (!entry || !entry->func_parse) return FALSE;
243
244         if (debug) printf("RAW using file parser for %s\n", entry->description);
245
246         found = entry->func_parse(data, len, &io, &eo);
247
248         if (!found ||
249             io >= len - 4 ||
250             eo >= len)
251                 {
252                 return FALSE;
253                 }
254
255         if (image_offset) *image_offset = io;
256         if (exif_offset) *exif_offset = eo;
257
258         return TRUE;
259 }
260
261 gint format_raw_img_exif_offsets(unsigned char *data, const guint len,
262                                  guint *image_offset, guint *exif_offset)
263 {
264         FormatRawEntry *entry;
265
266         if (!data || len < 1) return FALSE;
267
268         entry = format_raw_find(data, len);
269
270         if (!entry || !entry->func_parse) return FALSE;
271
272         return format_raw_parse(entry, data, len, image_offset, exif_offset);
273 }
274
275
276 FormatRawExifType format_raw_exif_offset(unsigned char *data, const guint len, guint *exif_offset,
277                                          FormatRawExifParseFunc *exif_parse_func)
278 {
279         FormatRawEntry *entry;
280
281         if (!data || len < 1) return FALSE;
282
283         entry = format_raw_find(data, len);
284
285         if (!entry || !entry->func_parse) return FALSE;
286
287         if (!format_raw_parse(entry, data, len, NULL, exif_offset)) return FORMAT_RAW_EXIF_NONE;
288
289         if (entry->exif_type == FORMAT_RAW_EXIF_PROPRIETARY && exif_parse_func)
290                 {
291                 *exif_parse_func = entry->exif_func;
292                 }
293
294         return entry->exif_type;
295 }
296
297
298 gint format_raw_img_exif_offsets_fd(int fd, const gchar *path,
299                                     unsigned char *header_data, const guint header_len,
300                                     guint *image_offset, guint *exif_offset)
301 {
302         FormatRawEntry *entry;
303         void *map_data = NULL;
304         size_t map_len = 0;
305         struct stat st;
306         gint success;
307
308         if (!header_data || fd < 0) return FALSE;
309
310         /* given image pathname, first do simple (and fast) file extension test */
311         if (path)
312                 {
313                 const gchar *ext;
314                 gint match = FALSE;
315                 gint i;
316
317                 ext = strrchr(path, '.');
318                 if (!ext) return FALSE;
319                 ext++;
320
321                 i = 0;
322                 while (!match && format_raw_list[i].magic_pattern)
323                         {
324                         if (format_raw_list[i].extension &&
325                             strcasecmp(format_raw_list[i].extension, ext) == 0)
326                                 {
327                                 match = TRUE;
328                                 }
329                         i++;
330                         }
331
332                 if (!match) return FALSE;
333
334                 if (debug) printf("RAW file parser extension match\n");
335                 }
336
337         /* FIXME:
338          * when the target is a tiff file it should be mmaped prior to format_raw_find as
339          * the make field data may not always be within header_data + header_len
340          */ 
341         entry = format_raw_find(header_data, header_len);
342
343         if (!entry || !entry->func_parse) return FALSE;
344
345         if (fstat(fd, &st) == -1)
346                 {
347                 printf("Failed to stat file %d\n", fd);
348                 return FALSE;
349                 }
350         map_len = st.st_size;
351         map_data = mmap(0, map_len, PROT_READ, MAP_PRIVATE, fd, 0);
352         if (map_data == MAP_FAILED)
353                 {
354                 printf("Failed to mmap file %d\n", fd);
355                 return FALSE;
356                 }
357
358         success = format_raw_parse(entry, map_data, map_len, image_offset, exif_offset);
359
360         if (munmap(map_data, map_len) == -1)
361                 {
362                 printf("Failed to unmap file %d\n", fd);
363                 }
364
365         if (success && image_offset)
366                 {
367                 if (lseek(fd, *image_offset, SEEK_SET) != *image_offset)
368                         {
369                         printf("Failed to seek to embedded image\n");
370
371                         *image_offset = 0;
372                         if (*exif_offset) *exif_offset = 0;
373                         success = FALSE;
374                         }
375                 }
376
377         return success;
378 }
379
380
381 static FormatExifEntry *format_exif_makernote_find(ExifData *exif, unsigned char *tiff,
382                                                    guint offset, guint size)
383 {
384         ExifItem *make;
385         gint n;
386
387         make = exif_get_item(exif, "Make");
388
389         n = 0;
390         while (format_exif_list[n].header_pattern)
391                 {
392                 switch (format_exif_list[n].header_type)
393                         {
394                         case FORMAT_EXIF_MATCH_MAKERNOTE:
395                                 if (format_exif_list[n].header_length + offset < size &&
396                                     memcmp(tiff + offset, format_exif_list[n].header_pattern,
397                                                           format_exif_list[n].header_length) == 0)
398                                         {
399                                         return &format_exif_list[n];
400                                         }
401                                 break;
402                         case FORMAT_EXIF_MATCH_MAKE:
403                                 if (make &&
404                                     make->data_len >= format_exif_list[n].header_length &&
405                                     memcmp(make->data, format_exif_list[n].header_pattern,
406                                                        format_exif_list[n].header_length) == 0)
407                                         {
408                                         return &format_exif_list[n];
409                                         }
410                                 break;
411                         }
412                 n++;
413                 }
414
415         return FALSE;
416 }
417
418 gint format_exif_makernote_parse(ExifData *exif, unsigned char *tiff, guint offset,
419                                  guint size, ExifByteOrder bo)
420 {
421         FormatExifEntry *entry;
422
423         entry = format_exif_makernote_find(exif, tiff, offset, size);
424
425         if (!entry || !entry->func_parse) return FALSE;
426
427         if (debug) printf("EXIF using makernote parser for %s\n", entry->description);
428
429         return entry->func_parse(exif, tiff, offset, size, bo);
430 }
431
432 /*
433  *-----------------------------------------------------------------------------
434  * Basic TIFF debugger, prints all IFD entries within tiff file
435  *-----------------------------------------------------------------------------
436  */
437 #if DEBUG_RAW_TIFF
438
439 static guint format_debug_tiff_table(unsigned char *data, const guint len, guint offset,
440                                      ExifByteOrder bo, gint level);
441
442 static void format_debug_tiff_entry(unsigned char *data, const guint len, guint offset,
443                                     ExifByteOrder bo, gint level)
444 {
445         guint tag;
446         guint type;
447         guint count;
448         guint segment;
449         guint seg_len;
450
451         tag = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_TAG, bo);
452         type = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_FORMAT, bo);
453         count = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_COUNT, bo);
454
455         seg_len = ExifFormatList[type].size * count;
456         if (seg_len > 4)
457                 {
458                 segment = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo);
459                 if (segment + seg_len > len) return;
460                 }
461         else
462                 {
463                 segment = offset + EXIF_TIFD_OFFSET_DATA;
464                 }
465
466         printf("%*stag:0x%04X (%05d), type:%2d %9s, len:%6d [%02X %02X %02X %02X] @ offset:%d\n",
467                 level, "", tag, tag, type,
468                 (type < EXIF_FORMAT_COUNT) ? ExifFormatList[type].short_name : "???", count,
469                 data[segment], data[segment + 1], data[segment + 2], data[segment + 3], segment);
470
471         if (tag == 0x8769 || tag == 0x14a)
472                 {
473                 gint i;
474
475                 printf("%*s~~~ found %s table\n", level, "", (tag == 0x14a) ? "subIFD" : "EXIF" );
476
477                 for (i = 0; i < count; i++)
478                         {
479                         guint subset;
480
481                         subset = exif_byte_get_int32(data + segment + i * 4, bo);
482                         format_debug_tiff_table(data, len, subset, bo, level + 1);
483                         }
484                 }
485         else if (tag == 0x8773 && type == EXIF_FORMAT_UNDEFINED)
486                 {
487                 printf("%*s~~~ found ICC color profile at offset %d, length %d\n", level, "", segment, seg_len);
488                 }
489         else if (tag == 0x201 && (type == EXIF_FORMAT_LONG_UNSIGNED || type == EXIF_FORMAT_LONG))
490                 {
491                 guint subset = exif_byte_get_int32(data + segment, bo);
492                 printf("%*s~~~ found jpeg data at offset %d\n", level, "", subset);
493                 }
494         else if (tag == 0x202 && (type == EXIF_FORMAT_LONG_UNSIGNED || type == EXIF_FORMAT_LONG))
495                 {
496                 guint subset = exif_byte_get_int32(data + segment, bo);
497                 printf("%*s~~~ found jpeg data length of %d\n", level, "", subset);
498                 }
499 }
500
501 static guint format_debug_tiff_table(unsigned char *data, const guint len, guint offset,
502                                      ExifByteOrder bo, gint level)
503 {
504         guint count;
505         guint i;
506
507         if (level > EXIF_TIFF_MAX_LEVELS) return 0;
508
509         if (len < offset + 2) return FALSE;
510
511         count = exif_byte_get_int16(data + offset, bo);
512         offset += 2;
513         if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0;
514
515         printf("%*s== tiff table #%d has %d entries ==\n", level, "", level, count);
516
517         for (i = 0; i < count; i++)
518                 {
519                 format_debug_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo, level);
520                 }
521
522         printf("%*s----------- end of #%d ------------\n", level, "", level);
523
524         return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo);
525 }
526
527 gint format_debug_tiff_raw(unsigned char *data, const guint len,
528                            guint *image_offset, guint *exif_offset)
529 {
530         ExifByteOrder bo;
531         gint level;
532         guint offset;
533
534         if (len < 8) return FALSE;
535
536         /* for debugging, we are more relaxed as to magic header */
537         if (memcmp(data, "II", 2) == 0)
538                 {
539                 bo = EXIF_BYTE_ORDER_INTEL;
540                 }
541         else if (memcmp(data, "MM", 2) == 0)
542                 {
543                 bo = EXIF_BYTE_ORDER_MOTOROLA;
544                 }
545         else
546                 {
547                 return FALSE;
548                 }
549
550         printf("*** debug parsing tiff\n");
551
552         offset = exif_byte_get_int32(data + 4, bo);
553         level = 0;
554         while (offset && level < EXIF_TIFF_MAX_LEVELS)
555                 {
556                 offset = format_debug_tiff_table(data, len, offset, bo, 0);
557                 level++;
558                 }
559
560         printf("*** end\n");
561
562         /* we are debugging, not trying to return any data */
563         return FALSE;
564 }
565 #endif
566
567