diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 0d5870b6a..7e4c02015 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -34,6 +34,10 @@ //#define BENCHMARK #include "StopWatch.h" +#include +#include + + /* dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net @@ -1229,23 +1233,46 @@ void CLASS lossless_dng_load_raw() } } +static uint32_t DNG_HalfToFloat(uint16_t halfValue); + void CLASS packed_dng_load_raw() { ushort *pixel, *rp; int row, col; + int isfloat = (tiff_nifds == 1 && tiff_ifd[0].sample_format == 3 && (tiff_bps == 16 || tiff_bps == 32)); + if (isfloat) { + float_raw_image = new float[raw_width * raw_height]; + } pixel = (ushort *) calloc (raw_width, tiff_samples*sizeof *pixel); merror (pixel, "packed_dng_load_raw()"); for (row=0; row < raw_height; row++) { - if (tiff_bps == 16) + if (tiff_bps == 16) { read_shorts (pixel, raw_width * tiff_samples); - else { + if (isfloat) { + uint32_t *dst = reinterpret_cast(&float_raw_image[row*raw_width]); + for (col = 0; col < raw_width; col++) { + uint32_t f = DNG_HalfToFloat(pixel[col]); + dst[col] = f; + } + } + } else if (isfloat) { + if (fread(&float_raw_image[row*raw_width], sizeof(float), raw_width, ifp) != raw_width) { + derror(); + } + if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) { + char *d = reinterpret_cast(float_raw_image); + rtengine::swab(d, d, sizeof(float)*raw_width); + } + } else { getbits(-1); for (col=0; col < raw_width * tiff_samples; col++) pixel[col] = getbits(tiff_bps); } - for (rp=pixel, col=0; col < raw_width; col++) - adobe_copy_pixel (row, col, &rp); + if (!isfloat) { + for (rp=pixel, col=0; col < raw_width; col++) + adobe_copy_pixel (row, col, &rp); + } } free (pixel); } @@ -6173,6 +6200,7 @@ int CLASS parse_tiff_ifd (int base) break; case 305: case 11: /* Software */ fgets (software, 64, ifp); + RT_software = software; if (!strncmp(software,"Adobe",5) || !strncmp(software,"dcraw",5) || !strncmp(software,"UFRaw",5) || @@ -6441,6 +6469,7 @@ guess_cfa_pc: case 61450: cblack[4] = cblack[5] = MIN(sqrt(len),64); case 50714: /* BlackLevel */ + RT_blacklevel_from_constant = ThreeValBool::F; if(cblack[4] * cblack[5] == 0) { int dblack[] = { 0,0,0,0 }; black = getreal(type); @@ -6461,9 +6490,11 @@ guess_cfa_pc: for (num=i=0; i < (len & 0xffff); i++) num += getreal(type); black += num/len + 0.5; + RT_blacklevel_from_constant = ThreeValBool::F; break; case 50717: /* WhiteLevel */ maximum = getint(type); + RT_whitelevel_from_constant = ThreeValBool::F; break; case 50718: /* DefaultScale */ pixel_aspect = getreal(type); @@ -6492,6 +6523,14 @@ guess_cfa_pc: xyz[2] = 1 - xyz[0] - xyz[1]; FORC3 xyz[c] /= d65_white[c]; break; + case 50730: /* BaselineExposure */ + if (dng_version) { + double be = getreal(type); + if (!std::isnan(be)) { + RT_baseline_exposure = be; + } + } + break; case 50740: /* DNGPrivateData */ if (dng_version) break; parse_minolta (j = get4()+base); @@ -6601,8 +6640,6 @@ guess_cfa_pc: if (!use_cm) FORCC pre_mul[c] /= cc[cm_D65][c][c]; - RT_from_adobe_dng_converter = !strncmp(software, "Adobe DNG Converter", 19); - return 0; } @@ -8665,11 +8702,31 @@ void CLASS adobe_coeff (const char *make, const char *model) int i, j; sprintf (name, "%s %s", make, model); + + + // -- RT -------------------------------------------------------------------- + const bool is_pentax_dng = dng_version && !strncmp(RT_software.c_str(), "PENTAX", 6); + // indicate that DCRAW wants these from constants (rather than having loaded these from RAW file + // note: this is simplified so far, in some cases dcraw calls this when it has say the black level + // from file, but then we will not provide any black level in the tables. This case is mainly just + // to avoid loading table values if we have loaded a DNG conversion of a raw file (which already + // have constants stored in the file). + if (RT_whitelevel_from_constant == ThreeValBool::X || is_pentax_dng) { + RT_whitelevel_from_constant = ThreeValBool::T; + } + if (RT_blacklevel_from_constant == ThreeValBool::X || is_pentax_dng) { + RT_blacklevel_from_constant = ThreeValBool::T; + } + if (RT_matrix_from_constant == ThreeValBool::X) { + RT_matrix_from_constant = ThreeValBool::T; + } + // -- RT -------------------------------------------------------------------- + for (i=0; i < sizeof table / sizeof *table; i++) if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) { - if (table[i].black) black = (ushort) table[i].black; - if (table[i].maximum) maximum = (ushort) table[i].maximum; - if (table[i].trans[0]) { + if (RT_blacklevel_from_constant == ThreeValBool::T && table[i].black) black = (ushort) table[i].black; + if (RT_whitelevel_from_constant == ThreeValBool::T && table[i].maximum) maximum = (ushort) table[i].maximum; + if (RT_matrix_from_constant == ThreeValBool::T && table[i].trans[0]) { for (raw_color = j=0; j < 12; j++) ((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0; cam_xyz_coeff (rgb_cam, cam_xyz); @@ -10107,14 +10164,16 @@ bw: colors = 1; dng_skip: if ((use_camera_matrix & (use_camera_wb || dng_version)) && cmatrix[0][0] > 0.125 - && !RT_from_adobe_dng_converter /* RT -- do not use the embedded - * matrices for DNGs coming from the - * Adobe DNG Converter, to ensure - * consistency of WB values between - * DNG-converted and original raw - * files. See #4129 */) { + && strncmp(RT_software.c_str(), "Adobe DNG Converter", 19) != 0 + /* RT -- do not use the embedded + * matrices for DNGs coming from the + * Adobe DNG Converter, to ensure + * consistency of WB values between + * DNG-converted and original raw + * files. See #4129 */) { memcpy (rgb_cam, cmatrix, sizeof cmatrix); - raw_color = 0; +// raw_color = 0; + RT_matrix_from_constant = ThreeValBool::F; } if(!strncmp(make, "Panasonic", 9) && !strncmp(model, "DMC-LX100",9)) adobe_coeff (make, model); @@ -10148,7 +10207,14 @@ dng_skip: if (raw_width < width ) raw_width = width; } if (!tiff_bps) tiff_bps = 12; - if (!maximum) maximum = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32 + if (!maximum) { + if (tiff_nifds == 1 && tiff_ifd[0].sample_format == 3) { + // float DNG, default white level is 1.0 + maximum = 1; + } else { + maximum = ((uint64_t)1 << tiff_bps) - 1; // use uint64_t to avoid overflow if tiff_bps == 32 + } + } if (!load_raw || height < 22 || width < 22 || tiff_samples > 6 || colors > 4) is_raw = 0; @@ -10231,8 +10297,8 @@ notraw: /* RT: DNG Float */ -#include -#include +// #include +// #include static void decodeFPDeltaRow(Bytef * src, Bytef * dst, size_t tileWidth, size_t realTileWidth, int bytesps, int factor) { // DecodeDeltaBytes @@ -10264,9 +10330,10 @@ static void decodeFPDeltaRow(Bytef * src, Bytef * dst, size_t tileWidth, size_t } -#ifndef __F16C__ +#if 1 //ndef __F16C__ // From DNG SDK dng_utils.h -static inline uint32_t DNG_HalfToFloat(uint16_t halfValue) { +static //inline +uint32_t DNG_HalfToFloat(uint16_t halfValue) { int32_t sign = (halfValue >> 15) & 0x00000001; int32_t exponent = (halfValue >> 10) & 0x0000001f; int32_t mantissa = halfValue & 0x000003ff; diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index dd4831625..aa49b99ce 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -57,10 +57,10 @@ public: ,verbose(0) ,use_auto_wb(0),use_camera_wb(0),use_camera_matrix(1) ,output_color(1),output_bps(8),output_tiff(0),med_passes(0),no_auto_bright(0) - ,RT_whitelevel_from_constant(0) - ,RT_blacklevel_from_constant(0) - ,RT_matrix_from_constant(0) - ,RT_from_adobe_dng_converter(false) + ,RT_whitelevel_from_constant(ThreeValBool::X) + ,RT_blacklevel_from_constant(ThreeValBool::X) + ,RT_matrix_from_constant(ThreeValBool::X) + ,RT_baseline_exposure(0) ,getbithuff(this,ifp,zero_after_ff) ,nikbithuff(ifp) { @@ -152,10 +152,12 @@ protected: int output_color, output_bps, output_tiff, med_passes; int no_auto_bright; unsigned greybox[4] ; - int RT_whitelevel_from_constant; - int RT_blacklevel_from_constant; - int RT_matrix_from_constant; - bool RT_from_adobe_dng_converter; + enum class ThreeValBool { X = -1, F, T }; + ThreeValBool RT_whitelevel_from_constant; + ThreeValBool RT_blacklevel_from_constant; + ThreeValBool RT_matrix_from_constant; + std::string RT_software; + double RT_baseline_exposure; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 47ca7085f..ced3fbb23 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -30,9 +30,9 @@ RawImage::RawImage( const Glib::ustring &name ) , allocation(nullptr) { memset(maximum_c4, 0, sizeof(maximum_c4)); - RT_matrix_from_constant = 0; - RT_blacklevel_from_constant = 0; - RT_whitelevel_from_constant = 0; + RT_matrix_from_constant = ThreeValBool::X; + RT_blacklevel_from_constant = ThreeValBool::X; + RT_whitelevel_from_constant = ThreeValBool::X; } RawImage::~RawImage() @@ -503,6 +503,10 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro fseek (ifp, data_offset, SEEK_SET); (this->*load_raw)(); + if (!float_raw_image) { // apply baseline exposure only for float DNGs + RT_baseline_exposure = 0; + } + if (plistener) { plistener->setProgress(0.9 * progressRange); } @@ -599,14 +603,14 @@ int RawImage::loadRaw (bool loadData, unsigned int imageNum, bool closeFile, Pro if (cc) { for (int i = 0; i < 4; i++) { - if (RT_blacklevel_from_constant) { + if (RT_blacklevel_from_constant == ThreeValBool::T) { int blackFromCc = cc->get_BlackLevel(i, iso_speed); // if black level from camconst > 0xffff it is an absolute value. black_c4[i] = blackFromCc > 0xffff ? (blackFromCc & 0xffff) : blackFromCc + cblack[i]; } // load 4 channel white level here, will be used if available - if (RT_whitelevel_from_constant) { + if (RT_whitelevel_from_constant == ThreeValBool::T) { maximum_c4[i] = cc->get_WhiteLevel(i, iso_speed, aperture); if(tiff_bps > 0 && maximum_c4[i] > 0 && !isFoveon()) { @@ -1049,16 +1053,31 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is *black_level = -1; *white_level = -1; + + const bool is_pentax_dng = dng_version && !strncmp(RT_software.c_str(), "PENTAX", 6); + + if (RT_blacklevel_from_constant == ThreeValBool::F && !is_pentax_dng) { + *black_level = black; + } + if (RT_whitelevel_from_constant == ThreeValBool::F && !is_pentax_dng) { + *white_level = maximum; + } memset(trans, 0, sizeof(*trans) * 12); - // indicate that DCRAW wants these from constants (rather than having loaded these from RAW file - // note: this is simplified so far, in some cases dcraw calls this when it has say the black level - // from file, but then we will not provide any black level in the tables. This case is mainly just - // to avoid loading table values if we have loaded a DNG conversion of a raw file (which already - // have constants stored in the file). - RT_whitelevel_from_constant = 1; - RT_blacklevel_from_constant = 1; - RT_matrix_from_constant = 1; + // // indicate that DCRAW wants these from constants (rather than having loaded these from RAW file + // // note: this is simplified so far, in some cases dcraw calls this when it has say the black level + // // from file, but then we will not provide any black level in the tables. This case is mainly just + // // to avoid loading table values if we have loaded a DNG conversion of a raw file (which already + // // have constants stored in the file). + // if (RT_whitelevel_from_constant == ThreeValBool::X || is_pentax_dng) { + // RT_whitelevel_from_constant = ThreeValBool::T; + // } + // if (RT_blacklevel_from_constant == ThreeValBool::X || is_pentax_dng) { + // RT_blacklevel_from_constant = ThreeValBool::T; + // } + // if (RT_matrix_from_constant == ThreeValBool::X) { + // RT_matrix_from_constant = ThreeValBool::T; + // } { // test if we have any information in the camera constants store, if so we take that. @@ -1066,10 +1085,14 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is rtengine::CameraConst *cc = ccs->get(make, model); if (cc) { - *black_level = cc->get_BlackLevel(0, iso_speed); - *white_level = cc->get_WhiteLevel(0, iso_speed, aperture); + if (RT_blacklevel_from_constant == ThreeValBool::T) { + *black_level = cc->get_BlackLevel(0, iso_speed); + } + if (RT_whitelevel_from_constant == ThreeValBool::T) { + *white_level = cc->get_WhiteLevel(0, iso_speed, aperture); + } - if (cc->has_dcrawMatrix()) { + if (RT_matrix_from_constant == ThreeValBool::T && cc->has_dcrawMatrix()) { const short *mx = cc->get_dcrawMatrix(); for (int j = 0; j < 12; j++) { @@ -1086,8 +1109,12 @@ DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int is for (size_t i = 0; i < sizeof table / sizeof(table[0]); i++) { if (strcasecmp(name, table[i].prefix) == 0) { - *black_level = table[i].black_level; - *white_level = table[i].white_level; + if (RT_blacklevel_from_constant == ThreeValBool::T) { + *black_level = table[i].black_level; + } + if (RT_whitelevel_from_constant == ThreeValBool::T) { + *white_level = table[i].white_level; + } for (int j = 0; j < 12; j++) { trans[j] = table[i].trans[j]; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 7017f4c1b..0dabfef0d 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -125,6 +125,8 @@ public: float** data; // holds pixel values, data[i][j] corresponds to the ith row and jth column unsigned prefilters; // original filters saved ( used for 4 color processing ) unsigned int getFrameCount() const { return is_raw; } + + double getBaselineExposure() const { return RT_baseline_exposure; } protected: Glib::ustring filename; // complete filename int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 086747b1b..13ff1171c 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -716,6 +716,11 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima gm /= area; bm /= area; bool doHr = (hrp.hrenabled && hrp.method != "Color"); + const float expcomp = std::pow(2, ri->getBaselineExposure()); + rm *= expcomp; + gm *= expcomp; + bm *= expcomp; + #ifdef _OPENMP #pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088) { diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 0ca2c24ec..150582f57 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -574,6 +574,7 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; //ri->get_pre_mul(2); //tpp->defGain = 1.0 / min(ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2)); tpp->defGain = max (scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]) / min (scale_mul[0], scale_mul[1], scale_mul[2], scale_mul[3]); + tpp->defGain *= std::pow(2, ri->getBaselineExposure()); tpp->gammaCorrected = true;