6 * Raw NEF jpeg extraction based on nefextract.c by Joseph Heled,
7 * in addition nefextract.c is based on dcraw by Dave Coffin.
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!
27 #include "format_nikon.h"
33 *-----------------------------------------------------------------------------
34 * Raw NEF embedded jpeg extraction for Nikon
35 *-----------------------------------------------------------------------------
38 static guint nikon_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
40 guint *image_offset, guint *jpeg_len);
43 static void nikon_tiff_entry(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
45 guint *image_offset, guint *image_length, guint *jpeg_start, guint *jpeg_len)
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);
57 /* so far, we only care about tags with type long */
58 if (type != EXIF_FORMAT_LONG_UNSIGNED && type != EXIF_FORMAT_LONG) return;
60 seg_len = ExifFormatList[type].size * count;
63 segment = exif_byte_get_int32(data + offset + EXIF_TIFD_OFFSET_DATA, bo);
64 if (segment + seg_len > len) return;
68 segment = offset + EXIF_TIFD_OFFSET_DATA;
76 for (i = 0; i < count; i++)
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);
85 else if (tag == 0x201)
87 /* jpeg data start offset */
88 *jpeg_start = exif_byte_get_int32(data + segment, bo);
90 else if (tag == 0x202)
92 /* jpeg data length */
93 *jpeg_len = exif_byte_get_int32(data + segment, bo);
97 static guint nikon_tiff_table(unsigned char *data, const guint len, guint offset, ExifByteOrder bo,
99 guint *image_offset, guint *image_length)
103 guint jpeg_start = 0;
106 /* limit damage from infinite loops */
107 if (level > EXIF_TIFF_MAX_LEVELS) return 0;
109 if (len < offset + 2) return FALSE;
111 count = exif_byte_get_int16(data + offset, bo);
113 if (len < offset + count * EXIF_TIFD_SIZE + 4) return 0;
116 for (i = 0; i < count; i++)
118 nikon_tiff_entry(data, len, offset + i * EXIF_TIFD_SIZE, bo, level,
119 image_offset, image_length, &jpeg_start, &jpeg_len);
122 if (jpeg_start > 0 &&
123 jpeg_len > *image_length)
125 *image_offset = jpeg_start;
126 *image_length = jpeg_len;
129 return exif_byte_get_int32(data + offset + count * EXIF_TIFD_SIZE, bo);
132 gint format_nikon_raw(unsigned char *data, const guint len,
133 guint *image_offset, guint *exif_offset)
141 if (!exif_tiff_directory_offset(data, len, &offset, &bo)) return FALSE;
144 while (offset && level < EXIF_TIFF_MAX_LEVELS)
146 offset = nikon_tiff_table(data, len, offset, bo, 0, &i_off, &i_len);
152 if (image_offset) *image_offset = i_off;
161 *-----------------------------------------------------------------------------
162 * EXIF Makernote for Nikon
163 *-----------------------------------------------------------------------------
166 static ExifTextList NikonTagQuality[]= {
171 { 5, "SXGA normal" },
173 { 7, "XGA basic (?)" },
174 { 8, "XGA normal (?)" },
175 { 9, "XGA fine (?)" },
176 { 10, "UXGA basic" },
177 { 11, "UXGA normal" },
182 static ExifTextList NikonTagColorMode[]= {
188 static ExifTextList NikonTagImgAdjust[]= {
197 static ExifTextList NikonTagISOSensitivity[]= {
205 static ExifTextList NikonTagWhiteBalance[]= {
209 { 3, "incandescent" },
210 { 4, "fluorescence" },
216 static ExifTextList NikonTagConverter[]= {
223 static ExifTextList NikonTag[]= {
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 },
246 static ExifTextList NikonTag2FlashComp[]= {
267 static ExifTextList NikonTag2FlashUsed[]= {
274 static ExifTextList NikonTagi2Saturation[]= {
275 { -3, "black and white" },
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 },
339 gint format_nikon_makernote(ExifData *exif, unsigned char *tiff, guint offset,
340 guint size, ExifByteOrder bo)
344 if (offset + 8 + 4 >= size) return FALSE;
346 data = tiff + offset;
348 /* Nikon tag format 1 */
349 if (memcmp(data, "Nikon\x00\x01\x00", 8) == 0)
351 if (exif_parse_IFD_table(exif, tiff, offset + 8, size,
352 bo, 0, NikonExifMarkersList1) != 0)
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)
365 tiff_header = offset + 10;
366 if (exif_tiff_parse(exif, tiff + tiff_header, size - tiff_header,
367 NikonExifMarkersList2) != 0)
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)