summaryrefslogtreecommitdiffstats
path: root/libkdcraw/libraw/src/metadata/nikon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkdcraw/libraw/src/metadata/nikon.cpp')
-rw-r--r--libkdcraw/libraw/src/metadata/nikon.cpp1051
1 files changed, 1051 insertions, 0 deletions
diff --git a/libkdcraw/libraw/src/metadata/nikon.cpp b/libkdcraw/libraw/src/metadata/nikon.cpp
new file mode 100644
index 0000000..c0c90f8
--- /dev/null
+++ b/libkdcraw/libraw/src/metadata/nikon.cpp
@@ -0,0 +1,1051 @@
+/* -*- C++ -*-
+ * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
+ *
+ LibRaw is free software; you can redistribute it and/or modify
+ it under the terms of the one of two licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+ */
+
+#include "../../internal/dcraw_defs.h"
+
+// void hexDump(char *title, void *addr, int len);
+
+unsigned sget4_order (short _order, uchar *s);
+double sget_fixed32u (short _order, uchar *s);
+double AngleConversion_a (short _order, uchar *s);
+double AngleConversion (short _order, uchar *s);
+
+static const uchar xlat[2][256] = {
+ {0xc1, 0xbf, 0x6d, 0x0d, 0x59, 0xc5, 0x13, 0x9d, 0x83, 0x61, 0x6b, 0x4f,
+ 0xc7, 0x7f, 0x3d, 0x3d, 0x53, 0x59, 0xe3, 0xc7, 0xe9, 0x2f, 0x95, 0xa7,
+ 0x95, 0x1f, 0xdf, 0x7f, 0x2b, 0x29, 0xc7, 0x0d, 0xdf, 0x07, 0xef, 0x71,
+ 0x89, 0x3d, 0x13, 0x3d, 0x3b, 0x13, 0xfb, 0x0d, 0x89, 0xc1, 0x65, 0x1f,
+ 0xb3, 0x0d, 0x6b, 0x29, 0xe3, 0xfb, 0xef, 0xa3, 0x6b, 0x47, 0x7f, 0x95,
+ 0x35, 0xa7, 0x47, 0x4f, 0xc7, 0xf1, 0x59, 0x95, 0x35, 0x11, 0x29, 0x61,
+ 0xf1, 0x3d, 0xb3, 0x2b, 0x0d, 0x43, 0x89, 0xc1, 0x9d, 0x9d, 0x89, 0x65,
+ 0xf1, 0xe9, 0xdf, 0xbf, 0x3d, 0x7f, 0x53, 0x97, 0xe5, 0xe9, 0x95, 0x17,
+ 0x1d, 0x3d, 0x8b, 0xfb, 0xc7, 0xe3, 0x67, 0xa7, 0x07, 0xf1, 0x71, 0xa7,
+ 0x53, 0xb5, 0x29, 0x89, 0xe5, 0x2b, 0xa7, 0x17, 0x29, 0xe9, 0x4f, 0xc5,
+ 0x65, 0x6d, 0x6b, 0xef, 0x0d, 0x89, 0x49, 0x2f, 0xb3, 0x43, 0x53, 0x65,
+ 0x1d, 0x49, 0xa3, 0x13, 0x89, 0x59, 0xef, 0x6b, 0xef, 0x65, 0x1d, 0x0b,
+ 0x59, 0x13, 0xe3, 0x4f, 0x9d, 0xb3, 0x29, 0x43, 0x2b, 0x07, 0x1d, 0x95,
+ 0x59, 0x59, 0x47, 0xfb, 0xe5, 0xe9, 0x61, 0x47, 0x2f, 0x35, 0x7f, 0x17,
+ 0x7f, 0xef, 0x7f, 0x95, 0x95, 0x71, 0xd3, 0xa3, 0x0b, 0x71, 0xa3, 0xad,
+ 0x0b, 0x3b, 0xb5, 0xfb, 0xa3, 0xbf, 0x4f, 0x83, 0x1d, 0xad, 0xe9, 0x2f,
+ 0x71, 0x65, 0xa3, 0xe5, 0x07, 0x35, 0x3d, 0x0d, 0xb5, 0xe9, 0xe5, 0x47,
+ 0x3b, 0x9d, 0xef, 0x35, 0xa3, 0xbf, 0xb3, 0xdf, 0x53, 0xd3, 0x97, 0x53,
+ 0x49, 0x71, 0x07, 0x35, 0x61, 0x71, 0x2f, 0x43, 0x2f, 0x11, 0xdf, 0x17,
+ 0x97, 0xfb, 0x95, 0x3b, 0x7f, 0x6b, 0xd3, 0x25, 0xbf, 0xad, 0xc7, 0xc5,
+ 0xc5, 0xb5, 0x8b, 0xef, 0x2f, 0xd3, 0x07, 0x6b, 0x25, 0x49, 0x95, 0x25,
+ 0x49, 0x6d, 0x71, 0xc7},
+ {0xa7, 0xbc, 0xc9, 0xad, 0x91, 0xdf, 0x85, 0xe5, 0xd4, 0x78, 0xd5, 0x17,
+ 0x46, 0x7c, 0x29, 0x4c, 0x4d, 0x03, 0xe9, 0x25, 0x68, 0x11, 0x86, 0xb3,
+ 0xbd, 0xf7, 0x6f, 0x61, 0x22, 0xa2, 0x26, 0x34, 0x2a, 0xbe, 0x1e, 0x46,
+ 0x14, 0x68, 0x9d, 0x44, 0x18, 0xc2, 0x40, 0xf4, 0x7e, 0x5f, 0x1b, 0xad,
+ 0x0b, 0x94, 0xb6, 0x67, 0xb4, 0x0b, 0xe1, 0xea, 0x95, 0x9c, 0x66, 0xdc,
+ 0xe7, 0x5d, 0x6c, 0x05, 0xda, 0xd5, 0xdf, 0x7a, 0xef, 0xf6, 0xdb, 0x1f,
+ 0x82, 0x4c, 0xc0, 0x68, 0x47, 0xa1, 0xbd, 0xee, 0x39, 0x50, 0x56, 0x4a,
+ 0xdd, 0xdf, 0xa5, 0xf8, 0xc6, 0xda, 0xca, 0x90, 0xca, 0x01, 0x42, 0x9d,
+ 0x8b, 0x0c, 0x73, 0x43, 0x75, 0x05, 0x94, 0xde, 0x24, 0xb3, 0x80, 0x34,
+ 0xe5, 0x2c, 0xdc, 0x9b, 0x3f, 0xca, 0x33, 0x45, 0xd0, 0xdb, 0x5f, 0xf5,
+ 0x52, 0xc3, 0x21, 0xda, 0xe2, 0x22, 0x72, 0x6b, 0x3e, 0xd0, 0x5b, 0xa8,
+ 0x87, 0x8c, 0x06, 0x5d, 0x0f, 0xdd, 0x09, 0x19, 0x93, 0xd0, 0xb9, 0xfc,
+ 0x8b, 0x0f, 0x84, 0x60, 0x33, 0x1c, 0x9b, 0x45, 0xf1, 0xf0, 0xa3, 0x94,
+ 0x3a, 0x12, 0x77, 0x33, 0x4d, 0x44, 0x78, 0x28, 0x3c, 0x9e, 0xfd, 0x65,
+ 0x57, 0x16, 0x94, 0x6b, 0xfb, 0x59, 0xd0, 0xc8, 0x22, 0x36, 0xdb, 0xd2,
+ 0x63, 0x98, 0x43, 0xa1, 0x04, 0x87, 0x86, 0xf7, 0xa6, 0x26, 0xbb, 0xd6,
+ 0x59, 0x4d, 0xbf, 0x6a, 0x2e, 0xaa, 0x2b, 0xef, 0xe6, 0x78, 0xb6, 0x4e,
+ 0xe0, 0x2f, 0xdc, 0x7c, 0xbe, 0x57, 0x19, 0x32, 0x7e, 0x2a, 0xd0, 0xb8,
+ 0xba, 0x29, 0x00, 0x3c, 0x52, 0x7d, 0xa8, 0x49, 0x3b, 0x2d, 0xeb, 0x25,
+ 0x49, 0xfa, 0xa3, 0xaa, 0x39, 0xa7, 0xc5, 0xa7, 0x50, 0x11, 0x36, 0xfb,
+ 0xc6, 0x67, 0x4a, 0xf5, 0xa5, 0x12, 0x65, 0x7e, 0xb0, 0xdf, 0xaf, 0x4e,
+ 0xb3, 0x61, 0x7f, 0x2f} };
+
+void LibRaw::processNikonLensData(uchar *LensData, unsigned len)
+{
+
+ ushort i=0;
+ if (imgdata.lens.nikon.LensType & 0x80) {
+ strcpy (ilm.LensFeatures_pre, "AF-P");
+ } else if (!(imgdata.lens.nikon.LensType & 0x01)) {
+ ilm.LensFeatures_pre[0] = 'A';
+ ilm.LensFeatures_pre[1] = 'F';
+ } else {
+ ilm.LensFeatures_pre[0] = 'M';
+ ilm.LensFeatures_pre[1] = 'F';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x40) {
+ ilm.LensFeatures_suf[0] = 'E';
+ } else if (imgdata.lens.nikon.LensType & 0x04) {
+ ilm.LensFeatures_suf[0] = 'G';
+ } else if (imgdata.lens.nikon.LensType & 0x02) {
+ ilm.LensFeatures_suf[0] = 'D';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x08)
+ {
+ ilm.LensFeatures_suf[1] = ' ';
+ ilm.LensFeatures_suf[2] = 'V';
+ ilm.LensFeatures_suf[3] = 'R';
+ }
+
+ if (imgdata.lens.nikon.LensType & 0x10)
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_1INCH;
+ }
+ else
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_Nikon_F;
+
+ if (imgdata.lens.nikon.LensType & 0x20)
+ {
+ strcpy(ilm.Adapter, "FT-1");
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_F;
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ }
+
+ imgdata.lens.nikon.LensType = imgdata.lens.nikon.LensType & 0xdf;
+
+ if ((len < 20) || (len == 58) || (len == 108))
+ {
+ switch (len)
+ {
+ case 9:
+ i = 2;
+ break;
+ case 15:
+ i = 7;
+ break;
+ case 16:
+ i = 8;
+ break;
+ case 58: // "Z 6", "Z 6 II", "Z 7", "Z 7 II", "Z 50", D780, "Z 5", "Z fc"
+ case 108: // "Z 9"
+ if (model[6] == 'Z')
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_Z;
+ if (imNikon.HighSpeedCropFormat != 12)
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ i = 1;
+ while ((LensData[i] == LensData[0]) && (i < 17))
+ i++;
+ if (i == 17)
+ {
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_Z;
+ ilm.LensID = sget2(LensData + 0x2c);
+ if (
+ (ilm.LensID == 11)
+ || (ilm.LensID == 12)
+ || (ilm.LensID == 26)
+ ) ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ else ilm.LensFormat = LIBRAW_FORMAT_FF;
+ if (ilm.MaxAp4CurFocal < 0.7f)
+ ilm.MaxAp4CurFocal = libraw_powf64l(
+ 2.0f, (float)sget2(LensData + 0x32) / 384.0f - 1.0f);
+ if (ilm.CurAp < 0.7f)
+ ilm.CurAp = libraw_powf64l(
+ 2.0f, (float)sget2(LensData + 0x34) / 384.0f - 1.0f);
+ if (fabsf(ilm.CurFocal) < 1.1f)
+ ilm.CurFocal = sget2(LensData + 0x38);
+ return;
+ }
+ i = 9;
+ ilm.LensMount = LIBRAW_MOUNT_Nikon_F;
+ if (ilm.CameraMount == LIBRAW_MOUNT_Nikon_Z)
+ strcpy(ilm.Adapter, "FTZ");
+ break;
+ }
+ imgdata.lens.nikon.LensIDNumber = LensData[i];
+ imgdata.lens.nikon.LensFStops = LensData[i + 1];
+ ilm.LensFStops = (float)imgdata.lens.nikon.LensFStops / 12.0f;
+ if (fabsf(ilm.MinFocal) < 1.1f)
+ {
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 2])
+ ilm.MinFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 2] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 3])
+ ilm.MaxFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 3] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 4])
+ ilm.MaxAp4MinFocal =
+ libraw_powf64l(2.0f, (float)LensData[i + 4] / 24.0f);
+ if ((imgdata.lens.nikon.LensType ^ (uchar)0x01) || LensData[i + 5])
+ ilm.MaxAp4MaxFocal =
+ libraw_powf64l(2.0f, (float)LensData[i + 5] / 24.0f);
+ }
+ imgdata.lens.nikon.MCUVersion = LensData[i + 6];
+ if (i != 2)
+ {
+ if ((LensData[i - 1]) && (fabsf(ilm.CurFocal) < 1.1f))
+ ilm.CurFocal =
+ 5.0f * libraw_powf64l(2.0f, (float)LensData[i - 1] / 24.0f);
+ if (LensData[i + 7])
+ imgdata.lens.nikon.EffectiveMaxAp =
+ libraw_powf64l(2.0f, (float)LensData[i + 7] / 24.0f);
+ }
+ ilm.LensID = (unsigned long long)LensData[i] << 56 |
+ (unsigned long long)LensData[i + 1] << 48 |
+ (unsigned long long)LensData[i + 2] << 40 |
+ (unsigned long long)LensData[i + 3] << 32 |
+ (unsigned long long)LensData[i + 4] << 24 |
+ (unsigned long long)LensData[i + 5] << 16 |
+ (unsigned long long)LensData[i + 6] << 8 |
+ (unsigned long long)imgdata.lens.nikon.LensType;
+ }
+ else if ((len == 459) || (len == 590))
+ {
+ memcpy(ilm.Lens, LensData + 390, 64);
+ }
+ else if (len == 509)
+ {
+ memcpy(ilm.Lens, LensData + 391, 64);
+ }
+ else if (len == 879)
+ {
+ memcpy(ilm.Lens, LensData + 680, 64);
+ }
+
+ return;
+}
+
+void LibRaw::Nikon_NRW_WBtag(int wb, int skip)
+{
+
+ int r, g0, g1, b;
+ if (skip)
+ get4(); // skip wb "CCT", it is not unique
+ r = get4();
+ g0 = get4();
+ g1 = get4();
+ b = get4();
+ if (r && g0 && g1 && b)
+ {
+ icWBC[wb][0] = r << 1;
+ icWBC[wb][1] = g0;
+ icWBC[wb][2] = b << 1;
+ icWBC[wb][3] = g1;
+ }
+ return;
+}
+
+void LibRaw::parseNikonMakernote(int base, int uptag, unsigned /*dng_writer */)
+{
+
+ unsigned offset = 0, entries, tag, type, len, save;
+
+ unsigned c, i;
+ unsigned LensData_len = 0;
+ uchar *LensData_buf=0;
+ uchar ColorBalanceData_buf[324];
+ int ColorBalanceData_ready = 0;
+ uchar ci, cj, ck;
+ unsigned serial = 0;
+ unsigned custom_serial = 0;
+
+ unsigned ShotInfo_len = 0;
+ uchar *ShotInfo_buf=0;
+
+/* for dump:
+uchar *cj_block, *ck_block;
+*/
+
+ short morder, sorder = order;
+ char buf[10];
+ INT64 fsize = ifp->size();
+
+ fread(buf, 1, 10, ifp);
+
+ if (!strcmp(buf, "Nikon"))
+ {
+ if (buf[6] != '\2')
+ return;
+ base = ftell(ifp);
+ order = get2();
+ if (get2() != 42)
+ goto quit;
+ offset = get4();
+ fseek(ifp, INT64(offset) - 8LL, SEEK_CUR);
+ }
+ else
+ {
+ fseek(ifp, -10, SEEK_CUR);
+ }
+
+ entries = get2();
+ if (entries > 1000)
+ return;
+ morder = order;
+
+ while (entries--)
+ {
+ order = morder;
+ tiff_get(base, &tag, &type, &len, &save);
+
+ INT64 pos = ifp->tell();
+ if (len > 8 && pos + len > 2 * fsize)
+ {
+ fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
+ continue;
+ }
+ tag |= uptag << 16;
+ if (len > 100 * 1024 * 1024)
+ goto next; // 100Mb tag? No!
+
+ if (tag == 0x0002)
+ {
+ if (!iso_speed)
+ iso_speed = (get2(), get2());
+ }
+ else if (tag == 0x000a)
+ {
+ ilm.LensMount = ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if ((tag == 0x000c) && (len == 4) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_RATIONAL))
+ {
+ cam_mul[0] = getreal(type);
+ cam_mul[2] = getreal(type);
+ cam_mul[1] = getreal(type);
+ cam_mul[3] = getreal(type);
+ }
+ else if (tag == 0x0011)
+ {
+ if (is_raw)
+ {
+ fseek(ifp, get4() + base, SEEK_SET);
+ parse_tiff_ifd(base);
+ }
+ }
+ else if (tag == 0x0012)
+ {
+ uchar uc1 = fgetc(ifp);
+ uchar uc2 = fgetc(ifp);
+ uchar uc3 = fgetc(ifp);
+ if (uc3)
+ imCommon.FlashEC = (float)(uc1 * uc2) / (float)uc3;
+ }
+ else if (tag == 0x0014)
+ {
+ if (tagtypeIs(LIBRAW_EXIFTOOLTAGTYPE_binary))
+ {
+ if (len == 2560)
+ { // E5400, E8400, E8700, E8800
+ fseek(ifp, 0x4e0L, SEEK_CUR);
+ order = 0x4d4d;
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ cam_mul[1] = cam_mul[3] = 1.0;
+ icWBC[LIBRAW_WBI_Auto][0] = get2();
+ icWBC[LIBRAW_WBI_Auto][2] = get2();
+ icWBC[LIBRAW_WBI_Daylight][0] = get2();
+ icWBC[LIBRAW_WBI_Daylight][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Tungsten][0] = get2();
+ icWBC[LIBRAW_WBI_Tungsten][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_FL_W][0] = get2();
+ icWBC[LIBRAW_WBI_FL_W][2] = get2();
+ icWBC[LIBRAW_WBI_FL_N][0] = get2();
+ icWBC[LIBRAW_WBI_FL_N][2] = get2();
+ icWBC[LIBRAW_WBI_FL_D][0] = get2();
+ icWBC[LIBRAW_WBI_FL_D][2] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][0] = get2();
+ icWBC[LIBRAW_WBI_Cloudy][2] = get2();
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Flash][0] = get2();
+ icWBC[LIBRAW_WBI_Flash][2] = get2();
+
+ icWBC[LIBRAW_WBI_Auto][1] = icWBC[LIBRAW_WBI_Auto][3] =
+ icWBC[LIBRAW_WBI_Daylight][1] = icWBC[LIBRAW_WBI_Daylight][3] =
+ icWBC[LIBRAW_WBI_Tungsten][1] = icWBC[LIBRAW_WBI_Tungsten][3] =
+ icWBC[LIBRAW_WBI_FL_W][1] = icWBC[LIBRAW_WBI_FL_W][3] =
+ icWBC[LIBRAW_WBI_FL_N][1] = icWBC[LIBRAW_WBI_FL_N][3] =
+ icWBC[LIBRAW_WBI_FL_D][1] = icWBC[LIBRAW_WBI_FL_D][3] =
+ icWBC[LIBRAW_WBI_Cloudy][1] = icWBC[LIBRAW_WBI_Cloudy][3] =
+ icWBC[LIBRAW_WBI_Flash][1] = icWBC[LIBRAW_WBI_Flash][3] = 256;
+
+ if (strncmp(model, "E8700", 5))
+ {
+ fseek(ifp, 0x18L, SEEK_CUR);
+ icWBC[LIBRAW_WBI_Shade][0] = get2();
+ icWBC[LIBRAW_WBI_Shade][2] = get2();
+ icWBC[LIBRAW_WBI_Shade][1] = icWBC[LIBRAW_WBI_Shade][3] = 256;
+ }
+ }
+ else if (len == 1280)
+ { // E5000, E5700
+ cam_mul[0] = cam_mul[1] = cam_mul[2] = cam_mul[3] = 1.0;
+ }
+ else
+ {
+ fread(buf, 1, 10, ifp);
+ if (!strncmp(buf, "NRW ", 4))
+ { // P6000, P7000, P7100, B700, P1000
+ if (!strcmp(buf + 4, "0100"))
+ { // P6000
+ fseek(ifp, 0x13deL, SEEK_CUR);
+ cam_mul[0] = get4() << 1;
+ cam_mul[1] = get4();
+ cam_mul[3] = get4();
+ cam_mul[2] = get4() << 1;
+ Nikon_NRW_WBtag(LIBRAW_WBI_Daylight, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Cloudy, 0);
+ fseek(ifp, 0x10L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Tungsten, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_W, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Flash, 0);
+ fseek(ifp, 0x10L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Custom, 0);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 0);
+ }
+ else
+ { // P7000, P7100, B700, P1000
+ fseek(ifp, 0x16L, SEEK_CUR);
+ black = get2();
+ if (cam_mul[0] < 0.1f)
+ {
+ fseek(ifp, 0x16L, SEEK_CUR);
+ cam_mul[0] = get4() << 1;
+ cam_mul[1] = get4();
+ cam_mul[3] = get4();
+ cam_mul[2] = get4() << 1;
+ }
+ else
+ {
+ fseek(ifp, 0x26L, SEEK_CUR);
+ }
+ if (len != 332)
+ { // not A1000
+ Nikon_NRW_WBtag(LIBRAW_WBI_Daylight, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Cloudy, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Shade, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Tungsten, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_W, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_N, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_FL_D, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_HT_Mercury, 1);
+ fseek(ifp, 0x14L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Custom, 1);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 1);
+ }
+ else
+ {
+ fseek(ifp, 0xc8L, SEEK_CUR);
+ Nikon_NRW_WBtag(LIBRAW_WBI_Auto, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (tag == 0x001b)
+ {
+ imNikon.HighSpeedCropFormat = get2();
+ imNikon.SensorHighSpeedCrop.cwidth = get2();
+ imNikon.SensorHighSpeedCrop.cheight = get2();
+ imNikon.SensorWidth = get2();
+ imNikon.SensorHeight = get2();
+ imNikon.SensorHighSpeedCrop.cleft = get2();
+ imNikon.SensorHighSpeedCrop.ctop = get2();
+ switch (imNikon.HighSpeedCropFormat)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 11:
+ ilm.CameraFormat = LIBRAW_FORMAT_FF;
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 12:
+ ilm.CameraFormat = LIBRAW_FORMAT_APSC;
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
+ break;
+ case 3:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_5to4;
+ break;
+ case 6:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
+ break;
+ case 17:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
+ break;
+ default:
+ imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_OTHER;
+ break;
+ }
+ }
+ else if (tag == 0x001d)
+ { // serial number
+ if (len > 0)
+ {
+ int model_len = (int)strbuflen(model);
+ while ((c = fgetc(ifp)) && (len-- > 0) && (c != (unsigned)EOF))
+ {
+ if ((!custom_serial) && (!isdigit(c)))
+ {
+ if (((model_len == 3) && !strcmp(model, "D50")) ||
+ ((model_len >= 4) && !isalnum(model[model_len - 4]) &&
+ !strncmp(&model[model_len - 3], "D50", 3)))
+ {
+ custom_serial = 34;
+ }
+ else
+ {
+ custom_serial = 96;
+ }
+ break;
+ }
+ serial = serial * 10 + (isdigit(c) ? c - '0' : c % 10);
+ }
+ if (!imgdata.shootinginfo.BodySerial[0])
+ sprintf(imgdata.shootinginfo.BodySerial, "%d", serial);
+ }
+ }
+ else if (tag == 0x001e) {
+ switch (get2()) {
+ case 1:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
+ break;
+ case 2:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
+ break;
+ default:
+ imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
+ break;
+ }
+ } else if (tag == 0x0025)
+ {
+ imCommon.real_ISO = int(100.0 * libraw_powf64l(2.0, double((uchar)fgetc(ifp)) / 12.0 - 5.0));
+ if (!iso_speed || (iso_speed == 65535))
+ {
+ iso_speed = imCommon.real_ISO;
+ }
+ }
+ else if (tag == 0x0022)
+ {
+ imNikon.Active_D_Lighting = get2();
+ }
+ else if (tag == 0x003b)
+ { // WB for multi-exposure (ME); all 1s for regular exposures
+ imNikon.ME_WB[0] = getreal(type);
+ imNikon.ME_WB[2] = getreal(type);
+ imNikon.ME_WB[1] = getreal(type);
+ imNikon.ME_WB[3] = getreal(type);
+ }
+ else if (tag == 0x003d)
+ { // not corrected for file bitcount, to be patched in open_datastream
+ FORC4 cblack[RGGB_2_RGBG(c)] = get2();
+ i = cblack[3];
+ FORC3 if (i > cblack[c]) i = cblack[c];
+ FORC4 cblack[c] -= i;
+ black += i;
+ }
+ else if (tag == 0x0045)
+ { /* upper left pixel (x,y), size (width,height) */
+ imgdata.sizes.raw_inset_crops[0].cleft = get2();
+ imgdata.sizes.raw_inset_crops[0].ctop = get2();
+ imgdata.sizes.raw_inset_crops[0].cwidth = get2();
+ imgdata.sizes.raw_inset_crops[0].cheight = get2();
+ }
+ else if (tag == 0x0051)
+ {
+ fseek(ifp, 10LL, SEEK_CUR);
+ imNikon.NEFCompression = get2();
+ }
+ else if (tag == 0x0082)
+ { // lens attachment
+ stmread(ilm.Attachment, len, ifp);
+ }
+ else if (tag == 0x0083)
+ { // lens type
+ imgdata.lens.nikon.LensType = fgetc(ifp);
+ }
+ else if (tag == 0x0084)
+ { // lens
+ ilm.MinFocal = getreal(type);
+ ilm.MaxFocal = getreal(type);
+ ilm.MaxAp4MinFocal = getreal(type);
+ ilm.MaxAp4MaxFocal = getreal(type);
+ }
+ else if (tag == 0x0088) // AFInfo
+ {
+ if (!imCommon.afcount)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount = 1;
+ }
+ }
+ else if (tag == 0x008b) // lens f-stops
+ {
+ uchar uc1 = fgetc(ifp);
+ uchar uc2 = fgetc(ifp);
+ uchar uc3 = fgetc(ifp);
+ if (uc3)
+ {
+ imgdata.lens.nikon.LensFStops = uc1 * uc2 * (12 / uc3);
+ ilm.LensFStops = (float)imgdata.lens.nikon.LensFStops / 12.0f;
+ }
+ }
+ else if ((tag == 0x008c) || (tag == 0x0096))
+ {
+ meta_offset = ftell(ifp);
+ }
+ else if ((tag == 0x0091) && (len > 4))
+ {
+ ShotInfo_len = len;
+ ShotInfo_buf = (uchar *)malloc(ShotInfo_len);
+
+/* for dump:
+cj_block = (uchar *)malloc(ShotInfo_len);
+ck_block = (uchar *)malloc(ShotInfo_len);
+*/
+
+ fread(ShotInfo_buf, ShotInfo_len, 1, ifp);
+ FORC4 imNikon.ShotInfoVersion =
+ imNikon.ShotInfoVersion * 10 + ShotInfo_buf[c] - '0';
+ }
+ else if (tag == 0x0093)
+ {
+ imNikon.NEFCompression = i = get2();
+ if ((i == 7) || (i == 9))
+ {
+ ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.CameraMount = LIBRAW_MOUNT_FixedLens;
+ }
+ }
+ else if (tag == 0x0097)
+ { // ver97
+ FORC4 imNikon.ColorBalanceVersion =
+ imNikon.ColorBalanceVersion * 10 + fgetc(ifp) - '0';
+ switch (imNikon.ColorBalanceVersion)
+ {
+ case 100: // NIKON D100
+ fseek(ifp, 0x44L, SEEK_CUR);
+ FORC4 cam_mul[RBGG_2_RGBG(c)] = get2();
+ break;
+ case 102: // NIKON D2H
+ fseek(ifp, 0x6L, SEEK_CUR);
+ FORC4 cam_mul[RGGB_2_RGBG(c)] = get2();
+ break;
+ case 103: // NIKON D70, D70s
+ fseek(ifp, 0x10L, SEEK_CUR);
+ FORC4 cam_mul[c] = get2();
+ }
+ if (imNikon.ColorBalanceVersion >= 200)
+ {
+ /*
+ 204: NIKON D2X, D2Xs
+ 205: NIKON D50
+ 206: NIKON D2Hs
+ 207: NIKON D200
+ 208: NIKON D40, D40X, D80
+ 209: NIKON D3, D3X, D300, D700
+ 210: NIKON D60
+ 211: NIKON D90, D5000
+ 212: NIKON D300S
+ 213: NIKON D3000
+ 214: NIKON D3S
+ 215: NIKON D3100
+ 216: NIKON D5100, D7000
+ 217: NIKON D4, D600, D800, D800E, D3200
+ -= unknown =-
+ 218: NIKON D5200, D7100
+ 219: NIKON D5300
+ 220: NIKON D610, Df
+ 221: NIKON D3300
+ 222: NIKON D4S
+ 223: NIKON D750, D810
+ 224: NIKON D3400, D3500, D5500, D5600, D7200
+ 225: NIKON D5, D500
+ 226: NIKON D7500
+ 227: NIKON D850
+ */
+ if (imNikon.ColorBalanceVersion != 205)
+ {
+ fseek(ifp, 0x118L, SEEK_CUR);
+ }
+ ColorBalanceData_ready =
+ (fread(ColorBalanceData_buf, 324, 1, ifp) == 1);
+ }
+ if ((imNikon.ColorBalanceVersion >= 400) &&
+ (imNikon.ColorBalanceVersion <= 405))
+ { // 1 J1, 1 V1, 1 J2, 1 V2, 1 J3, 1 S1, 1 AW1, 1 S2, 1 J4, 1 V3, 1 J5
+ ilm.CameraFormat = LIBRAW_FORMAT_1INCH;
+ ilm.CameraMount = LIBRAW_MOUNT_Nikon_CX;
+ }
+ else if ((imNikon.ColorBalanceVersion >= 500) &&
+ (imNikon.ColorBalanceVersion <= 502))
+ { // P7700, P7800, P330, P340
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
+ }
+ else if (imNikon.ColorBalanceVersion == 601)
+ { // Coolpix A
+ ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
+ ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
+ ilm.FocalType = LIBRAW_FT_PRIME_LENS;
+ }
+ }
+ else if (tag == 0x0098) // contains lens data
+ {
+ FORC4 imNikon.LensDataVersion =
+ imNikon.LensDataVersion * 10 + fgetc(ifp) - '0';
+ switch (imNikon.LensDataVersion)
+ {
+ case 100:
+ LensData_len = 9;
+ break;
+ case 101:
+ case 201: // encrypted, starting from v.201
+ case 202:
+ case 203:
+ LensData_len = 15;
+ break;
+ case 204:
+ LensData_len = 16;
+ break;
+ case 400:
+ LensData_len = 459;
+ break;
+ case 401:
+ LensData_len = 590;
+ break;
+ case 402:
+ LensData_len = 509;
+ break;
+ case 403:
+ LensData_len = 879;
+ break;
+ case 800:
+ case 801:
+ LensData_len = 58;
+ break;
+ case 802:
+ LensData_len = 108;
+ break;
+ }
+ if (LensData_len)
+ {
+ LensData_buf = (uchar *)malloc(LensData_len);
+ fread(LensData_buf, LensData_len, 1, ifp);
+ }
+ }
+ else if (tag == 0x00a0)
+ {
+ stmread(imgdata.shootinginfo.BodySerial, len, ifp);
+ }
+ else if (tag == 0x00a7) // shutter count
+ {
+ imNikon.key = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp);
+ if (custom_serial)
+ {
+ ci = xlat[0][custom_serial];
+ }
+ else
+ {
+ ci = xlat[0][serial & 0xff];
+ }
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ if (((unsigned)(imNikon.ColorBalanceVersion - 200) < 18) &&
+ ColorBalanceData_ready)
+ {
+ for (i = 0; i < 324; i++)
+ ColorBalanceData_buf[i] ^= (cj += ci * ck++);
+ i = "66666>666;6A;:;555"[imNikon.ColorBalanceVersion - 200] - '0';
+ FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+ sget2(ColorBalanceData_buf + (i & -2) + c * 2);
+ }
+
+ if (LensData_len)
+ {
+ if (imNikon.LensDataVersion > 200)
+ {
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ for (i = 0; i < LensData_len; i++)
+ {
+ LensData_buf[i] ^= (cj += ci * ck++);
+ }
+ }
+ processNikonLensData(LensData_buf, LensData_len);
+ LensData_len = 0;
+ free(LensData_buf);
+ }
+ if (ShotInfo_len && (imNikon.ShotInfoVersion >= 208)) {
+ unsigned RotationOffset = 0,
+ OrientationOffset = 0;
+
+ cj = xlat[1][imNikon.key];
+ ck = 0x60;
+ for (i = 4; i < ShotInfo_len; i++) {
+ ShotInfo_buf[i] ^= (cj += ci * ck++);
+
+/* for dump:
+cj_block[i-4] = cj;
+ck_block[i-4] = ck-1;
+*/
+ }
+/* for dump:
+printf ("==>> ci: 0x%02x, cj at start: 0x%02x\n",
+ci, xlat[1][imNikon.key]);
+hexDump("ck array:", ck_block, ShotInfo_len-4);
+hexDump("cj array:", cj_block, ShotInfo_len-4);
+free(cj_block);
+free(ck_block);
+*/
+
+ switch (imNikon.ShotInfoVersion) {
+ case 208: // ShotInfoD80, Rotation
+ RotationOffset = 590;
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = *(ShotInfo_buf+RotationOffset) & 0x07;
+ }
+ break;
+
+ case 231: // ShotInfoD4S, Rotation, Roll/Pitch/Yaw
+ OrientationOffset = 0x350b;
+ RotationOffset = 0x3693;
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = (*(ShotInfo_buf+RotationOffset)>>4) & 0x03;
+ }
+ break;
+
+ case 233: // ShotInfoD810, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x84);
+ break;
+
+ case 238: // D5, ShotInfoD500, Rotation, Roll/Pitch/Yaw
+ case 239: // D500, ShotInfoD500, Rotation, Roll/Pitch/Yaw
+ RotationOffset = sget4_order(morder, ShotInfo_buf+0x10) + 0xca;
+ if (RotationOffset > 0xca) {
+ RotationOffset -= 0xb0;
+ }
+ if (RotationOffset<ShotInfo_len) {
+ imNikon.MakernotesFlip = *(ShotInfo_buf+RotationOffset) & 0x03;
+ }
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0xa0);
+ break;
+
+ case 243: // ShotInfoD850, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0xa0);
+ break;
+
+ case 246: // ShotInfoD6, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x9c);
+ break;
+
+ case 800: // Z 6, Z 7, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 801: // Z 50, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 802: // Z 5, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 803: // Z 6_2, Z 7_2, ShotInfoZ7II, Roll/Pitch/Yaw
+ case 804: // Z fc ShotInfoZ7II, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x98);
+ break;
+
+ case 805: // Z 9, ShotInfoZ9, Roll/Pitch/Yaw
+ OrientationOffset = sget4_order(morder, ShotInfo_buf+0x84);
+ break;
+ }
+
+ if (OrientationOffset && ((OrientationOffset+12)<ShotInfo_len) && OrientationOffset < 0xffff) {
+ if (imNikon.ShotInfoVersion == 231) // ShotInfoD4S
+ imNikon.RollAngle = AngleConversion_a(morder, ShotInfo_buf+OrientationOffset);
+ else
+ imNikon.RollAngle = AngleConversion(morder, ShotInfo_buf+OrientationOffset);
+ imNikon.PitchAngle = AngleConversion (morder, ShotInfo_buf+OrientationOffset+4);
+ imNikon.YawAngle = AngleConversion (morder, ShotInfo_buf+OrientationOffset+8);
+ }
+ if ((RotationOffset) && (imNikon.MakernotesFlip < 4) && (imNikon.MakernotesFlip >= 0))
+ imNikon.MakernotesFlip = "0863"[imNikon.MakernotesFlip] - '0';
+ ShotInfo_len = 0;
+ free(ShotInfo_buf);
+ }
+ }
+ else if (tag == 0x00a8)
+ { // contains flash data
+ FORC4 imNikon.FlashInfoVersion =
+ imNikon.FlashInfoVersion * 10 + fgetc(ifp) - '0';
+ }
+ else if (tag == 0x00b0)
+ {
+ get4(); // ME (multi-exposure) tag version, 4 symbols
+ imNikon.ExposureMode = get4();
+ imNikon.nMEshots = get4();
+ imNikon.MEgainOn = get4();
+ }
+ else if (tag == 0x00b7) // AFInfo2
+ {
+ if (!imCommon.afcount && len > 4)
+ {
+ imCommon.afdata[imCommon.afcount].AFInfoData_tag = tag;
+ imCommon.afdata[imCommon.afcount].AFInfoData_order = order;
+ int ver = 0;
+ FORC4 ver = ver * 10 + (fgetc(ifp) - '0');
+ imCommon.afdata[imCommon.afcount].AFInfoData_version = ver;
+ imCommon.afdata[imCommon.afcount].AFInfoData_length = len-4;
+ imCommon.afdata[imCommon.afcount].AFInfoData = (uchar *)malloc(imCommon.afdata[imCommon.afcount].AFInfoData_length);
+ fread(imCommon.afdata[imCommon.afcount].AFInfoData, imCommon.afdata[imCommon.afcount].AFInfoData_length, 1, ifp);
+ imCommon.afcount = 1;
+ }
+ }
+ else if (tag == 0x00b9)
+ {
+ imNikon.AFFineTune = fgetc(ifp);
+ imNikon.AFFineTuneIndex = fgetc(ifp);
+ imNikon.AFFineTuneAdj = (int8_t)fgetc(ifp);
+ }
+ else if ((tag == 0x0100) && tagtypeIs(LIBRAW_EXIFTAG_TYPE_UNDEFINED))
+ {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ else if (tag == 0x0e01)
+ { /* Nikon Software / in-camera edit Note */
+ int loopc = 0;
+ int WhiteBalanceAdj_active = 0;
+ order = 0x4949;
+ fseek(ifp, 22, SEEK_CUR);
+ for (offset = 22; offset + 22 < len; offset += 22 + i)
+ {
+ if (loopc++ > 1024)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ tag = get4();
+ fseek(ifp, 14, SEEK_CUR);
+ i = get4() - 4;
+
+ if (tag == 0x76a43204)
+ {
+ WhiteBalanceAdj_active = fgetc(ifp);
+ }
+ else if (tag == 0xbf3c6c20)
+ {
+ if (WhiteBalanceAdj_active)
+ {
+ union {
+ double dbl;
+ unsigned long long lng;
+ } un;
+ un.dbl = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
+ if ((un.lng != 0x3FF0000000000000ULL) &&
+ (un.lng != 0x000000000000F03FULL))
+ {
+ cam_mul[0] = un.dbl;
+ cam_mul[2] = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
+ cam_mul[1] = cam_mul[3] = 1.0;
+ i -= 16;
+ }
+ else
+ i -= 8;
+ }
+ fseek(ifp, i, SEEK_CUR);
+ }
+ else if (tag == 0x76a43207)
+ {
+ flip = get2();
+ }
+ else
+ {
+ fseek(ifp, i, SEEK_CUR);
+ }
+ }
+ }
+ else if (tag == 0x0e22)
+ {
+ FORC4 imNikon.NEFBitDepth[c] = get2();
+ }
+ next:
+ fseek(ifp, save, SEEK_SET);
+ }
+quit:
+ order = sorder;
+}
+
+unsigned sget4_order (short _order, uchar *s) {
+ unsigned v;
+ if (_order == 0x4949)
+ v= s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ else
+ v= s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+ return v;
+}
+
+double sget_fixed32u (short _order, uchar *s) {
+ unsigned v = sget4_order (_order, s);
+ return ((double)v / 6.5536 + 0.5) / 10000.0;
+}
+
+double AngleConversion_a (short _order, uchar *s) {
+ double v = sget_fixed32u(_order, s);
+ if (v < 180.0) return -v;
+ return 360.0-v;
+}
+
+double AngleConversion (short _order, uchar *s) {
+ double v = sget_fixed32u(_order, s);
+ if (v <= 180.0) return v;
+ return v-360.0;
+}
+
+/* ========= */
+/*
+void hexDump(char *title, void *addr, int len)
+{
+ int i;
+ unsigned char buff[17];
+ unsigned char *pc = (unsigned char*)addr;
+
+ // Output description if given.
+ if (title != NULL)
+ printf ("%s:\n", title);
+
+ // Process every byte in the data.
+ for (i = 0; i < len; i++) {
+ // Multiple of 16 means new line (with line offset).
+
+ if ((i % 16) == 0) {
+ // Just don't print ASCII for the zeroth line.
+ if (i != 0)
+ printf(" %s\n", buff);
+
+ // Output the offset.
+ printf(" %04x ", i);
+ }
+
+ // Now the hex code for the specific character.
+ printf(" %02x", pc[i]);
+
+ // And store a printable ASCII character for later.
+ if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
+ buff[i % 16] = '.';
+ } else {
+ buff[i % 16] = pc[i];
+ }
+
+ buff[(i % 16) + 1] = '\0';
+ }
+
+ // Pad out last line if not exactly 16 characters.
+ while ((i % 16) != 0) {
+ printf(" ");
+ i++;
+ }
+
+ // And print the final ASCII bit.
+ printf(" %s\n", buff);
+}
+*/