Open With feature
[geeqie.git] / src / format-nikon.cc
1 /*
2  * Copyright (C) 2005 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: Joseph Heled
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <config.h>
23
24 #ifndef HAVE_EXIV2
25
26 #include <cstdio>
27 #include <cstring>
28 #include <unistd.h>
29
30 #include <glib.h>
31
32 #include "intl.h"
33
34 #include "main.h"
35 #include "format-nikon.h"
36
37 #include "exif.h"
38
39
40 /*
41  *-----------------------------------------------------------------------------
42  * Raw NEF embedded jpeg extraction for Nikon
43  *-----------------------------------------------------------------------------
44  */
45
46 static guint nikon_tiff_table(guchar *data, guint len, guint offset, ExifByteOrder bo,
47                               gint level,
48                               guint *image_offset, guint *jpeg_len);
49
50
51 static void nikon_tiff_entry(guchar *data, const guint len, guint offset, ExifByteOrder bo,
52                              gint level,
53                              guint *image_offset, guint *image_length, guint *jpeg_start, guint *jpeg_len)
54 {
55         guint tag;
56         guint type;
57         guint count;
58         guint segment;
59         guint seg_len;
60
61         tag = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_TAG, bo);
62         type = exif_byte_get_int16(data + offset + EXIF_TIFD_OFFSET_FORMAT, bo);
63         count = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_COUNT, bo);
64
65         /* so far, we only care about tags with type long */
66         if (type != EXIF_FORMAT_LONG_UNSIGNED && type != EXIF_FORMAT_LONG) return;
67
68         seg_len = ExifFormatList[type].size * count;
69         if (seg_len > 4)
70                 {
71                 segment = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo);
72                 if (segment + seg_len > len) return;
73                 }
74         else
75                 {
76                 segment = offset + EXIF_TIFD_OFFSET_DATA;
77                 }
78
79         if (tag == 0x14a)
80                 {
81                 /* sub IFD table */
82                 guint i;
83
84                 for (i = 0; i < count; i++)
85                         {
86                         guint subset;
87
88                         subset = exif_byte_get_int32(data + segment + i * 4, bo);
89                         nikon_tiff_table(data, len, subset, bo, level + 1, image_offset, image_length);
90                         }
91
92                 }
93         else if (tag == 0x201)
94                 {
95                 /* jpeg data start offset */
96                 *jpeg_start = exif_byte_get_int32(data + segment, bo);
97                 }
98         else if (tag == 0x202)
99                 {
100                 /* jpeg data length */
101                 *jpeg_len = exif_byte_get_int32(data + segment, bo);
102                 }
103 }
104
105 static guint nikon_tiff_table(guchar *data, const guint len, guint offset, ExifByteOrder bo,
106                               gint level,
107                               guint *image_offset, guint *image_length)
108 {
109         guint count;
110         guint i;
111         guint jpeg_start = 0;
112         guint jpeg_len = 0;
113
114         /* limit damage from infinite loops */
115         if (level > EXIF_TIFF_MAX_LEVELS) return 0;
116
117         if (len < offset + 2) return FALSE;
118
119         count = exif_byte_get_int16(data + offset, bo);
120         offset += 2;
121         if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0;
122
123         for (i = 0; i < count; i++)
124                 {
125                 nikon_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo, level,
126                                  image_offset, image_length, &jpeg_start, &jpeg_len);
127                 }
128
129         if (jpeg_start > 0 &&
130             jpeg_len > *image_length)
131                 {
132                 *image_offset = jpeg_start;
133                 *image_length = jpeg_len;
134                 }
135
136         return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo);
137 }
138
139 gboolean format_nikon_raw(guchar *data, const guint len,
140                           guint *image_offset, guint *)
141 {
142         guint i_off = 0;
143         guint i_len = 0;
144         ExifByteOrder bo;
145         guint offset;
146         gint level;
147
148         if (!exif_tiff_directory_offset(data, len, &offset, &bo)) return FALSE;
149
150         level = 0;
151         while (offset && level < EXIF_TIFF_MAX_LEVELS)
152                 {
153                 offset = nikon_tiff_table(data, len, offset, bo, 0, &i_off, &i_len);
154                 level++;
155                 }
156
157         if (i_off != 0)
158                 {
159                 if (image_offset) *image_offset = i_off;
160                 return TRUE;
161                 }
162
163         return FALSE;
164 }
165
166
167 /*
168  *-----------------------------------------------------------------------------
169  * EXIF Makernote for Nikon
170  *-----------------------------------------------------------------------------
171  */
172
173 static ExifTextList NikonTagQuality[]= {
174         { 1,    "VGA basic" },
175         { 2,    "VGA normal" },
176         { 3,    "VGA fine" },
177         { 4,    "SXGA basic" },
178         { 5,    "SXGA normal" },
179         { 6,    "SXGA fine" },
180         { 7,    "XGA basic (?)" },
181         { 8,    "XGA normal (?)" },
182         { 9,    "XGA fine (?)" },
183         { 10,   "UXGA basic" },
184         { 11,   "UXGA normal" },
185         { 12,   "UXGA fine" },
186         EXIF_TEXT_LIST_END
187 };
188
189 static ExifTextList NikonTagColorMode[]= {
190         { 1,    "color" },
191         { 2,    "monochrome" },
192         EXIF_TEXT_LIST_END
193 };
194
195 static ExifTextList NikonTagImgAdjust[]= {
196         { 0,    "normal" },
197         { 1,    "bright+" },
198         { 2,    "bright-" },
199         { 3,    "contrast+" },
200         { 4,    "contrast-" },
201         EXIF_TEXT_LIST_END
202 };
203
204 static ExifTextList NikonTagISOSensitivity[]= {
205         { 0,    "80" },
206         { 2,    "160" },
207         { 4,    "320" },
208         { 5,    "100" },
209         EXIF_TEXT_LIST_END
210 };
211
212 static ExifTextList NikonTagWhiteBalance[]= {
213         { 0,    "auto" },
214         { 1,    "preset" },
215         { 2,    "daylight" },
216         { 3,    "incandescent" },
217         { 4,    "fluorescence" },
218         { 5,    "cloudy" },
219         { 6,    "speedlight" },
220         EXIF_TEXT_LIST_END
221 };
222
223 static ExifTextList NikonTagConverter[]= {
224         { 0,    "none" },
225         { 1,    "Fisheye" },
226         EXIF_TEXT_LIST_END
227 };
228
229 static ExifMarker NikonExifMarkersList1[] = {
230 { 0x0002, EXIF_FORMAT_STRING, 6,                "Nikon.unknown",        nullptr,                nullptr },
231 { 0x0003, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.Quality",        "Quality",      NikonTagQuality },
232 { 0x0004, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.ColorMode",      "Color mode",   NikonTagColorMode },
233 { 0x0005, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.ImageAdjustment",
234                                                                 "Image adjustment",     NikonTagImgAdjust },
235 { 0x0006, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.ISOSensitivity",
236                                                                 "ISO sensitivity",      NikonTagISOSensitivity },
237 { 0x0007, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.WhiteBalance",   "White balance",NikonTagWhiteBalance },
238 { 0x0008, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "Nikon.Focus",          "Focus",        nullptr },
239 { 0x000a, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,     "Nikon.DigitalZoom",    "Digital zoom", nullptr },
240 { 0x000b, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.Converter",      "Converter",    NikonTagConverter },
241 EXIF_MARKER_LIST_END
242 };
243
244 static ExifTextList NikonTag2FlashComp[]= {
245         { 0x06, "+1.0 EV" },
246         { 0x04, "+0.7 EV" },
247         { 0x03, "+0.5 EV" },
248         { 0x02, "+0.3 EV" },
249         { 0x00, "0.0 EV" },
250         { 0xfe, "-0.3 EV" },
251         { 0xfd, "-0.5 EV" },
252         { 0xfc, "-0.7 EV" },
253         { 0xfa, "-1.0 EV" },
254         { 0xf8, "-1.3 EV" },
255         { 0xf7, "-1.5 EV" },
256         { 0xf6, "-1.7 EV" },
257         { 0xf4, "-2.0 EV" },
258         { 0xf2, "-2.3 EV" },
259         { 0xf1, "-2.5 EV" },
260         { 0xf0, "-2.7 EV" },
261         { 0xee, "-3.0 EV" },
262         EXIF_TEXT_LIST_END
263 };
264
265 static ExifTextList NikonTag2LensType[]= {
266         { 0,    "AF non D" },
267         { 1,    "manual" },
268         { 2,    "AF-D or AF-s" },
269         { 6,    "AF-D G" },
270         { 10,   "AF-D VR" },
271         EXIF_TEXT_LIST_END
272 };
273
274 static ExifTextList NikonTag2FlashUsed[]= {
275         { 0,    "no" },
276         { 4,    "unit unknown" },
277         { 7,    "external" },
278         { 9,    "yes" },
279         EXIF_TEXT_LIST_END
280 };
281
282
283 static ExifMarker NikonExifMarkersList2[] = {
284 { 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "Nikon.ISOSpeed",       "ISO speed",    nullptr },
285 { 0x0003, EXIF_FORMAT_STRING, -1,               "Nikon.ColorMode",      "Color mode",   nullptr },
286 { 0x0004, EXIF_FORMAT_STRING, -1,               "Nikon.Quality",        "Quality",      nullptr },
287 { 0x0005, EXIF_FORMAT_STRING, -1,               "Nikon.WhiteBalance",   "White balance",nullptr },
288 { 0x0006, EXIF_FORMAT_STRING, -1,               "Nikon.Sharpening",     "Sharpening",   nullptr },
289 { 0x0007, EXIF_FORMAT_STRING, -1,               "Nikon.FocusMode",      "Focus mode",   nullptr },
290 { 0x0008, EXIF_FORMAT_STRING, -1,               "Nikon.FlashSetting",   "Flash setting",nullptr },
291 { 0x0009, EXIF_FORMAT_STRING, -1,               "Nikon.AutoFlashMode","Auto flash mode",nullptr },
292 { 0x000b, EXIF_FORMAT_SHORT, 1,                 "Nikon.WhiteBalanceBias",
293                                                         "White balance bias value",     nullptr },
294 /* { 0x000c, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "Nikon.WhiteBalanceRB",
295                                                 "White balance red/blue coefficients",  NULL }, */
296 /* { 0x000f, EXIF_FORMAT_STRING, -1,            "Nikon.ISOSelect",      "ISO selection",NULL }, */
297 { 0x0012, EXIF_FORMAT_UNDEFINED, 4,             "Nikon.FlashCompensation",
298                                                                 "Flash compensation",   NikonTag2FlashComp },
299 { 0x0013, EXIF_FORMAT_SHORT_UNSIGNED, 2,        "Nikon.ISOSpeedRequest",
300                                                                 "ISO speed requested",  nullptr },
301 { 0x0016, EXIF_FORMAT_SHORT_UNSIGNED, 4,        "Nikon.CornerCoord",
302                                                                 "Corner coordinates",   nullptr },
303 { 0x0018, EXIF_FORMAT_UNDEFINED, 4,             "Nikon.FlashBracketCompensation",
304                                                         "Flash bracket compensation",   NikonTag2FlashComp },
305 { 0x0019, EXIF_FORMAT_RATIONAL, 1,              "Nikon.AEBracketCompensation",
306                                                         "AE bracket compensation",      nullptr },
307 { 0x0080, EXIF_FORMAT_STRING, -1,               "Nikon.ImageAdjustment",
308                                                                 "Image adjustment",     nullptr },
309 { 0x0081, EXIF_FORMAT_STRING, -1,               "Nikon.Contrast",       "Contrast",     nullptr },
310 { 0x0082, EXIF_FORMAT_STRING, -1,               "Nikon.AuxLens", "Aux lens adapter",    nullptr },
311 { 0x0083, EXIF_FORMAT_BYTE_UNSIGNED, -1,        "Nikon.LensType",       "Lens type",    NikonTag2LensType },
312 { 0x0084, EXIF_FORMAT_RATIONAL_UNSIGNED, -1,    "Nikon.LensFocalLength",
313                                                         "Lens min/max focal length and aperture", nullptr },
314 { 0x0085, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.ManualFocusDistance",
315                                                         "Manual focus distance",        nullptr },
316 { 0x0086, EXIF_FORMAT_RATIONAL, 1,              "Nikon.DigitalZoomFactor",
317                                                         "Digital zoom factor",          nullptr },
318 { 0x0087, EXIF_FORMAT_BYTE_UNSIGNED, 1,         "Nikon.FlashUsed",      "Flash used",   NikonTag2FlashUsed },
319 { 0x0088, EXIF_FORMAT_UNDEFINED, 4,             "Nikon.AutoFocusArea","Auto focus area",nullptr },
320 /* { 0x0089, EXIF_FORMAT_SHORT_UNSIGNED, -1,    "Nikon.Bracket/ShootingMode", NULL,     NULL }, */
321 { 0x008d, EXIF_FORMAT_STRING, -1,               "Nikon.ColorMode",      "Color mode",   nullptr },
322 { 0x008f, EXIF_FORMAT_SHORT_UNSIGNED, 1,        "Nikon.SceneMode",      "Scene mode",   nullptr },
323 { 0x0090, EXIF_FORMAT_STRING, -1,               "Nikon.LightingType",   "Lighting type",nullptr },
324 { 0x0092, EXIF_FORMAT_SHORT, 1,                 "Nikon.HueAdjust",      "Hue adjustment",nullptr },
325 /* { 0x0094, EXIF_FORMAT_SHORT_UNSIGNED, 1,     "Nikon.Saturation",     "Saturation",   NikonTag2Saturation }, */
326 { 0x0095, EXIF_FORMAT_STRING, -1,               "Nikon.NoiseReduction", "Noise reduction", nullptr },
327 { 0x00a7, EXIF_FORMAT_LONG_UNSIGNED, 1,         "Nikon.ShutterCount", "Shutter release count", nullptr },
328 { 0x00a9, EXIF_FORMAT_STRING, -1,               "Nikon.ImageOptimization", "Image optimization", nullptr },
329 { 0x00aa, EXIF_FORMAT_STRING, -1,               "Nikon.Saturation", "Saturation",       nullptr },
330 { 0x00ab, EXIF_FORMAT_STRING, -1,               "Nikon.DigitalVariProg", "Digital Vari-program", nullptr },
331 EXIF_MARKER_LIST_END
332 };
333
334 static ExifTextList NikonAFPoint[]= {
335         { 0,    "center" },
336         { 1,    "top" },
337         { 2,    "bottom" },
338         { 3,    "left" },
339         { 4,    "right" },
340         EXIF_TEXT_LIST_END
341 };
342
343
344 gboolean format_nikon_makernote(ExifData *exif, guchar *tiff, guint offset,
345                                 guint size, ExifByteOrder bo)
346 {
347         guchar *data;
348         ExifItem *item;
349
350         if (offset + 8 + 4 >= size) return FALSE;
351
352         data = tiff + offset;
353
354         /* Nikon tag format 1 */
355         if (memcmp(data, "Nikon\x00\x01\x00", 8) == 0)
356                 {
357                 if (exif_parse_IFD_table(exif, tiff, offset + 8, size,
358                                          bo, 0, NikonExifMarkersList1) != 0)
359                         {
360                         return FALSE;
361                         }
362                 return TRUE;
363                 }
364
365         /* Nikon tag format 2 uses Embedded tiff header */
366         if (memcmp(data, "Nikon\x00\x02\x00\x00\x00", 10) == 0 ||
367             memcmp(data, "Nikon\x00\x02\x10\x00\x00", 10) == 0)
368                 {
369                 guint tiff_header;
370
371                 tiff_header = offset + 10;
372                 if (exif_tiff_parse(exif, tiff + tiff_header, size - tiff_header,
373                     NikonExifMarkersList2) != 0)
374                         {
375                         return FALSE;
376                         }
377                 }
378         /* Nikon tag format 3 uses format 2 tags without "Nikon" and tiff header */
379         else if (exif_parse_IFD_table(exif, tiff, offset, size,
380                                       bo, 0, NikonExifMarkersList2) != 0)
381                 {
382                 return FALSE;
383                 }
384
385         item = exif_get_item(exif, "Nikon.AutoFocusArea");
386         if (item && item->data_len == 4 * sizeof(guchar))
387                 {
388                 static ExifMarker marker = { 0x0088, EXIF_FORMAT_STRING, -1,
389                                              "Nikon.AutoFocusPoint", "Auto focus point", nullptr };
390                 auto array = static_cast<guchar*>(item->data);
391                 gchar *text;
392                 gint l;
393
394                 text = exif_text_list_find_value(NikonAFPoint, static_cast<gint>(array[1]));
395                 l = strlen(text) + 1;
396
397                 item = exif_item_new(marker.format, marker.tag, l, &marker);
398                 memcpy(item->data, text, l);
399
400                 g_free(text);
401
402                 exif->items = g_list_prepend(exif->items, item);
403                 }
404
405         item = exif_get_item(exif, "Nikon.ISOSpeed");
406         if (item && item->data_len == 2 * 2)
407                 {
408                 static ExifMarker marker = { 0x0002, EXIF_FORMAT_SHORT_UNSIGNED, 1,
409                                              "ISOSpeedRatings", "ISO speed", nullptr };
410                 ExifItem *shadow;
411
412                 shadow = exif_item_new(marker.format, marker.tag, 1, &marker);
413                 memcpy(shadow->data, static_cast<char *>(item->data) + 2, 2);
414
415                 exif->items = g_list_prepend(exif->items, shadow);
416                 }
417
418         item = exif_get_item(exif, "Nikon.WhiteBalance");
419         if (item && item->format == EXIF_FORMAT_STRING)
420                 {
421                 static ExifMarker marker = { 0x0005, EXIF_FORMAT_STRING, -1,
422                                              "LightSource", "Light source", nullptr };
423                 ExifItem *shadow;
424
425                 shadow = exif_item_new(marker.format, marker.tag, item->data_len, &marker);
426                 memcpy(shadow->data, item->data, item->data_len);
427
428                 exif->items = g_list_prepend(exif->items, shadow);
429                 }
430
431         return TRUE;
432 }
433
434 #else
435 using dummy_variable = int;
436 #endif
437 /* not HAVE_EXIV2 */
438 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */