00001 #include <fstream>
00002 #include <sstream>
00003 #include <stdio.h>
00004 #include <string.h>
00005 #include <time.h>
00006 #include <sched.h>
00007 #include <math.h>
00008 #include <errno.h>
00009
00010 #include <FCam/processing/DNG.h>
00011 #include <FCam/processing/Color.h>
00012 #include <FCam/processing/Demosaic.h>
00013 #include <FCam/Event.h>
00014 #include <FCam/Frame.h>
00015
00016 #include "TIFF.h"
00017 #include "../Debug.h"
00018
00019 namespace FCam {
00020
00021 void _DNGFrame::rawToRGBColorMatrix(int kelvin, float *matrix) const {
00022 if (dng.numIlluminants == 1) {
00023 for (int i=0;i < 12; i++) matrix[i] = dng.colorMatrix1[i];
00024 return;
00025 }
00026 float alpha =
00027 ((float)kelvin-dng.illuminant1)
00028 /(dng.illuminant2 - dng.illuminant1);
00029 colorMatrixInterpolate(dng.colorMatrix1,
00030 dng.colorMatrix2,
00031 alpha, matrix);
00032 }
00033
00034 void _DNGFrame::debug(const char *name) const {
00035 printf("\tDump of FCam::DNGFrame %s at %llx:\n", name, (long long unsigned)this);
00036 printf("\t Number of calibration illuminants: %d\n", dng.numIlluminants);
00037 printf("\t Illuminant 1: %d K, conversion matrix:\n", dng.illuminant1);
00038 const float *matrix = dng.colorMatrix1;
00039 printf("\t\t[ [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[0], matrix[1], matrix[2], matrix[3]);
00040 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[4], matrix[5], matrix[6], matrix[7]);
00041 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[8], matrix[9], matrix[10], matrix[11]);
00042 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ] ]\n", matrix[12], matrix[13], matrix[14], matrix[15]);
00043 if (dng.numIlluminants == 2) {
00044 printf("\t Illuminant 2: %d K, conversion matrix:\n", dng.illuminant2);
00045 matrix = dng.colorMatrix2;
00046 printf("\t\t[ [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[0], matrix[1], matrix[2], matrix[3]);
00047 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[4], matrix[5], matrix[6], matrix[7]);
00048 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ]\n", matrix[8], matrix[9], matrix[10], matrix[11]);
00049 printf("\t\t [ %5.3f %5.3f %5.3f %5.3f ] ]\n", matrix[12], matrix[13], matrix[14], matrix[15]);
00050 }
00051 printf("\t** Dump of DNGFrame thumbnail image data follows\n");
00052 thumbnail.debug("DNGFrame::thumbnail");
00053 printf("\t** Dump of base Frame fields follows\n");
00054 FCam::_Frame::debug("base frame");
00055 }
00056
00057 DNGFrame::DNGFrame(_DNGFrame *f): FCam::Frame(f) {}
00058
00059 const char understoodDNGVersion[4] = {1,3,0,0};
00060 const char oldestSupportedDNGVersion[4] = {1,2,0,0};
00061 const char privateDataPreamble[] = "stanford.fcam.privatedata";
00062 const int privateDataVersion = 1;
00063
00064 void saveDNG(Frame frame, const std::string &filename) {
00065 dprintf(DBG_MINOR, "saveDNG: Starting to write %s\n", filename.c_str());
00066
00067
00068
00069 if (!frame.valid()) {
00070 error(Event::FileSaveError, frame,
00071 "saveDNG: Cannot save invalid frame as %s.", filename.c_str());
00072 return;
00073 }
00074 if (!frame.image().valid()) {
00075 error(Event::FileSaveError, frame,
00076 "saveDNG: Cannot save frame with no valid image as %s.", filename.c_str());
00077 return;
00078 }
00079 if (frame.image().type() != RAW) {
00080 error(Event::FileSaveError, frame,
00081 "saveDNG: Cannot save a non-RAW frame as a DNG %s", filename.c_str());
00082 return;
00083 }
00084 if (frame.bayerPattern() == NotBayer) {
00085 error(Event::FileSaveError, frame,
00086 "saveDNG: Cannot save non-Bayer pattern RAW data as %s", filename.c_str());
00087 return;
00088 }
00089
00090
00091 std::vector<float> rawToRGB3000(12);
00092 std::vector<float> rawToRGB6500(12);
00093 frame.rawToRGBColorMatrix(3000, &rawToRGB3000[0]);
00094 frame.rawToRGBColorMatrix(6500, &rawToRGB6500[0]);
00095
00096
00097 double rawToXYZ3000[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
00098 double rawToXYZ6500[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
00099 for (int i = 0; i < 3; i++) {
00100 for (int j = 0; j < 3; j++) {
00101 for (int k = 0; k < 3; k++) {
00102 rawToXYZ3000[i*3+j] += FCam::RGBtoXYZ[i*3+k]*rawToRGB3000[k*4+j];
00103 rawToXYZ6500[i*3+j] += FCam::RGBtoXYZ[i*3+k]*rawToRGB6500[k*4+j];
00104 }
00105 }
00106 }
00107
00108 std::vector<double> xyzToRaw3000(9);
00109 std::vector<double> xyzToRaw6500(9);
00110
00111 invert3x3(rawToXYZ3000, &xyzToRaw3000.front());
00112 invert3x3(rawToXYZ6500, &xyzToRaw6500.front());
00113
00114
00115
00116
00117
00118 TIFFFile dng;
00119
00120 TIFFFile::Ifd *ifd0 = dng.addIfd();
00121
00122
00123
00124 std::string dngVersion(understoodDNGVersion,4);
00125 ifd0->add(DNG_TAG_DNGVersion, dngVersion);
00126
00127 std::string dngBackVersion(oldestSupportedDNGVersion,4);
00128 ifd0->add(DNG_TAG_DNGBackwardVersion, dngBackVersion);
00129
00130 ifd0->add(TIFF_TAG_Make, frame.manufacturer());
00131 ifd0->add(TIFF_TAG_Model, frame.model());
00132 ifd0->add(DNG_TAG_UniqueCameraModel, frame.model());
00133
00134 if (frame.tags().find("flash.brightness") != frame.tags().end()) {
00135
00136
00137
00138
00139
00140
00141
00142 ifd0->add(TIFFEP_TAG_Flash, 1);
00143 }
00144
00145
00146 ifd0->add(TIFFEP_TAG_TIFFEPStandardID, 1);
00147
00148 time_t tim = frame.exposureStartTime().s();
00149 struct tm *local = localtime(&tim);
00150 char buf[20];
00151 snprintf(buf, 20, "%04d:%02d:%02d %02d:%02d:%02d",
00152 local->tm_year + 1900,
00153 local->tm_mon,
00154 local->tm_mday,
00155 local->tm_hour,
00156 local->tm_min,
00157 local->tm_sec);
00158 ifd0->add(TIFF_TAG_DateTime, std::string(buf));
00159
00160 ifd0->add(DNG_TAG_CalibrationIlluminant1, DNG_TAG_CalibrationIlluminant_StdA);
00161 ifd0->add(DNG_TAG_ColorMatrix1, xyzToRaw3000);
00162
00163 ifd0->add(DNG_TAG_CalibrationIlluminant2, DNG_TAG_CalibrationIlluminant_D65);
00164 ifd0->add(DNG_TAG_ColorMatrix2, xyzToRaw6500);
00165
00166 std::vector<double> whiteXY(2);
00167 float x,y;
00168 kelvinToXY(frame.whiteBalance(), &x, &y);
00169 whiteXY[0] = x; whiteXY[1] = y;
00170 ifd0->add(DNG_TAG_AsShotWhiteXY, whiteXY);
00171
00172 std::vector<double> lensInfo(4);
00173 if (frame.tags().find("lens.minZoom") != frame.tags().end()) {
00174 lensInfo[0] = frame["lens.minZoom"].asFloat();
00175 lensInfo[1] = frame["lens.maxZoom"].asFloat();
00176 lensInfo[2] = frame["lens.wideApertureMin"].asFloat();
00177 lensInfo[3] = frame["lens.wideApertureMax"].asFloat();
00178 ifd0->add(DNG_TAG_LensInfo, lensInfo);
00179 }
00180
00181
00182 ifd0->add(EXIF_TAG_ExposureTime, double(frame.exposure())/1e6);
00183 if (frame.tags().find("lens.aperture") != frame.tags().end()) {
00184 double fNumber = frame["lens.aperture"].asFloat();
00185 ifd0->add(EXIF_TAG_FNumber, fNumber);
00186 }
00187
00188
00189 {
00190 std::stringstream privateData;
00191
00192 privateData << privateDataPreamble << std::ends;
00193
00194 privateData << TagValue(privateDataVersion).toBlob();
00195
00196 privateData << TagValue(frame.exposureStartTime()).toBlob();
00197 privateData << TagValue(frame.exposureEndTime()).toBlob();
00198 privateData << TagValue(frame.processingDoneTime()).toBlob();
00199 privateData << TagValue(frame.exposure()).toBlob();
00200 privateData << TagValue(frame.frameTime()).toBlob();
00201 privateData << TagValue(frame.gain()).toBlob();
00202 privateData << TagValue(frame.whiteBalance()).toBlob();
00203
00204 privateData << TagValue(frame.shot().exposure).toBlob();
00205 privateData << TagValue(frame.shot().frameTime).toBlob();
00206 privateData << TagValue(frame.shot().gain).toBlob();
00207 privateData << TagValue(frame.shot().whiteBalance).toBlob();
00208
00209 privateData << TagValue(frame.minRawValue()).toBlob();
00210 privateData << TagValue(frame.maxRawValue()).toBlob();
00211
00212 privateData << TagValue(3000).toBlob();
00213 privateData << TagValue(rawToRGB3000).toBlob();
00214 privateData << TagValue(6500).toBlob();
00215 privateData << TagValue(rawToRGB6500).toBlob();
00216
00217
00218
00219
00220
00221 for (TagMap::const_iterator it = frame.tags().begin(); it != frame.tags().end(); it++) {
00222 privateData << TagValue(it->first) << TagValue(it->second);
00223 }
00224 ifd0->add(DNG_TAG_DNGPrivateData, privateData.str());
00225 }
00226
00227
00228 TIFFFile::Ifd *thumbIfd = ifd0;
00229 Image thumbnail = makeThumbnail(frame);
00230
00231 thumbIfd->add(TIFF_TAG_NewSubFileType, (int)TIFF_NewSubfileType_MainPreview);
00232 thumbIfd->setImage(thumbnail);
00233
00234
00235
00236 TIFFFile::Ifd *rawIfd = ifd0->addSubIfd();
00237
00238 rawIfd->add(TIFF_TAG_NewSubFileType, (int)TIFF_NewSubfileType_FullRAW);
00239
00240 std::vector<int> CFARepeatPatternDim(2,2);
00241 rawIfd->add(TIFFEP_TAG_CFARepeatPatternDim, CFARepeatPatternDim);
00242
00243 std::string CFAPattern;
00244 std::vector<int> blackLevel;
00245 switch(frame.bayerPattern()) {
00246 case RGGB:
00247 CFAPattern = std::string(TIFFEP_CFAPattern_RGGB,4);
00248 blackLevel.push_back(-rawToRGB3000[3]);
00249 blackLevel.push_back(-rawToRGB3000[7]);
00250 blackLevel.push_back(-rawToRGB3000[7]);
00251 blackLevel.push_back(-rawToRGB3000[11]);
00252 break;
00253 case BGGR:
00254 CFAPattern = std::string(TIFFEP_CFAPattern_BGGR,4);
00255 blackLevel.push_back(-rawToRGB3000[11]);
00256 blackLevel.push_back(-rawToRGB3000[7]);
00257 blackLevel.push_back(-rawToRGB3000[7]);
00258 blackLevel.push_back(-rawToRGB3000[3]);
00259 break;
00260 case GRBG:
00261 CFAPattern = std::string(TIFFEP_CFAPattern_GRBG,4);
00262 blackLevel.push_back(-rawToRGB3000[7]);
00263 blackLevel.push_back(-rawToRGB3000[3]);
00264 blackLevel.push_back(-rawToRGB3000[11]);
00265 blackLevel.push_back(-rawToRGB3000[7]);
00266 break;
00267 case GBRG:
00268 CFAPattern = std::string(TIFFEP_CFAPattern_GBRG,4);
00269 blackLevel.push_back(-rawToRGB3000[7]);
00270 blackLevel.push_back(-rawToRGB3000[11]);
00271 blackLevel.push_back(-rawToRGB3000[3]);
00272 blackLevel.push_back(-rawToRGB3000[7]);
00273 default:
00274 error(Event::FileSaveError, "saveDNG: %s: Can't handle non-bayer RAW images", filename.c_str());
00275 return;
00276 break;
00277 }
00278 rawIfd->add(TIFFEP_TAG_CFAPattern, CFAPattern);
00279 rawIfd->add(DNG_TAG_BlackLevel, blackLevel);
00280
00281 std::vector<int> blackLevelRepeatDim(2,2);
00282 rawIfd->add(DNG_TAG_BlackLevelRepeatDim, blackLevelRepeatDim);
00283
00284 rawIfd->add(DNG_TAG_WhiteLevel, frame.maxRawValue());
00285
00286 rawIfd->setImage(frame.image());
00287
00288
00289 dng.writeTo(filename);
00290
00291 dprintf(DBG_MINOR, "saveDNG: Done writing %s\n", filename.c_str());
00292 }
00293
00294
00295 DNGFrame loadDNG(const std::string &filename) {
00296 TIFFFile dng(filename);
00297 if (!dng.valid) {
00298
00299
00300 Event err = dng.lastEvent;
00301 DNGFrame nullF;
00302 err.creator = nullF;
00303 postEvent(err);
00304 return nullF;
00305 }
00306
00307
00308 #define fatalError(...) do { \
00309 DNGFrame nullF; \
00310 error(Event::FileLoadError, nullF, __VA_ARGS__); \
00311 return nullF; } while(0)
00312
00313
00314
00315
00316 const TIFFFile::IfdEntry *versionEntry, *backVersionEntry;
00317
00318 versionEntry = dng.ifds(0)->find(DNG_TAG_DNGVersion);
00319 if (!versionEntry) fatalError("loadDNG: File %s is not a valid DNG file (no DNG version found)", filename.c_str());
00320
00321 std::string ver(versionEntry->value());
00322 dprintf(4, "loadDNG: DNG file version is %d.%d.%d.%d.\n", ver[0],ver[1],ver[2],ver[3]);
00323
00324 backVersionEntry = dng.ifds(0)->find(DNG_TAG_DNGBackwardVersion);
00325 if (!backVersionEntry) {
00326
00327 ver = (std::string)backVersionEntry->value();
00328 ver[2] = 0;
00329 ver[3] = 0;
00330 } else {
00331
00332 ver = (std::string)backVersionEntry->value();
00333 }
00334 dprintf(4, "loadDNG: DNG file backward version is %d.%d.%d.%d.\n", ver[0], ver[1], ver[2], ver[3]);
00335
00336 if ( (understoodDNGVersion[0] < ver[0]) ||
00337 ( (understoodDNGVersion[0] == ver[0]) && (understoodDNGVersion[1] < ver[1])) ||
00338 ( (understoodDNGVersion[1] == ver[1]) && (understoodDNGVersion[2] < ver[2])) ||
00339 ( (understoodDNGVersion[2] == ver[2]) && (understoodDNGVersion[3] < ver[3]) ) ) {
00340 fatalError("loadDNG: File %s is too new, requires understanding at least DNG version %d.%d.%d.%d\n", filename.c_str(), ver[0],ver[1],ver[2],ver[3]);
00341 }
00342
00343
00344
00345
00346 const TIFFFile::IfdEntry *entry;
00347 entry = dng.ifds(0)->find(TIFF_TAG_NewSubFileType);
00348 int ifdType = TIFF_NewSubfileType_DEFAULT;
00349 if (entry) {
00350 ifdType = entry->value();
00351 }
00352
00353 TIFFFile::Ifd *rawIfd=NULL;
00354 if (ifdType == (int)TIFF_NewSubfileType_FullRAW) {
00355
00356 dprintf(4, "loadDNG: RAW data found in IFD0\n");
00357 rawIfd = dng.ifds(0);
00358 } else {
00359
00360 for (size_t i=0; i < dng.ifds(0)->subIfds().size(); i++) {
00361 ifdType = TIFF_NewSubfileType_DEFAULT;
00362 entry = dng.ifds(0)->subIfds(i)->find(TIFF_TAG_NewSubFileType);
00363 if (entry) {
00364 ifdType = entry->value();
00365 }
00366 if (ifdType == (int)TIFF_NewSubfileType_FullRAW) {
00367 dprintf(4, "loadDNG: RAW data found in subIFD %d\n", i);
00368 rawIfd = dng.ifds(0)->subIfds(i);
00369 break;
00370 }
00371 }
00372 if (!rawIfd) fatalError("loadDNG: %s: Can't find RAW data!", filename.c_str());
00373 }
00374
00375
00376
00377
00378
00379 Image img = rawIfd->getImage();
00380 if (!img.valid()) {
00381 fatalError("loadDNG: %s: Cannot load RAW image data", filename.c_str());
00382 }
00383
00384
00385
00386
00387 entry = rawIfd->find(TIFFEP_TAG_CFARepeatPatternDim);
00388 if (!entry) fatalError("loadDNG: %s: No CFA pattern dimensions tag found.");
00389 BayerPattern bayer;
00390 {
00391 std::vector<int> &cfaRepeatPatternDim = entry->value();
00392 if (cfaRepeatPatternDim[0] != 2 ||
00393 cfaRepeatPatternDim[1] != 2) fatalError("loadDNG: %s: CFA pattern dimensions not 2x2 (%d x %d). Unsupported.\n", filename.c_str());
00394
00395 entry = rawIfd->find(TIFFEP_TAG_CFAPattern);
00396 if (!entry) fatalError("loadDNG: %s: No CFA pattern tag found.");
00397 std::string cfaPattern = entry->value();
00398 if (cfaPattern.size() != 4) fatalError("loadDNG: %s: CFA pattern entry incorrect\n", filename.c_str());
00399 if (cfaPattern[0] == TIFFEP_CFAPattern_RGGB[0] &&
00400 cfaPattern[1] == TIFFEP_CFAPattern_RGGB[1] &&
00401 cfaPattern[2] == TIFFEP_CFAPattern_RGGB[2] &&
00402 cfaPattern[3] == TIFFEP_CFAPattern_RGGB[3]) {
00403 bayer = RGGB;
00404 } else if (cfaPattern[0] == TIFFEP_CFAPattern_BGGR[0] &&
00405 cfaPattern[1] == TIFFEP_CFAPattern_BGGR[1] &&
00406 cfaPattern[2] == TIFFEP_CFAPattern_BGGR[2] &&
00407 cfaPattern[3] == TIFFEP_CFAPattern_BGGR[3]) {
00408 bayer = BGGR;
00409 } else if (cfaPattern[0] == TIFFEP_CFAPattern_GRBG[0] &&
00410 cfaPattern[1] == TIFFEP_CFAPattern_GRBG[1] &&
00411 cfaPattern[2] == TIFFEP_CFAPattern_GRBG[2] &&
00412 cfaPattern[3] == TIFFEP_CFAPattern_GRBG[3]) {
00413 bayer = GRBG;
00414 } else if (cfaPattern[0] == TIFFEP_CFAPattern_GBRG[0] &&
00415 cfaPattern[1] == TIFFEP_CFAPattern_GBRG[1] &&
00416 cfaPattern[2] == TIFFEP_CFAPattern_GBRG[2] &&
00417 cfaPattern[3] == TIFFEP_CFAPattern_GBRG[3]) {
00418 bayer = GBRG;
00419 } else {
00420 fatalError("loadDNG: %s: Unsupported CFA pattern: %d %d %d %d\n", filename.c_str(), cfaPattern[0], cfaPattern[1], cfaPattern[2], cfaPattern[3]);
00421 }
00422 dprintf(4,"loadDNG: %s: CFA pattern is type %d\n", filename.c_str(), bayer);
00423 }
00424
00425
00426 entry = rawIfd->find(DNG_TAG_BlackLevelRepeatDim);
00427 uint16_t blackLevelRepeatRows = 1;
00428 uint16_t blackLevelRepeatCols = 1;
00429 if (entry) {
00430 std::vector<int> &blackLevelDims = entry->value();
00431 blackLevelRepeatRows = blackLevelDims[0];
00432 blackLevelRepeatCols = blackLevelDims[1];
00433 }
00434 if (! ((blackLevelRepeatRows == 1 && blackLevelRepeatCols == 1)
00435 || (blackLevelRepeatRows == 2 && blackLevelRepeatCols == 2)) ) {
00436 fatalError("loadDNG: %s: Black level pattern size is unsupported: %d x %d (only support 1x1 or 2x2)",
00437 filename.c_str(), blackLevelRepeatRows, blackLevelRepeatCols);
00438 }
00439
00440 entry = rawIfd->find(DNG_TAG_BlackLevel);
00441 uint16_t blackLevel[3] = {0,0,0};
00442 if (entry) {
00443 if (entry->value().type == TagValue::Int) {
00444 if (blackLevelRepeatRows != 1) {
00445 fatalError("loadDNG: %s: Mismatched entry count between BlackLevelRepeatDim and BlackLevel",
00446 filename.c_str());
00447 }
00448 blackLevel[0] = (int)entry->value();
00449 blackLevel[1] = (int)entry->value();
00450 blackLevel[2] = (int)entry->value();
00451 } else if (entry->value().type == TagValue::IntVector) {
00452 std::vector<int> &blackLevelTag = entry->value();
00453 if (blackLevelRepeatRows != 2 ||
00454 blackLevelTag.size() != 4) {
00455 fatalError("loadDNG: %s: Mismatched entry count between BlackLevelRepeatDim and BlackLevel",
00456 filename.c_str());
00457 }
00458 switch(bayer) {
00459 case RGGB:
00460 blackLevel[0] = (int)blackLevelTag[0];
00461 blackLevel[1] = (int)(blackLevelTag[1] + blackLevelTag[2])/2;
00462 blackLevel[2] = (int)blackLevelTag[3];
00463 break;
00464 case BGGR:
00465 blackLevel[0] = blackLevelTag[3];
00466 blackLevel[1] = (blackLevelTag[1] + blackLevelTag[2])/2;
00467 blackLevel[2] = blackLevelTag[0];
00468 break;
00469 case GRBG:
00470 blackLevel[0] = blackLevelTag[1];
00471 blackLevel[1] = (blackLevelTag[0] + blackLevelTag[3])/2;
00472 blackLevel[2] = blackLevelTag[2];
00473 break;
00474 case GBRG:
00475 blackLevel[0] = blackLevelTag[2];
00476 blackLevel[1] = (blackLevelTag[0] + blackLevelTag[3])/2;
00477 blackLevel[2] = blackLevelTag[1];
00478 break;
00479 default:
00480 fatalError("loadDNG: %s: Unexpected Bayer value (should already have been validated)!", filename.c_str());
00481 };
00482 } else {
00483 fatalError("loadDNG: %s: Unexpected type of black level tag found", filename.c_str());
00484 }
00485 }
00486 dprintf(4,"loadDNG: %s: Black levels are %d, %d, %d\n", filename.c_str(), blackLevel[0], blackLevel[1], blackLevel[2]);
00487
00488
00489 entry = rawIfd->find(DNG_TAG_WhiteLevel);
00490 uint16_t whiteLevel = 65535;
00491 if (entry) {
00492 whiteLevel = (int)entry->value();
00493 }
00494 dprintf(4,"loadDNG: %s: White level is %d\n", filename.c_str(), whiteLevel);
00495
00496
00497
00498
00499 entry = dng.ifds(0)->find(TIFF_TAG_NewSubFileType);
00500 ifdType = TIFF_NewSubfileType_DEFAULT;
00501 if (entry) {
00502 ifdType = entry->value();
00503 }
00504
00505 TIFFFile::Ifd *thumbIfd=NULL;
00506 if (ifdType == (int)TIFF_NewSubfileType_MainPreview) {
00507
00508 dprintf(4, "loadDNG: Thumbnail data found in IFD0\n");
00509 thumbIfd = dng.ifds(0);
00510 } else {
00511
00512 for (size_t i=0; i < dng.ifds(0)->subIfds().size(); i++) {
00513 ifdType = TIFF_NewSubfileType_DEFAULT;
00514 entry = dng.ifds(0)->subIfds(i)->find(TIFF_TAG_NewSubFileType);
00515 if (entry) {
00516 ifdType = entry->value();
00517 }
00518 if (ifdType == (int)TIFF_NewSubfileType_MainPreview) {
00519 dprintf(4, "loadDNG: Thumbnail data found in subIFD %d\n", i);
00520 thumbIfd = dng.ifds(0)->subIfds(i);
00521 break;
00522 }
00523 }
00524 }
00525 Image thumbnail;
00526 if (thumbIfd) {
00527 dprintf(4, "loadDNG: %s: Loading thumbnail\n", filename.c_str());
00528 thumbnail = thumbIfd->getImage();
00529 }
00530
00531
00532
00533
00534
00535 entry = dng.ifds(0)->find(DNG_TAG_CalibrationIlluminant1);
00536 unsigned int calibIlluminant1 = 0;
00537 if (entry) calibIlluminant1 = (int)entry->value();
00538 if (calibIlluminant1 >= DNG_CalibrationIlluminant_Values) calibIlluminant1 = DNG_CalibrationIlluminant_Values - 1;
00539
00540 int calibTemp1 = DNG_CalibrationIlluminant_Temp[calibIlluminant1];
00541 dprintf(4,"loadDNG: %s: Calibration illuminant #1 is type %d (%d K)\n", filename.c_str(), calibIlluminant1, calibTemp1);
00542
00543 std::vector<float> camToRGBMatrix1(9);
00544 {
00545 entry = dng.ifds(0)->find(DNG_TAG_ColorMatrix1);
00546 if (!entry) fatalError("loadDNG: %s: No color calibration matrix found in IFD0", filename.c_str());
00547
00548 std::vector<double> &xyzToCamMatrix1 = entry->value();
00549
00550 std::vector<float> rgbToCamMatrix1(9);
00551
00552 for (int i=0;i<3;i++) {
00553 for (int j=0; j<3; j++) {
00554 for (int k=0; k<3;k++) {
00555 rgbToCamMatrix1[i*3+j] += RGBtoXYZ[i*3+k]*xyzToCamMatrix1[k*3+j];
00556 }
00557 }
00558 }
00559 invert3x3(&rgbToCamMatrix1[0], &camToRGBMatrix1[0]);
00560 }
00561
00562 entry = dng.ifds(0)->find(DNG_TAG_CalibrationIlluminant2);
00563 int numCalibIlluminants = 1;
00564 int calibTemp2 = -1;
00565 std::vector<float> camToRGBMatrix2(9);
00566 if (entry) {
00567 numCalibIlluminants = 2;
00568 unsigned int calibIlluminant2 = (int)entry->value();
00569 if (calibIlluminant2 >= DNG_CalibrationIlluminant_Values) calibIlluminant2 = DNG_CalibrationIlluminant_Values - 1;
00570
00571 calibTemp2 = DNG_CalibrationIlluminant_Temp[calibIlluminant2];
00572 dprintf(4,"loadDNG: %s: Calibration illuminant #2 is type %d (%d K)\n", filename.c_str(), calibIlluminant2, calibTemp2);
00573
00574 entry = dng.ifds(0)->find(DNG_TAG_ColorMatrix2);
00575 if (!entry) fatalError("loadDNG: %s: No color matrix found for second calibration illuminant", filename.c_str());
00576
00577 std::vector<double> &xyzToCamMatrix2 = entry->value();
00578
00579 std::vector<float> rgbToCamMatrix2(9);
00580
00581 for (int i=0;i<3;i++) {
00582 for (int j=0; j<3; j++) {
00583 for (int k=0; k<3;k++) {
00584 rgbToCamMatrix2[i*3+j] += RGBtoXYZ[i*3+k]*xyzToCamMatrix2[k*3+j];
00585 }
00586 }
00587 }
00588 invert3x3(&rgbToCamMatrix2[0], &camToRGBMatrix2[0]);
00589 }
00590
00591
00592 entry = dng.ifds(0)->find(TIFF_TAG_Model);
00593 std::string cameraModel = "Unknown";
00594 if (entry) cameraModel = (std::string)entry->value();
00595 dprintf(4,"loadDNG: %s: Camera model is %s\n", filename.c_str(), cameraModel.c_str());
00596
00597
00598 entry = dng.ifds(0)->find(TIFF_TAG_Make);
00599 std::string cameraManufacturer = "Unknown";
00600 if (entry) cameraManufacturer = (std::string)entry->value();
00601 dprintf(4,"loadDNG: %s: Camera manufacturer is %s\n", filename.c_str(), cameraManufacturer.c_str());
00602
00603 #undef fatalError
00604
00605
00606 _DNGFrame *_f = new _DNGFrame;
00607 DNGFrame DNGFrame(_f);
00608
00609
00610 _f->dng.minRawValue = std::min(blackLevel[0], std::min(blackLevel[1], blackLevel[2]));
00611 _f->dng.maxRawValue = whiteLevel;
00612 _f->dng.numIlluminants = numCalibIlluminants;
00613 _f->dng.illuminant1 = calibTemp1;
00614 _f->dng.illuminant2 = calibTemp2;
00615 for (int i=0; i < 3; i++) {
00616 for (int j=0; j < 3; j++) {
00617 _f->dng.colorMatrix1[i*4+j] = camToRGBMatrix1[i*3+j];
00618 _f->dng.colorMatrix2[i*4+j] = camToRGBMatrix2[i*3+j];
00619 }
00620 }
00621 for (int i=0; i < 3; i++) {
00622 _f->dng.colorMatrix1[i*4+3] = -blackLevel[i];
00623 _f->dng.colorMatrix2[i*4+3] = -blackLevel[i];
00624 }
00625
00626
00627 entry = dng.ifds(0)->find(DNG_TAG_DNGPrivateData);
00628 if (entry) {
00629 std::string &privateString = entry->value();
00630
00631 int preambleEnd = privateString.find((char)0);
00632 std::string preamble = privateString.substr(0,preambleEnd);
00633 if (preamble == privateDataPreamble) {
00634
00635 std::stringstream privateData(privateString.substr(preambleEnd+1));
00636 TagValue version;
00637 privateData >> version;
00638 if (version.asInt() == privateDataVersion) {
00639 dprintf(4,"loadDNG: %s: Reading private data: %s version %d.\n", filename.c_str(), preamble.c_str(), version.asInt());
00640
00641
00642 TagValue val;
00643 privateData >> val;
00644 _f->exposureStartTime = val;
00645 privateData >> val;
00646 _f->exposureEndTime = val;
00647 privateData >> val;
00648 _f->processingDoneTime = val;
00649 privateData >> val;
00650 _f->exposure = val;
00651 privateData >> val;
00652 _f->frameTime = val;
00653 privateData >> val;
00654 _f->gain = val;
00655 privateData >> val;
00656 _f->whiteBalance = val;
00657
00658 privateData >> val;
00659 _f->_shot.exposure = val;
00660 privateData >> val;
00661 _f->_shot.frameTime = val;
00662 privateData >> val;
00663 _f->_shot.gain = val;
00664 privateData >> val;
00665 _f->_shot.whiteBalance = val;
00666
00667 privateData >> val;
00668 _f->dng.minRawValue = val.asInt();
00669 privateData >> val;
00670 _f->dng.maxRawValue = val.asInt();
00671
00672 _f->dng.numIlluminants = 2;
00673
00674 privateData >> val;
00675 _f->dng.illuminant1 = val;
00676 privateData >> val;
00677 for (int i=0; i < 12 ; i++)
00678 _f->dng.colorMatrix1[i] = val.asFloatVector()[i];
00679
00680 privateData >> val;
00681 _f->dng.illuminant2 = val;
00682 privateData >> val;
00683 for (int i=0; i < 12 ; i++)
00684 _f->dng.colorMatrix2[i] = val.asFloatVector()[i];
00685
00686
00687 TagValue key;
00688 while ((privateData >> key).good()) {
00689 privateData >> val;
00690 _f->tags[key] = val;
00691 }
00692 } else {
00693 warning(Event::FileLoadError,
00694 "loadDNG: %s: Private data version too new: %d (can handle %d), ignoring it.",
00695 filename.c_str(), version.asInt(), privateDataVersion);
00696 }
00697 } else {
00698 warning(Event::FileLoadError,
00699 "loadDNG: %s: Private data preamble doesn't match FCam's: '%s' (expecting '%s'), ignoring it.",
00700 filename.c_str(), preamble.c_str(), privateDataPreamble);
00701 }
00702 }
00703
00704
00705 _f->image = img;
00706 _f->thumbnail = thumbnail;
00707 _f->dng.bayerPattern = bayer;
00708 _f->dng.manufacturer = cameraManufacturer;
00709 _f->dng.model = cameraModel;
00710
00711 dprintf(4,"loadDNG: %s: Loaded successfully\n", filename.c_str());
00712 return DNGFrame;
00713 }
00714
00715 }