f5fcce6a2f31688ac72ccb772db2cc7132d9d0a2
[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 nikon_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
39                               gint level,
40                               guint *image_offset, guint *jpeg_len);
41
42
43 static void nikon_tiff_entry(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
44                              gint level,
45                              guint *image_offset, guint *image_length, guint *jpeg_start, guint *jpeg_len)
46 {
47         guint tag;
48         guint type;
49         guint count;
50         guint segment;
51         guint seg_len;
52
53         tag = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_TAG, bo);
54         type = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_FORMAT, bo);
55         count = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_COUNT, bo);
56
57         /* so far, we only care about tags with type long */
58         if (type != EXIF_FORMAT_LONG_UNSIGNED && type != EXIF_FORMAT_LONG) return;
59
60         seg_len = ExifFormatList[type].size * count;
61         if (seg_len > 4)
62                 {
63                 segment = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo);
64                 if (segment + seg_len > len) return;
65                 }
66         else
67                 {
68                 segment = offset + EXIF_TIFD_OFFSET_DATA;
69                 }
70
71         if (tag == 0x14a)
72                 {
73                 /* sub IFD table */
74                 gint i;
75
76                 for (i = 0; i < count; i++)
77                         {
78                         guint subset;
79
80                         subset = exif_byte_get_int32(data + segment + i * 4, bo);
81                         nikon_tiff_table(data, len, subset, bo, level + 1, image_offset, image_length);
82                         }
83
84                 }
85         else if (tag == 0x201)
86                 {
87                 /* jpeg data start offset */
88                 *jpeg_start = exif_byte_get_int32(data + segment, bo);
89                 }
90         else if (tag == 0x202)
91                 {
92                 /* jpeg data length */
93                 *jpeg_len = exif_byte_get_int32(data + segment, bo);
94                 }
95 }
96
97 static guint nikon_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
98                               gint level,
99                               guint *image_offset, guint *image_length)
100 {
101         guint count;
102         guint i;
103         guint jpeg_start = 0;
104         guint jpeg_len = 0;
105
106         /* limit damage from infinite loops */
107         if (level > EXIF_TIFF_MAX_LEVELS) return 0;
108
109         if (len < offset + 2) return FALSE;
110
111         count = exif_byte_get_int16(data + offset, bo);
112
113         if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0;
114         offset += 2;
115
116         for (i = 0; i < count; i++)
117                 {
118                 nikon_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo, level,
119                                  image_offset, image_length, &jpeg_start, &jpeg_len);
120                 }
121
122         if (jpeg_start > 0 &&
123             jpeg_len > *image_length)
124                 {
125                 *image_offset = jpeg_start;
126                 *image_length = jpeg_len;
127                 }
128
129         return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo);
130 }
131
132 gint format_nikon_raw(unsigned char *data, const guint len,
133                       guint *image_offset, guint *exif_offset)
134 {
135         guint i_off = 0;
136         guint i_len = 0;
137         ExifByteOrder bo;
138         guint offset;
139         gint level;
140
141         if (!exif_tiff_directory_offset(data, len, &offset, &bo)) return FALSE;
142
143         level = 0;
144         while (offset && level < EXIF_TIFF_MAX_LEVELS)
145                 {
146                 offset = nikon_tiff_table(data, len, offset, bo, 0, &i_off, &i_len);
147                 level++;
148                 }
149
150         if (i_off != 0)
151                 {
152                 if (image_offset) *image_offset = i_off;
153                 return TRUE;
154                 }
155
156         return FALSE;
157 }
158
159
160 /*
161  *-----------------------------------------------------------------------------
162  * EXIF Makernote for Nikon
163  *-----------------------------------------------------------------------------
164  */
165
166 static ExifTextList NikonTagQuality[]= {
167         { 1,    "VGA basic" },
168         { 2,    "VGA normal" },
169         { 3,    "VGA fine" },
170         { 4,    "SXGA basic" },
171         { 5,    "SXGA normal" },
172         { 6,    "SXGA fine" },
173         { 7,    "XGA basic (?)" },
174         { 8,    "XGA normal (?)" },
175         { 9,    "XGA fine (?)" },
176         { 10,   "UXGA basic" },
177         { 11,   "UXGA normal" },
178         { 12,   "UXGA fine" },
179         EXIF_TEXT_LIST_END
180 };
181
182 static ExifTextList NikonTagColorMode[]= {
183         { 1,    "color" },
184         { 2,    "monochrome" },
185         EXIF_TEXT_LIST_END
186 };
187
188 static ExifTextList NikonTagImgAdjust[]= {
189         { 0,    "normal" },
190         { 1,    "bright+" },
191         { 2,    "bright-" },
192         { 3,    "contrast+" },
193         { 4,    "contrast-" },
194         EXIF_TEXT_LIST_END
195 };
196
197 static ExifTextList NikonTagISOSensitivity[]= {
198         { 0,    "80" },
199         { 2,    "160" },
200         { 4,    "320" },
201         { 5,    "100" },
202         EXIF_TEXT_LIST_END
203 };
204
205 static ExifTextList NikonTagWhiteBalance[]= {
206         { 0,    "auto" },
207         { 1,    "preset" },
208         { 2,    "daylight" },
209         { 3,    "incandescent" },
210         { 4,    "fluorescence" },
211         { 5,    "cloudy" },
212         { 6,    "speedlight" },
213         EXIF_TEXT_LIST_END
214 };
215
216 static ExifTextList NikonTagConverter[]= {
217         { 0,    "none" },
218         { 1,    "Fisheye" },
219         EXIF_TEXT_LIST_END
220 };
221
222 #if 0
223 static ExifTextList NikonTag[]= {
224         { ,     "" },
225         { ,     "" },
226         EXIF_TEXT_LIST_END
227 };
228 #endif
229
230 static ExifMarker NikonExifMarkersList1[] = {
231 { 0x0002, EXIF_FORMAT_STRING, 6,                "MkN.Nikon.unknown",    NULL,           NULL },
232 { 0x0003, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.Quality",    "Quality",      NikonTagQuality },
233 { 0x0004, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ColorMode",  "Color mode",   NikonTagColorMode },
234 { 0x0005, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ImageAdjustment",
235                                                                 "Image adjustment",     NikonTagImgAdjust },
236 { 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ISOSensitivity",
237                                                                 "ISO sensitivity",      NikonTagISOSensitivity },
238 { 0x0007, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.WhiteBalance",
239                                                                 "White balance",        NikonTagWhiteBalance },
240 { 0x0008, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "MkN.Nikon.Focus",      "Focus",        NULL },
241 { 0x000a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "MkN.Nikon.DigitalZoom","Digital zoom", NULL },
242 { 0x000b, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.Converter",  "Converter",    NikonTagConverter },
243 EXIF_MARKER_LIST_END
244 };
245
246 static ExifTextList NikonTag2FlashComp[]= {
247         { 0x06, "+1.0 EV" },
248         { 0x04, "+0.7 EV" },
249         { 0x03, "+0.5 EV" },
250         { 0x02, "+0.3 EV" },
251         { 0x00, "0.0 EV" },
252         { 0xfe, "-0.3 EV" },
253         { 0xfd, "-0.5 EV" },
254         { 0xfc, "-0.7 EV" },
255         { 0xfa, "-1.0 EV" },
256         { 0xf8, "-1.3 EV" },
257         { 0xf7, "-1.5 EV" },
258         { 0xf6, "-1.7 EV" },
259         { 0xf4, "-2.0 EV" },
260         { 0xf2, "-2.3 EV" },
261         { 0xf1, "-2.5 EV" },
262         { 0xf0, "-2.7 EV" },
263         { 0xee, "-3.0 EV" },
264         EXIF_TEXT_LIST_END
265 };
266
267 static ExifTextList NikonTag2FlashUsed[]= {
268         { 0,    "no" },
269         { 9,    "yes" },
270         EXIF_TEXT_LIST_END
271 };
272
273 #if 0
274 static ExifTextList NikonTagi2Saturation[]= {
275         { -3,   "black and white" },
276         { -2,   "-2" },
277         { -1,   "-1" },
278         { 0,    "normal" },
279         { 1,    "+1" },
280         { 2,    "+2" },
281         EXIF_TEXT_LIST_END
282 };
283 #endif
284
285 static ExifMarker NikonExifMarkersList2[] = {
286 { 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "MkN.Nikon.ISOSpeed",   "ISO speed",    NULL },
287 { 0x0003, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ColorMode",  "Color mode",   NULL },
288 { 0x0004, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Quality",    "Quality",      NULL },
289 { 0x0005, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.WhiteBalance",
290                                                                 "White balance",        NULL },
291 { 0x0006, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Sharpening", "Sharpening",   NULL },
292 { 0x0007, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.FocusMode",  "Focus mode",   NULL },
293 { 0x0008, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.FlashSetting",
294                                                                 "Flash setting",        NULL },
295 { 0x0009, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.AutoFlashMode","Auto flash mode",NULL },
296 { 0x000b, EXIF_FORMAT_SHORT, 1,                 "MkN.Nikon.WhiteBalanceBias",
297                                                         "White balance bias value",     NULL },
298 /* { 0x000c, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "MkN.Nikon.WhiteBalanceCoeff",
299                                                 "White balance red/blue coefficents",   NULL }, */
300 /* { 0x000f, EXIF_FORMAT_STRING, -1,            "MkN.Nikon.ISOSelect",  "ISO selection",NULL }, */
301 { 0x0012, EXIF_FORMAT_UNDEFINED, 4,             "MkN.Nikon.FlashCompensation",
302                                                                 "Flash compensation",   NikonTag2FlashComp },
303 { 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "MkN.Nikon.ISOSpeedRequest",
304                                                                 "ISO speed requested",  NULL },
305 { 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4,        "MkN.Nikon.CornerCoord",
306                                                                 "Corner coordinates",   NULL },
307 { 0x0018, EXIF_FORMAT_UNDEFINED, 4,             "MkN.Nikon.FlashBracketCompensation",
308                                                         "Flash bracket compensation",   NikonTag2FlashComp },
309 { 0x0019, EXIF_FORMAT_RATIONAL, 1,              "MkN.Nikon.AEBracketCompensation",
310                                                         "AE bracket compensation",      NULL },
311 { 0x0080, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ImageAdjustment",
312                                                                 "Image adjustment",     NULL },
313 { 0x0081, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Contrast",   "Contrast",     NULL },
314 { 0x0082, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.AuxLens","Aux lens adapter", NULL },
315 { 0x0083, EXIF_FORMAT_BYTE_UNSIGNED, -1,        "MkN.Nikon.LensType",   "Lens type",    NULL },
316 { 0x0084, EXIF_FORMAT_RATIONAL_UNSIGNED, -1,    "MkN.Nikon.LensFocalLength",
317                                                         "Lens min/max focal length and aperture", NULL },
318 { 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.ManualFocusDistance",
319                                                         "Manual focus distance",        NULL },
320 { 0x0086, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.DigitalZoomFactor",
321                                                         "Digital zoom facotr",          NULL },
322 { 0x0087, EXIF_FORMAT_BYTE_UNSIGNED, 1,         "MkN.Nikon.FlashUsed",  "Flash used",   NikonTag2FlashUsed },
323 { 0x0088, EXIF_FORMAT_UNDEFINED, -1,            "MkN.Nikon.AutoFocusArea", NULL,        NULL },
324 /* { 0x0089, EXIF_FORMAT_SHORT_UNSIGNED, -1,    "MkN.Nikon.Bracket/ShootingMode", NULL, NULL }, */
325 { 0x008d, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ColorMode",  "Color mode",   NULL },
326 { 0x008f, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "MkN.Nikon.SceneMode",  NULL,           NULL },
327 { 0x0090, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.LightingType", "Lighting type", NULL },
328 { 0x0092, EXIF_FORMAT_SHORT, 1,                 "MkN.Nikon.HueAdjust",  "Hue adjustment", NULL },
329 /* { 0x0094, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "MkN.Nikon.Saturation", "Saturation",   NikonTag2Saturation }, */
330 { 0x0095, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.NoiseReduction", "Noise reduction", NULL },
331 { 0x00a7, EXIF_FORMAT_LONG_UNSIGNED, 1,         "MkN.Nikon.ShutterCount", "Shutter release count", NULL },
332 { 0x00a9, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.ImageOptimization", "Image optimization", NULL },
333 { 0x00aa, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.Saturation", "Saturation",   NULL },
334 { 0x00ab, EXIF_FORMAT_STRING, -1,               "MkN.Nikon.DigitalVariProg", "Digital Vari-program", NULL },
335 EXIF_MARKER_LIST_END
336 };
337
338
339 gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset,
340                             guint size, ExifByteOrder bo)
341 {
342         unsigned char *data;
343
344         if (offset + 8 + 4 >= size) return FALSE;
345
346         data = tiff + offset;
347
348         /* Nikon tag format 1 */
349         if (memcmp(data, "Nikon\x00\x01\x00", 8) == 0)
350                 {
351                 if (exif_parse_IFD_table(exif, tiff, offset + 8, size,
352                                          bo, 0, NikonExifMarkersList1) != 0)
353                         {
354                         return FALSE;
355                         }
356                 return TRUE;
357                 }
358
359         /* Nikon tag format 2 uses Embedded tiff header */
360         if (memcmp(data, "Nikon\x00\x02\x00\x00\x00", 10) == 0 ||
361             memcmp(data, "Nikon\x00\x02\x10\x00\x00", 10) == 0)
362                 {
363                 guint tiff_header;
364
365                 tiff_header = offset + 10;
366                 if (exif_tiff_parse(exif, tiff + tiff_header, size - tiff_header,
367                     NikonExifMarkersList2) != 0)
368                         {
369                         return FALSE;
370                         }
371                 return TRUE;
372                 }
373
374         /* Nikon tag format 3 uses format 2 tags without "Nikon" and tiff header */
375         if (exif_parse_IFD_table(exif, tiff, offset, size,
376                                  bo, 0, NikonExifMarkersList2) != 0)
377                 {
378                 return FALSE;
379                 }
380
381         return FALSE;
382 }
383