Tue Jun 7 03:47:03 2005 John Ellis <johne@verizon.net>
[geeqie.git] / src / format_nikon.c
1 /*
2  *  GQView
3  *  (C) 2005 John Ellis
4  *
5  *  Authors:
6  *    Raw NEF jpeg extraction based on nefextract.c by Joseph Heled,
7  *        in addition nefextract.c is based on dcraw by Dave Coffin.
8  *
9  * This software is released under the GNU General Public License (GNU GPL).
10  * Please read the included file COPYING for more information.
11  * This software comes with no warranty of any kind, use at your own risk!
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #  include "config.h"
16 #endif
17
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <glib.h>
24
25 #include "intl.h"
26
27 #include "format_nikon.h"
28
29 #include "exif.h"
30
31
32 /*
33  *-----------------------------------------------------------------------------
34  * Raw NEF embedded jpeg extraction for Nikon
35  *-----------------------------------------------------------------------------
36  */
37
38 static guint tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder byte_order,
39                         guint *image_offset, guint *jpeg_len);
40
41
42 static void tiff_entry(unsigned char *data, const guint len, guint offset, ExifByteOrder byte_order,
43                        guint *image_offset, guint *image_length, guint *jpeg_start, guint *jpeg_len)
44 {
45         static gint size[] = { 1,1,1,2,4,8,1,1,2,4,8,4,8 };
46         guint tag;
47         guint type;
48         guint count;
49         guint segment;
50
51         tag = exif_byte_get_int16(data + offset, byte_order);
52         type = exif_byte_get_int16(data + offset + 2, byte_order);
53         count = exif_byte_get_int32(data + offset + 4, byte_order);
54
55         if (type > 12) return;
56         if (count * size[type] > 4)
57                 {
58                 segment = exif_byte_get_int32(data + offset + 8, byte_order);
59                 if (len < segment + count * size[type]) return;
60                 }
61         else
62                 {
63                 segment = offset + 8;
64                 }
65
66         if (tag == 0x14a &&
67             type == EXIF_FORMAT_LONG_UNSIGNED)
68                 {
69                 /* sub IFD table */
70                 gint i;
71
72                 for (i = 0; i < count; i++)
73                         {
74                         guint subset;
75
76                         subset = exif_byte_get_int32(data + segment + i * 4, byte_order);
77                         tiff_table(data, len, subset, byte_order, image_offset, image_length);
78                         }
79
80                 }
81         else if (tag == 0x201)
82                 {
83                 /* jpeg data start offset */
84                 *jpeg_start = exif_byte_get_int32(data + segment, byte_order);
85                 }
86         else if (tag == 0x202)
87                 {
88                 /* jpeg data length */
89                 *jpeg_len = exif_byte_get_int32(data + segment, byte_order);
90                 }
91 }
92
93 static guint tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder byte_order,
94                         guint *image_offset, guint *image_length)
95 {
96         guint count;
97         guint i;
98         guint jpeg_start = 0;
99         guint jpeg_len = 0;
100
101         if (len < offset + 2) return FALSE;
102
103         count = exif_byte_get_int16((unsigned char *)data + offset, byte_order);
104
105         if (len < offset + count * 12 + 4) return 0;
106         offset += 2;
107
108         for (i = 0; i < count; i++)
109                 {
110                 tiff_entry(data, len, offset + i * 12, byte_order,
111                            image_offset, image_length, &jpeg_start, &jpeg_len);
112                 }
113
114         if (jpeg_start > 0 &&
115             jpeg_len > *image_length)
116                 {
117                 *image_offset = jpeg_start;
118                 *image_length = jpeg_len;
119                 }
120
121         return exif_byte_get_int32((unsigned char *)data + offset + count * 12, byte_order);
122 }
123
124 /*
125  * Walk the first TIFF IFD table and check for existence of a "make" tag (0x10f) that
126  * identifies NIKON CORPORATION, so that we can abort quickly if it is not a raw NEF.
127  */
128 static gint tiff_nikon_verify(unsigned char *data, const guint len, guint offset, ExifByteOrder byte_order)
129 {
130         guint nb_entries;
131         guint i;
132
133         if (len < offset + 2) return FALSE;
134
135         nb_entries = exif_byte_get_int16(data + offset, byte_order);
136         offset += 2;
137         if (len < offset + nb_entries * 12 + 4) return FALSE;
138
139         for (i = 0; i < nb_entries; i++)
140                 {
141                 guint segment;
142
143                 segment = offset + i * 12;
144                 if (exif_byte_get_int16(data + segment, byte_order) == 0x10f &&
145                     exif_byte_get_int16(data + segment + 2, byte_order) == EXIF_FORMAT_STRING)
146                         {
147                         guint count;
148                         guint make_text;
149
150                         count = exif_byte_get_int32(data + segment + 4, byte_order);
151                         make_text = exif_byte_get_int32(data + segment + 8, byte_order);
152
153                         if (count >= 17 &&
154                             memcmp(data + make_text, "NIKON CORPORATION", 17) == 0)
155                                 {
156                                 return TRUE;
157                                 }
158
159                         return FALSE;
160                         }
161                 }
162
163         return FALSE;
164 }
165
166 gint format_nikon_raw(const void *data, const guint len,
167                       guint *image_offset, guint *exif_offset)
168 {
169         guint i_off = 0;
170         guint i_len = 0;
171         ExifByteOrder byte_order;
172         guint offset;
173
174         if (len < 8) return FALSE;
175
176         if (memcmp(data, "II", 2) == 0)
177                 {
178                 byte_order = EXIF_BYTE_ORDER_INTEL;
179                 }
180         else if (memcmp(data, "MM", 2) == 0)
181                 {
182                 byte_order = EXIF_BYTE_ORDER_MOTOROLA;
183                 }
184         else
185                 {
186                 return FALSE;
187                 }
188
189         if (exif_byte_get_int16((unsigned char *)data + 2, byte_order) != 0x002A)
190                 {
191                 return FALSE;
192                 }
193
194         offset = exif_byte_get_int32((unsigned char *)data + 4, byte_order);
195         if (!tiff_nikon_verify((unsigned char *)data, len, offset, byte_order)) return FALSE;
196
197         while (offset != 0)
198                 {
199                 guint next_offset = 0;
200                 tiff_table((unsigned char *)data, len, offset, byte_order, &i_off, &i_len);
201                 offset = next_offset;
202                 }
203
204         if (i_off != 0)
205                 {
206                 if (image_offset) *image_offset = i_off;
207                 return TRUE;
208                 }
209
210         return FALSE;
211 }
212
213
214 /*
215  *-----------------------------------------------------------------------------
216  * EXIF Makernote for Nikon
217  *-----------------------------------------------------------------------------
218  */
219
220 static ExifTextList NikonTagQuality[]= {
221         { 1,    "VGA basic" },
222         { 2,    "VGA normal" },
223         { 3,    "VGA fine" },
224         { 4,    "SXGA basic" },
225         { 5,    "SXGA normal" },
226         { 6,    "SXGA fine" },
227         { 7,    "XGA basic (?)" },
228         { 8,    "XGA normal (?)" },
229         { 9,    "XGA fine (?)" },
230         { 10,   "UXGA basic" },
231         { 11,   "UXGA normal" },
232         { 12,   "UXGA fine" },
233         EXIF_TEXT_LIST_END
234 };
235
236 static ExifTextList NikonTagColorMode[]= {
237         { 1,    "color" },
238         { 2,    "monochrome" },
239         EXIF_TEXT_LIST_END
240 };
241
242 static ExifTextList NikonTagImgAdjust[]= {
243         { 0,    "normal" },
244         { 1,    "bright+" },
245         { 2,    "bright-" },
246         { 3,    "contrast+" },
247         { 4,    "contrast-" },
248         EXIF_TEXT_LIST_END
249 };
250
251 static ExifTextList NikonTagISOSensitivity[]= {
252         { 0,    "80" },
253         { 2,    "160" },
254         { 4,    "320" },
255         { 5,    "100" },
256         EXIF_TEXT_LIST_END
257 };
258
259 static ExifTextList NikonTagWhiteBalance[]= {
260         { 0,    "auto" },
261         { 1,    "preset" },
262         { 2,    "daylight" },
263         { 3,    "incandescent" },
264         { 4,    "fluorescence" },
265         { 5,    "cloudy" },
266         { 6,    "speedlight" },
267         EXIF_TEXT_LIST_END
268 };
269
270 static ExifTextList NikonTagConverter[]= {
271         { 0,    "none" },
272         { 1,    "Fisheye" },
273         EXIF_TEXT_LIST_END
274 };
275
276 #if 0
277 static ExifTextList NikonTag[]= {
278         { ,     "" },
279         { ,     "" },
280         EXIF_TEXT_LIST_END
281 };
282 #endif
283
284 static ExifMarker NikonExifMarkersList1[] = {
285 { 0x0002, EXIF_FORMAT_STRING, 6,                "MkN.Nikon.unknown",    NULL,           NULL },
286 { 0x0003, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.Quality",    "Quality",      NikonTagQuality },
287 { 0x0004, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ColorMode",  "Color mode",   NikonTagColorMode },
288 { 0x0005, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ImageAdjustment",
289                                                                 "Image adjustment",     NikonTagImgAdjust },
290 { 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ISOSensitivity",
291                                                                 "ISO sensitivity",      NikonTagISOSensitivity },
292 { 0x0007, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.WhiteBalance",
293                                                                 "White balance",        NikonTagWhiteBalance },
294 { 0x0008, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "MkN.Nikon.Focus",      "Focus",        NULL },
295 { 0x000a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "MkN.Nikon.DigitalZoom","Digital zoom", NULL },
296 { 0x000b, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.Converter",  "Converter",    NikonTagConverter },
297 EXIF_MARKER_LIST_END
298 };
299
300 static ExifTextList NikonTag2FlashComp[]= {
301         { 0x06, "+1.0 EV" },
302         { 0x04, "+0.7 EV" },
303         { 0x03, "+0.5 EV" },
304         { 0x02, "+0.3 EV" },
305         { 0x00, "0.0 EV" },
306         { 0xfe, "-0.3 EV" },
307         { 0xfd, "-0.5 EV" },
308         { 0xfc, "-0.7 EV" },
309         { 0xfa, "-1.0 EV" },
310         { 0xf8, "-1.3 EV" },
311         { 0xf7, "-1.5 EV" },
312         { 0xf6, "-1.7 EV" },
313         { 0xf4, "-2.0 EV" },
314         { 0xf2, "-2.3 EV" },
315         { 0xf1, "-2.5 EV" },
316         { 0xf0, "-2.7 EV" },
317         { 0xee, "-3.0 EV" },
318         EXIF_TEXT_LIST_END
319 };
320
321 static ExifTextList NikonTag2FlashUsed[]= {
322         { 0,    "no" },
323         { 9,    "yes" },
324         EXIF_TEXT_LIST_END
325 };
326
327 #if 0
328 static ExifTextList NikonTagi2Saturation[]= {
329         { -3,   "black and white" },
330         { -2,   "-2" },
331         { -1,   "-1" },
332         { 0,    "normal" },
333         { 1,    "+1" },
334         { 2,    "+2" },
335         EXIF_TEXT_LIST_END
336 };
337 #endif
338
339 static ExifMarker NikonExifMarkersList2[] = {
340 { 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "MkN.Nikon.ISOSpeed",   "ISO speed",    NULL },
341 { 0x0003, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ColorMode",  "Color mode",   NULL },
342 { 0x0004, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Quality",    "Quality",      NULL },
343 { 0x0005, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.WhiteBalance",
344                                                                 "White balance",        NULL },
345 { 0x0006, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Sharpening", "Sharpening",   NULL },
346 { 0x0007, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.FocusMode",  "Focus mode",   NULL },
347 { 0x0008, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.FlashSetting",
348                                                                 "Flash setting",        NULL },
349 { 0x0009, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.AutoFlashMode","Auto flash mode",NULL },
350 { 0x000b, EXIF_FORMAT_SHORT, 1,                 "MkN.Nikon.WhiteBalanceBias",
351                                                         "White balance bias value",     NULL },
352 /* { 0x000c, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "MkN.Nikon.WhiteBalanceCoeff",
353                                                 "White balance red/blue coefficents",   NULL }, */
354 /* { 0x000f, EXIF_FORMAT_STRING, -1,            "MkN.Nikon.ISOSelect",  "ISO selection",NULL }, */
355 { 0x0012, EXIF_FORMAT_UNDEFINED, 4,             "MkN.Nikon.FlashCompensation",
356                                                                 "Flash compensation",   NikonTag2FlashComp },
357 { 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "MkN.Nikon.ISOSpeedRequest",
358                                                                 "ISO speed requested",  NULL },
359 { 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4,        "MkN.Nikon.CornerCoord",
360                                                                 "Corner coordinates",   NULL },
361 { 0x0018, EXIF_FORMAT_UNDEFINED, 4,             "MkN.Nikon.FlashBracketCompensation",
362                                                         "Flash bracket compensation",   NikonTag2FlashComp },
363 { 0x0019, EXIF_FORMAT_RATIONAL, 1,              "MkN.Nikon.AEBracketCompensation",
364                                                         "AE bracket compensation",      NULL },
365 { 0x0080, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ImageAdjustment",
366                                                                 "Image adjustment",     NULL },
367 { 0x0081, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Contrast",   "Contrast",     NULL },
368 { 0x0082, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.AuxLens","Aux lens adapter", NULL },
369 { 0x0083, EXIF_FORMAT_BYTE_UNSIGNED, -1,        "MkN.Nikon.LensType",   "Lens type",    NULL },
370 { 0x0084, EXIF_FORMAT_RATIONAL_UNSIGNED, -1,    "MkN.Nikon.LensFocalLength",
371                                                         "Lens min/max focal length and aperture", NULL },
372 { 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ManualFocusDistance",
373                                                         "Manual focus distance",        NULL },
374 { 0x0086, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.DigitalZoomFactor",
375                                                         "Digital zoom facotr",          NULL },
376 { 0x0087, EXIF_FORMAT_BYTE_UNSIGNED, 1,         "MkN.Nikon.FlashUsed",  "Flash used",   NikonTag2FlashUsed },
377 { 0x0088, EXIF_FORMAT_UNDEFINED, -1,            "MkN.Nikon.AutoFocusArea", NULL,        NULL },
378 /* { 0x0089, EXIF_FORMAT_SHORT_UNSIGNED, -1,    "MkN.Nikon.Bracket/ShootingMode", NULL, NULL }, */
379 { 0x008d, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ColorMode",  "Color mode",   NULL },
380 { 0x008f, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.SceneMode",  NULL,           NULL },
381 { 0x0090, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.LightingType", "Lighting type", NULL },
382 { 0x0092, EXIF_FORMAT_SHORT, 1,                 "MkN.Nikon.HueAdjust",  "Hue adjustment", NULL },
383 /* { 0x0094, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "MkN.Nikon.Saturation", "Saturation",   NikonTag2Saturation }, */
384 { 0x0095, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.NoiseReduction", "Noise reduction", NULL },
385 { 0x00a7, EXIF_FORMAT_LONG_UNSIGNED, 1,         "MkN.Nikon.ShutterCount", "Shutter release count", NULL },
386 { 0x00a9, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ImageOptimization", "Image optimization", NULL },
387 { 0x00aa, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Saturation", "Saturation",   NULL },
388 { 0x00ab, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.DigitalVariProg", "Digital Vari-program", NULL },
389 EXIF_MARKER_LIST_END
390 };
391
392
393 gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset,
394                             guint size, ExifByteOrder byte_order)
395 {
396         unsigned char *data;
397
398         if (offset + 8 + 4 >= size) return FALSE;
399
400         data = tiff + offset;
401         if (memcmp(data, "Nikon\x00\x01\x00", 8) == 0)
402                 {
403                 if (exif_parse_IFD_table(exif, tiff, offset + 8, size,
404                                          byte_order, NikonExifMarkersList1) != 0)
405                         {
406                         return FALSE;
407                         }
408                 return TRUE;
409                 }
410
411         if (memcmp(data, "Nikon\x00\x02\x00\x00\x00", 10) == 0 ||
412             memcmp(data, "Nikon\x00\x02\x10\x00\x00", 10) == 0)
413                 {
414                 guint tiff_header;
415
416                 tiff_header = offset + 10;
417                 if (exif_parse_TIFF(exif, tiff + tiff_header, size - tiff_header,
418                     NikonExifMarkersList2) != 0)
419                         {
420                         return FALSE;
421                         }
422                 return TRUE;
423                 }
424
425         /* fixme: support E990 and D1 */
426         if (exif_parse_IFD_table(exif, tiff, offset, size,
427                                  byte_order, NikonExifMarkersList2) != 0)
428                 {
429                 return FALSE;
430                 }
431
432         return FALSE;
433 }
434