Added Hasselblad model identification in rtexif

This commit is contained in:
torger
2015-01-10 14:16:01 +01:00
parent 3548a1783a
commit 8c52d6e3d7
2 changed files with 110 additions and 0 deletions

View File

@@ -2021,6 +2021,115 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) {
parse_leafdata(root, order);
if (make && !strncmp((char*)make->getValue(), "Hasselblad", 10)) {
/*
Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly
different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through
Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and
Phocus-generated DNGs.
FFF usually has a sane model name in Model (and is used as reference for what we shall
call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for
all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body.
V-mount backs may have the model name of the V body instead of the back model. Etc...
as said it's a mess.
This code is supposed to handle all raw containers and end up with the same model
regardless of container.
We don't differ between single shot and multi-shot models, and probably there's no use
of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that
tethered. In single-shot mode they should be exactly the same as the single-shot models.
*/
Tag *subd = root->getTag(0x14a);
Tag *iw = (subd) ? subd->getDirectory()->getTag("ImageWidth") : 0;
int sensorWidth = (iw) ? iw->toInt() : 0;
Tag* tmodel = root->getTag ("Model");
const char *model = (tmodel) ? (const char *)tmodel->getValue() : "";
if (strstr(model, "Hasselblad ") == model) {
model += 11;
} else {
// if HxD is used in flash sync mode for example, we need to fetch model from this tag
Tag* tmodel3 = root->getTag("UniqueCameraModel");
const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : "";
if (strstr(model3, "Hasselblad ") == model3) {
model = model3 + 11;
}
}
// FIXME: due to lack of test files this Hasselblad model identification is not 100% complete
// This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models
if (!strcmp(model, "H3D")) {
// We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a
// H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance
// to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50
// H3D-50 although Hasselblad never released such a model.
switch (sensorWidth) {
case 4096: tmodel->initString("H3D-22"); break;
case 6542: tmodel->initString("H3D-31"); break;
case 7262: tmodel->initString("H3D-39"); break;
case 8282: tmodel->initString("H3DII-50"); break;
}
} else if (!strcmp(model, "H4D")) {
switch (sensorWidth) {
case 6542: tmodel->initString("H4D-31"); break;
case 7410: tmodel->initString("H4D-40"); break;
case 8282: tmodel->initString("H4D-50"); break;
case 9044: tmodel->initString("H4D-60"); break;
}
} else if (!strcmp(model, "H5D")) {
switch (sensorWidth) {
case 7410: tmodel->initString("H5D-40"); break;
case 8282: tmodel->initString("H5D-50"); break;
case 8374: tmodel->initString("H5D-50c"); break;
case 9044: tmodel->initString("H5D-60"); break;
}
} else if (!strcmp(model, "CFV")) {
switch (sensorWidth) {
case 7262: tmodel->initString("CFV-39"); break;
case 8282: tmodel->initString("CFV-50"); break;
case 8374: tmodel->initString("CFV-50c"); break;
}
}
// and a few special cases
Tag* tmodel3 = root->getTag("UniqueCameraModel");
const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : "";
if (strstr(model3, "Hasselblad ") == model3) {
model3 = model3 + 11;
}
if (!strcmp(model3, "ixpressCF132")) {
tmodel->initString("CF-22");
} else if (!strcmp(model3, "Hasselblad96")) {
tmodel->initString("CFV"); // popularly called CFV-16, but the official name is CFV
} else if (!strcmp(model3, "Hasselblad234")) {
tmodel->initString("CFV-39");
} else if (sensorWidth == 4090) {
tmodel->initString("V96C");
}
// and yet some, this is for Adobe-generated DNG files
Tag* tmodel4 = root->getTag("LocalizedCameraModel");
if (tmodel4) {
const char *model4 = (tmodel4) ? (const char *)tmodel4->getValue() : "";
if (strstr(model4, "Hasselblad ") == model4) {
model4 = model4 + 11;
}
if (!strcmp(model4, "ixpressCF132-22")) {
tmodel->initString("CF-22");
} else if (!strcmp(model4, "Hasselblad96-16")) {
tmodel->initString("CFV");
} else if (!strcmp(model4, "Hasselblad234-39")) {
tmodel->initString("CFV-39");
} else if (!strcmp(model4, "H3D-50")) {
// Adobe names H3DII-50 incorrectly as H3D-50
tmodel->initString("H3DII-50");
} else if (strstr(model4, "H3D-") == model4 || strstr(model4, "H4D-") == model4 || strstr(model4, "H5D-") == model4) {
tmodel->initString(model4);
}
}
}
if (!root->getTag("Orientation")) {
if (make && !strncmp((char*)make->getValue(), "Phase One", 9)) {
int orientation = 0;

View File

@@ -705,6 +705,7 @@ const TagAttrib iopAttribs[] = {
{0, AC_DONTWRITE, 0, 0, 0xC612, AUTO, "DNGVersion", &stdInterpreter},
{0, AC_DONTWRITE, 0, 0, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter},
{0, AC_WRITE, 0, 0, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter},
{0, AC_WRITE, 0, 0, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter},
{0, AC_WRITE, 0, 0, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter},
{0, AC_SYSTEM, 0, 0, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter},
{0, AC_DONTWRITE, 0, 0, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData