blob: 7c3e8859ae39d61ee0a9368f4c8ee03b54f6dee5 [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 LibRaw::Kodak_KDC_WBtags(int wb, int wbi)
{
int c;
FORC3 icWBC[wb][c] = get4();
icWBC[wb][3] = icWBC[wb][1];
if (wbi == wb)
FORC4 cam_mul[c] = float(icWBC[wb][c]);
return;
}
void LibRaw::Kodak_DCR_WBtags(int wb, unsigned type, int wbi)
{
float mul[3] = {1.0f, 1.0f, 1.0f}, num, mul2;
int c;
FORC3 mul[c] = (num = getrealf(type)) <= 0.001f ? 1.0f : num;
icWBC[wb][1] = icWBC[wb][3] = int(mul[1]);
mul2 = mul[1] * mul[1];
icWBC[wb][0] = int(mul2 / mul[0]);
icWBC[wb][2] = int(mul2 / mul[2]);
if (wbi == wb)
FORC4 cam_mul[c] = float(icWBC[wb][c]);
return;
}
short LibRaw::KodakIllumMatrix(unsigned type, float *romm_camIllum)
{
int c, j, romm_camTemp[9], romm_camScale[3];
if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL))
{
for (j = 0; j < 9; j++)
((float *)romm_camIllum)[j] = getrealf(type);
return 1;
}
else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SLONG))
{
FORC3
{
romm_camScale[c] = 0;
for (j = 0; j < 3; j++)
{
romm_camTemp[c * 3 + j] = get4();
romm_camScale[c] += romm_camTemp[c * 3 + j];
}
}
if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) &&
(romm_camScale[2] > 0x1fff))
{
FORC3 for (j = 0; j < 3; j++)((float *)romm_camIllum)[c * 3 + j] =
((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]);
return 1;
}
}
return 0;
}
/* Thanks to Alexey Danilchenko for wb as-shot parsing code */
void LibRaw::parse_kodak_ifd(INT64 base)
{
unsigned entries, tag, type, len;
INT64 save;
int c, wbi = -1;
static const int wbtag_kdc[] = {
LIBRAW_WBI_Auto, // 64037 / 0xfa25
LIBRAW_WBI_Fluorescent, // 64040 / 0xfa28
LIBRAW_WBI_Tungsten, // 64039 / 0xfa27
LIBRAW_WBI_Daylight, // 64041 / 0xfa29
-1,
-1,
LIBRAW_WBI_Shade // 64042 / 0xfa2a
};
static const int wbtag_dcr[] = {
LIBRAW_WBI_Daylight, // 2120 / 0x0848
LIBRAW_WBI_Tungsten, // 2121 / 0x0849
LIBRAW_WBI_Fluorescent, // 2122 / 0x084a
LIBRAW_WBI_Flash, // 2123 / 0x084b
LIBRAW_WBI_Custom, // 2124 / 0x084c
LIBRAW_WBI_Auto // 2125 / 0x084d
};
// int a_blck = 0;
entries = get2();
if (entries > 1024)
return;
INT64 fsize = ifp->size();
while (entries--)
{
tiff_get(base, &tag, &type, &len, &save);
INT64 savepos = ftell(ifp);
if (len > 8 && len + savepos > 2 * fsize)
{
fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
continue;
}
if (callbacks.exif_cb)
{
callbacks.exif_cb(callbacks.exifparser_data, tag | 0x20000, type, len,
order, ifp, base);
fseek(ifp, savepos, SEEK_SET);
}
if (tag == 0x03eb) // 1003
imgdata.sizes.raw_inset_crops[0].cleft = get2();
else if (tag == 0x03ec) // 1004
imgdata.sizes.raw_inset_crops[0].ctop = get2();
else if (tag == 0x03ed) // 1005
imgdata.sizes.raw_inset_crops[0].cwidth = get2();
else if (tag == 0x03ee) // 1006
imgdata.sizes.raw_inset_crops[0].cheight = get2();
else if (tag == 0x03ef) // 1007
{
if (!strcmp(model, "EOS D2000C"))
black = get2();
else
imKodak.BlackLevelTop = get2();
}
else if (tag == 0x03f0) // 1008
{
if (!strcmp(model, "EOS D2000C"))
{
if (black) // already set by tag 1007 (0x03ef)
black = (black + get2()) / 2;
else
black = get2();
}
else
imKodak.BlackLevelBottom = get2();
}
else if (tag == 0x03f1)
{ // 1009 Kodak TextualInfo
if (len > 0)
{
char kti[1024];
char *pkti;
int nsym = MIN(len, 1023);
fread(kti, 1, nsym, ifp);
kti[nsym] = 0;
#ifdef LIBRAW_WIN32_CALLS
pkti = strtok(kti, "\x0a");
#else
char *last = 0;
pkti = strtok_r(kti, "\x0a", &last);
#endif
while (pkti != NULL)
{
c = 12;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Camera body:", c)))
{
while ((pkti[c] == ' ') && (c < (int)strlen(pkti)))
{
c++;
}
strcpy(ilm.body, pkti + c);
}
c = 5;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Lens:", c)))
{
ilm.CurFocal = float(atoi(pkti + c));
}
c = 9;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Aperture:", c)))
{
while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
{
c++;
}
ilm.CurAp = float(atof(pkti + c));
}
c = 10;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "ISO Speed:", c)))
{
iso_speed = float(atoi(pkti + c));
}
c = 13;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Focal Length:", c)))
{
ilm.CurFocal = float(atoi(pkti + c));
}
c = 13;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Max Aperture:", c)))
{
while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
{
c++;
}
ilm.MaxAp4CurFocal = float(atof(pkti + c));
}
c = 13;
if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Min Aperture:", c)))
{
while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti)))
{
c++;
}
ilm.MinAp4CurFocal = float(atof(pkti + c));
}
#ifdef LIBRAW_WIN32_CALLS
pkti = strtok(NULL, "\x0a");
#else
pkti = strtok_r(NULL, "\x0a", &last);
#endif
}
}
}
else if (tag == 0x03f3) // 1011
imCommon.FlashEC = getrealf(type);
else if (tag == 0x03fc) // 1020
{
wbi = getint(type);
if ((wbi >= 0) && (wbi < 6) && (wbi != -2))
wbi = wbtag_dcr[wbi];
}
else if (tag == 0x03fd && len == 72) // 1021
{ /* WB set in software */
fseek(ifp, 40, SEEK_CUR);
FORC3 cam_mul[c] = 2048.0f / fMAX(1.0f, get2());
wbi = -2;
}
else if ((tag == 0x0406) && (len == 1)) // 1030
imCommon.CameraTemperature = getrealf(type);
else if ((tag == 0x0413) && (len == 1)) // 1043
imCommon.SensorTemperature = getrealf(type);
else if (tag == 0x0848) // 2120
Kodak_DCR_WBtags(LIBRAW_WBI_Daylight, type, wbi);
else if (tag == 0x0849) // 2121
Kodak_DCR_WBtags(LIBRAW_WBI_Tungsten, type, wbi);
else if (tag == 0x084a) // 2122
Kodak_DCR_WBtags(LIBRAW_WBI_Fluorescent, type, wbi);
else if (tag == 0x084b) // 2123
Kodak_DCR_WBtags(LIBRAW_WBI_Flash, type, wbi);
else if (tag == 0x084c) // 2124
Kodak_DCR_WBtags(LIBRAW_WBI_Custom, type, wbi);
else if (tag == 0x084d) // 2125
{
if (wbi == -1)
wbi = LIBRAW_WBI_Auto;
Kodak_DCR_WBtags(LIBRAW_WBI_Auto, type, wbi);
}
else if (tag == 0x089f) // 2207
imKodak.ISOCalibrationGain = getrealf(type);
else if (tag == 0x0903) // 2307
imKodak.AnalogISO = iso_speed = getrealf(type);
else if (tag == 0x090d) // 2317
linear_table(len);
else if (tag == 0x09ce) // 2510
stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp);
else if (tag == 0x0e92) // 3730
{
imKodak.val018percent = get2();
imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
(int)(((float)imKodak.val018percent) / 18.0f * 170.0f);
}
else if (tag == 0x0e93) // 3731
imgdata.color.linear_max[0] = imgdata.color.linear_max[1] =
imgdata.color.linear_max[2] = imgdata.color.linear_max[3] =
imKodak.val170percent = get2();
else if (tag == 0x0e94) // 3732
imKodak.val100percent = get2();
/*
else if (tag == 0x1784) // 6020
iso_speed = getint(type);
*/
else if (tag == 0xfa00) // 64000
stmread(imgdata.shootinginfo.BodySerial, len, ifp);
else if (tag == 0xfa0d) // 64013
{
wbi = fgetc(ifp);
if ((wbi >= 0) && (wbi < 7))
wbi = wbtag_kdc[wbi];
}
else if (tag == 0xfa13) // 64019
width = getint(type);
else if (tag == 0xfa14) // 64020
height = (getint(type) + 1) & -2;
/*
height = getint(type);
else if (tag == 0xfa16) // 64022
raw_width = get2();
else if (tag == 0xfa17) // 64023
raw_height = get2();
*/
else if (tag == 0xfa18) // 64024
{
imKodak.offset_left = getint(LIBRAW_EXIFTAG_TYPE_SSHORT);
if (type != LIBRAW_EXIFTAG_TYPE_SSHORT)
imKodak.offset_left += 1;
}
else if (tag == 0xfa19) // 64025
{
imKodak.offset_top = getint(LIBRAW_EXIFTAG_TYPE_SSHORT);
if (type != LIBRAW_EXIFTAG_TYPE_SSHORT)
imKodak.offset_top += 1;
}
else if (tag == 0xfa25) // 64037
Kodak_KDC_WBtags(LIBRAW_WBI_Auto, wbi);
else if (tag == 0xfa27) // 64039
Kodak_KDC_WBtags(LIBRAW_WBI_Tungsten, wbi);
else if (tag == 0xfa28) // 64040
Kodak_KDC_WBtags(LIBRAW_WBI_Fluorescent, wbi);
else if (tag == 0xfa29) // 64041
Kodak_KDC_WBtags(LIBRAW_WBI_Daylight, wbi);
else if (tag == 0xfa2a) // 64042
Kodak_KDC_WBtags(LIBRAW_WBI_Shade, wbi);
else if (tag == 0xfa31) // 64049
imgdata.sizes.raw_inset_crops[0].cwidth = get2();
else if (tag == 0xfa32) // 64050
imgdata.sizes.raw_inset_crops[0].cheight = get2();
else if (tag == 0xfa3e) // 64062
imgdata.sizes.raw_inset_crops[0].cleft = get2();
else if (tag == 0xfa3f) // 64063
imgdata.sizes.raw_inset_crops[0].ctop = get2();
else if (((tag == 0x07e4) || (tag == 0xfb01)) &&
(len == 9)) // 2020 or 64257
{
if (KodakIllumMatrix(type, (float *)imKodak.romm_camDaylight))
{
romm_coeff(imKodak.romm_camDaylight);
}
}
else if (((tag == 0x07e5) || (tag == 0xfb02)) &&
(len == 9)) // 2021 or 64258
KodakIllumMatrix(type, (float *)imKodak.romm_camTungsten);
else if (((tag == 0x07e6) || (tag == 0xfb03)) &&
(len == 9)) // 2022 or 64259
KodakIllumMatrix(type, (float *)imKodak.romm_camFluorescent);
else if (((tag == 0x07e7) || (tag == 0xfb04)) &&
(len == 9)) // 2023 or 64260
KodakIllumMatrix(type, (float *)imKodak.romm_camFlash);
else if (((tag == 0x07e8) || (tag == 0xfb05)) &&
(len == 9)) // 2024 or 64261
KodakIllumMatrix(type, (float *)imKodak.romm_camCustom);
else if (((tag == 0x07e9) || (tag == 0xfb06)) &&
(len == 9)) // 2025 or 64262
KodakIllumMatrix(type, (float *)imKodak.romm_camAuto);
fseek(ifp, save, SEEK_SET);
}
}