blob: aa1f352b8970623cf2cc66e30eca93c5cdaa078b [file]
/* -*- C++ -*-
* Copyright 2019-2025 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 "third_party/libraw/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", "Z 30", "Z 8", "Z6_2"
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.LensID == 41)
|| (ilm.LensID == 43)
|| (ilm.LensID == 0xd003)
) 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(INT64 base, int uptag, unsigned /*dng_writer */)
{
unsigned offset = 0, entries, tag, type, len;
INT64 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] = {0,0,0,0,0,0,0,0,0,0};
INT64 fsize = ifp->size();
fread(buf, 1, 10, ifp);
buf[9] = 0;
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 (callbacks.makernotes_cb)
{
INT64 _savepos = ifp->tell();
callbacks.makernotes_cb(callbacks.makernotesparser_data, tag, type, len, order, ifp, base);
fseek(ifp, _savepos, SEEK_SET);
}
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] = getrealf(type);
cam_mul[2] = getrealf(type);
cam_mul[1] = getrealf(type);
cam_mul[3] = getrealf(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] = float(get2()) / 256.f;
cam_mul[2] = float(get2()) / 256.f;
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
{
memset(buf,0,sizeof(buf));
fread(buf, 1, 10, ifp);
buf[9] = 0;
if (!strncmp(buf, "NRW ", 4))
{ // P6000, P7000, P7100, B700, P1000
if (!strcmp(buf + 4, "0100"))
{ // P6000
fseek(ifp, 0x13deL, SEEK_CUR);
cam_mul[0] = float(get4() << 1);
cam_mul[1] = float(get4());
cam_mul[3] = float(get4());
cam_mul[2] = float(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] = float(get4() << 1);
cam_mul[1] = float(get4());
cam_mul[3] = float(get4());
cam_mul[2] = float(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;
case 4:
imCommon.ColorSpace = LIBRAW_COLORSPACE_Rec2020;
break;
default:
imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
break;
}
} else if (tag == 0x0025)
{
imCommon.real_ISO = float(100.f * float(libraw_powf64l(2.f, float((uchar)fgetc(ifp)) / 12.f - 5.f)));
if (!iso_speed || (iso_speed == 65535))
{
iso_speed = imCommon.real_ISO;
}
}
else if (tag == 0x0022)
{
imNikon.Active_D_Lighting = get2();
}
else if (tag == 0x0023)
{
FORC4 imNikon.PictureControlVersion =
imNikon.PictureControlVersion * 10 + fgetc(ifp) - '0';
if ((imNikon.PictureControlVersion >= 300) &&
(imNikon.PictureControlVersion <= 399))
{
fseek(ifp, 4, SEEK_CUR);
}
stmread (imNikon.PictureControlName, 20, ifp);
stmread (imNikon.PictureControlBase, 20, ifp);
if (!strncmp(imNikon.PictureControlBase, "STANDARD(HLG)", 13))
{
imCommon.ExposureCalibrationShift -= 2;
}
}
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();
}
// BurstTable_0x0056
/*
photo shooting menu -> [Pixel shift shooting] :
[Pixel shift shooting mode] : On(series) | On(single photo) | Off (default is Off)
[Number of shots] : 4 | 8 | 16 | 32 (default is 16)
[Delay] : (default is 2 s)
[Interval until next shot] : (default is 0)
*/
else if ((tag == 0x0056) && !strncmp(model+6, "Z ", 2))
{
imNikon.BurstTable_0x0056_len = len;
if (imNikon.BurstTable_0x0056_len == 16) {
imNikon.BurstTable_0x0056 = (uchar *)calloc(imNikon.BurstTable_0x0056_len+1,1);
fread(imNikon.BurstTable_0x0056, imNikon.BurstTable_0x0056_len, 1, ifp);
FORC4 imNikon.BurstTable_0x0056_ver = imNikon.BurstTable_0x0056_ver * 10 + (imNikon.BurstTable_0x0056[c] - '0');
imNikon.BurstTable_0x0056_gid = (imNikon.BurstTable_0x0056[5]<<8) | imNikon.BurstTable_0x0056[4];
imNikon.BurstTable_0x0056_fnum = imNikon.BurstTable_0x0056[8];
/*
printf (">> camera: %s; BurstTable_0x0056: len %d, ver %d, gid 0x%04x, fnum %d\n",
model, imNikon.BurstTable_0x0056_len, imNikon.BurstTable_0x0056_ver, imNikon.BurstTable_0x0056_gid, imNikon.BurstTable_0x0056_fnum);
printf (" 0x6: 0x%02x 0x7: 0x%02x\n 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
imNikon.BurstTable_0x0056[0x6], imNikon.BurstTable_0x0056[0x7],
imNikon.BurstTable_0x0056[0x9], imNikon.BurstTable_0x0056[0xa],
imNikon.BurstTable_0x0056[0xb], imNikon.BurstTable_0x0056[0xc],
imNikon.BurstTable_0x0056[0xd], imNikon.BurstTable_0x0056[0xe],
imNikon.BurstTable_0x0056[0xf]);
printf ("BurstTable_0x0056[5 .. 4]: ");
for (c = 1 << 7; c > 0; c = c / 2)
(imNikon.BurstTable_0x0056[5] & c) ? printf("1") : printf("0");
printf (" ");
for (c = 1 << 7; c > 0; c = c / 2)
(imNikon.BurstTable_0x0056[4] & c) ? printf("1") : printf("0");
printf ("\n");
printf ("BurstTable_0x0056[7 .. 6]: ");
for (c = 1 << 7; c > 0; c = c / 2)
(imNikon.BurstTable_0x0056[7] & c) ? printf("1") : printf("0");
printf (" ");
for (c = 1 << 7; c > 0; c = c / 2)
(imNikon.BurstTable_0x0056[6] & c) ? printf("1") : printf("0");
printf ("\n");
*/
}
/*
else {
printf (">> camera: =%s=; table 0x0056 len!=16, len %d\n", model, len);
}
*/
}
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 = getrealf(type);
ilm.MaxFocal = getrealf(type);
ilm.MaxAp4MinFocal = getrealf(type);
ilm.MaxAp4MaxFocal = getrealf(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 *)calloc(imCommon.afdata[imCommon.afcount].AFInfoData_length+1,1);
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 *)calloc(ShotInfo_len+1,1);
/* 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 *)calloc(LensData_len+1,1);
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;
case 806: // "Z 8"
if (ShotInfo_len >= 12) {
memcpy (imNikon.ShotInfoFirmware, ShotInfo_buf+4, 8*sizeof(char));
imNikon.ShotInfoFirmware[8] = '\0';
// printf (">> camera: =%s= exifSW: =%s= ShotInfo: Version %d, Firmware =%s=\n",
// model, software, imNikon.ShotInfoVersion, imNikon.ShotInfoFirmware);
}
break;
case 807: // "Z 30"
break;
case 808: // "Z f"
if (ShotInfo_len >= 12) {
memcpy (imNikon.ShotInfoFirmware, ShotInfo_buf+4, 8*sizeof(char));
imNikon.ShotInfoFirmware[8] = '\0';
// printf (">> camera: =%s= exifSW: =%s= ShotInfo: Version %d, Firmware =%s=\n",
// model, software, imNikon.ShotInfoVersion, imNikon.ShotInfoFirmware);
}
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 *)calloc(imCommon.afdata[imCommon.afcount].AFInfoData_length+1,1);
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] = float(un.dbl);
cam_mul[2] = getrealf(LIBRAW_EXIFTAG_TYPE_DOUBLE);
cam_mul[1] = cam_mul[3] = 1.f;
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);
}
*/