diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 3cde2a1dd..36cde4bae 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -123,7 +123,7 @@ void Crop::update (int todo) { if (skip==1 && params.dirpyrDenoise.enabled) parent->ipf.RGB_denoise(origCrop, origCrop, parent->imgsrc->isRAW(), /*Roffset,*/ params.dirpyrDenoise, params.defringe, parent->imgsrc->getDirPyrDenoiseExpComp()); } - parent->imgsrc->convertColorSpace(origCrop, params.icm, params.raw); + parent->imgsrc->convertColorSpace(origCrop, params.icm, parent->currWB, params.raw); } // transform diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index a9e346994..7ed046d8d 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -77,7 +77,7 @@ class ImageSource : public InitialImage { // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource virtual bool isWBProviderReady () =0; - virtual void convertColorSpace (Imagefloat* image, ColorManagementParams cmp, RAWParams raw) =0;// DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images + virtual void convertColorSpace (Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw) =0;// DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) =0; virtual ColorTemp getWB () =0; virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) =0; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 19d5cd7f2..9d934657a 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -239,7 +239,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) { if (scale==1 && params.dirpyrDenoise.enabled) ipf.RGB_denoise(orig_prev, orig_prev, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp()); } - imgsrc->convertColorSpace(orig_prev, params.icm, params.raw); + imgsrc->convertColorSpace(orig_prev, params.icm, currWB, params.raw); ipf.firstAnalysis (orig_prev, ¶ms, vhist16, imgsrc->getGamma()); } @@ -783,7 +783,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) { params.wb.temperature = currWB.getTemp (); params.wb.green = currWB.getGreen (); imgsrc->getImage (currWB, 0, im, pp, ppar.hlrecovery, ppar.icm, ppar.raw); - imgsrc->convertColorSpace(im, ppar.icm, params.raw); + imgsrc->convertColorSpace(im, ppar.icm, currWB, params.raw); Image16* im16 = im->to16(); delete im; im16->saveTIFF (fname,16,true); diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 746acf094..22c3f7a12 100755 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -47,7 +47,7 @@ RawImage::~RawImage() /* Similar to dcraw scale_colors for coeff. calculation, but without actual pixels scaling. * need pixels in data[][] available */ -void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblack_) +void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblack_, bool forceAutoWB) { unsigned row, col, x, y, c, sum[8]; @@ -60,7 +60,7 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac cblack_[c] = (float) this->get_cblack(c); pre_mul_[c] = this->get_pre_mul(c); } - if ( this->get_cam_mul(0) == -1 ) { + if ( this->get_cam_mul(0) == -1 || forceAutoWB) { memset(dsum, 0, sizeof dsum); for (row = 0; row < H; row += 8) for (col = 0; col < W ; col += 8) { diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h old mode 100644 new mode 100755 index 10865d0d7..0a4af7d4a --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -90,7 +90,7 @@ public: ~RawImage(); int loadRaw (bool loadData=true, bool closeFile=true); - void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_ ); + void get_colorsCoeff( float* pre_mul_, float* scale_mul_, float* cblack_, bool forceAutoWB ); void set_prefilters(){ if (isBayer() && get_colors() == 3) { prefilters = filters; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 9d0bddfc7..a55d0e558 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -215,9 +215,9 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre rm = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; gm = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; bm = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; - rm = camwb_red / rm; - gm = camwb_green / gm; - bm = camwb_blue / bm; + rm = refwb_red / rm; + gm = refwb_green / gm; + bm = refwb_blue / bm; /*float mul_lum = 0.299*rm + 0.587*gm + 0.114*bm; rm /= mul_lum; @@ -425,7 +425,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre //colorSpaceConversion (image, cmp, raw, embProfile, camProfile, xyz_cam, (static_cast(getMetaData()))->getCamera()); } -void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, RAWParams raw) { +void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw) { colorSpaceConversion (image, cmp, wb, raw, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); } @@ -874,19 +874,68 @@ int RawImageSource::load (Glib::ustring fname, bool batch) { camProfile = iccStore->createFromMatrix (imatrices.xyz_cam, false, "Camera"); inverse33 (imatrices.xyz_cam, imatrices.cam_xyz); + // First we get the "as shot" ("Camera") white balance and store it float pre_mul[4]; - ri->get_colorsCoeff( pre_mul, scale_mul, c_black);//modify for black level + ri->get_colorsCoeff( pre_mul, scale_mul, c_black, false);//modify for black level - camwb_red = ri->get_pre_mul(0) / pre_mul[0]; - camwb_green = ri->get_pre_mul(1) / pre_mul[1]; - camwb_blue = ri->get_pre_mul(2) / pre_mul[2]; - initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]); + double camwb_red = ri->get_pre_mul(0) / pre_mul[0]; + double camwb_green = ri->get_pre_mul(1) / pre_mul[1]; + double camwb_blue = ri->get_pre_mul(2) / pre_mul[2]; + double cam_r = imatrices.rgb_cam[0][0]*camwb_red + imatrices.rgb_cam[0][1]*camwb_green + imatrices.rgb_cam[0][2]*camwb_blue; + double cam_g = imatrices.rgb_cam[1][0]*camwb_red + imatrices.rgb_cam[1][1]*camwb_green + imatrices.rgb_cam[1][2]*camwb_blue; + double cam_b = imatrices.rgb_cam[2][0]*camwb_red + imatrices.rgb_cam[2][1]*camwb_green + imatrices.rgb_cam[2][2]*camwb_blue; + camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1.); // as shot WB - double cam_r = imatrices.rgb_cam[0][0]*camwb_red + imatrices.rgb_cam[0][1]*camwb_green + imatrices.rgb_cam[0][2]*camwb_blue; - double cam_g = imatrices.rgb_cam[1][0]*camwb_red + imatrices.rgb_cam[1][1]*camwb_green + imatrices.rgb_cam[1][2]*camwb_blue; - double cam_b = imatrices.rgb_cam[2][0]*camwb_red + imatrices.rgb_cam[2][1]*camwb_green + imatrices.rgb_cam[2][2]*camwb_blue; - - wb = ColorTemp (cam_r, cam_g, cam_b, 1.); + ColorTemp ReferenceWB; + double ref_r, ref_g, ref_b; + { + // ...then we re-get the constants but now with auto which gives us better demosaicing and CA auto-correct + // performance for strange white balance settings (such as UniWB) + ri->get_colorsCoeff( pre_mul, scale_mul, c_black, true); + refwb_red = ri->get_pre_mul(0) / pre_mul[0]; + refwb_green = ri->get_pre_mul(1) / pre_mul[1]; + refwb_blue = ri->get_pre_mul(2) / pre_mul[2]; + initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]); + ref_r = imatrices.rgb_cam[0][0]*refwb_red + imatrices.rgb_cam[0][1]*refwb_green + imatrices.rgb_cam[0][2]*refwb_blue; + ref_g = imatrices.rgb_cam[1][0]*refwb_red + imatrices.rgb_cam[1][1]*refwb_green + imatrices.rgb_cam[1][2]*refwb_blue; + ref_b = imatrices.rgb_cam[2][0]*refwb_red + imatrices.rgb_cam[2][1]*refwb_green + imatrices.rgb_cam[2][2]*refwb_blue; + ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.); + } + if (settings->verbose) { + printf("Raw As Shot White balance: temp %f, tint %f\n", camera_wb.getTemp(), camera_wb.getGreen()); + printf("Raw Reference (auto) white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green); + } + + /*{ + // Test code: if you want to test a specific white balance + ColorTemp d50wb = ColorTemp(5000.0, 1.0, 1.0, "Custom"); + double rm,gm,bm,r,g,b; + d50wb.getMultipliers(r, g, b); + camwb_red = imatrices.cam_rgb[0][0]*r + imatrices.cam_rgb[0][1]*g + imatrices.cam_rgb[0][2]*b; + camwb_green = imatrices.cam_rgb[1][0]*r + imatrices.cam_rgb[1][1]*g + imatrices.cam_rgb[1][2]*b; + camwb_blue = imatrices.cam_rgb[2][0]*r + imatrices.cam_rgb[2][1]*g + imatrices.cam_rgb[2][2]*b; + double pre_mul[3], dmax = 0; + pre_mul[0] = ri->get_pre_mul(0) / camwb_red; + pre_mul[1] = ri->get_pre_mul(1) / camwb_green; + pre_mul[2] = ri->get_pre_mul(2) / camwb_blue; + for (int c = 0; c < 3; c++) { + if (dmax < pre_mul[c]) + dmax = pre_mul[c]; + } + for (int c = 0; c < 3; c++) { + pre_mul[c] /= dmax; + } + camwb_red *= dmax; + camwb_green *= dmax; + camwb_blue *= dmax; + for (int c = 0; c < 3; c++) { + int sat = ri->get_white(c) - ri->get_cblack(c); + scale_mul[c] = pre_mul[c] * 65535.0 / sat; + } + scale_mul[3] = pre_mul[1] * 65535.0 / (ri->get_white(3) - ri->get_cblack(3)); + initialGain = 1.0 / min(pre_mul[0], pre_mul[1], pre_mul[2]); + }*/ + ri->set_prefilters(); @@ -2224,15 +2273,15 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { if (ri->isBayer()) { for (int j=start; jISGREEN(i,j)) tmphistogram[CLIP((int)(camwb_green*rawData[i][j]))>>histcompr]+=4; - else if (ri->ISRED(i,j)) tmphistogram[CLIP((int)(camwb_red* rawData[i][j]))>>histcompr]+=4; - else if (ri->ISBLUE(i,j)) tmphistogram[CLIP((int)(camwb_blue* rawData[i][j]))>>histcompr]+=4; + if (ri->ISGREEN(i,j)) tmphistogram[CLIP((int)(refwb_green*rawData[i][j]))>>histcompr]+=4; + else if (ri->ISRED(i,j)) tmphistogram[CLIP((int)(refwb_red* rawData[i][j]))>>histcompr]+=4; + else if (ri->ISBLUE(i,j)) tmphistogram[CLIP((int)(refwb_blue* rawData[i][j]))>>histcompr]+=4; } } else { for (int j=start; j>histcompr]++; - tmphistogram[CLIP((int)(camwb_green*rawData[i][3*j+1]))>>histcompr]+=2; - tmphistogram[CLIP((int)(camwb_blue* rawData[i][3*j+2]))>>histcompr]++; + tmphistogram[CLIP((int)(refwb_red* rawData[i][3*j+0]))>>histcompr]++; + tmphistogram[CLIP((int)(refwb_green*rawData[i][3*j+1]))>>histcompr]+=2; + tmphistogram[CLIP((int)(refwb_blue* rawData[i][3*j+2]))>>histcompr]++; } } } @@ -2433,9 +2482,9 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end) { // return ColorTemp (pow(avg_r/rn, 1.0/6.0)*img_r, pow(avg_g/gn, 1.0/6.0)*img_g, pow(avg_b/bn, 1.0/6.0)*img_b); - double reds = avg_r/rn * camwb_red; - double greens = avg_g/gn * camwb_green; - double blues = avg_b/bn * camwb_blue; + double reds = avg_r/rn * refwb_red; + double greens = avg_g/gn * refwb_green; + double blues = avg_b/bn * refwb_blue; redAWBMul = rm = imatrices.rgb_cam[0][0]*reds + imatrices.rgb_cam[0][1]*greens + imatrices.rgb_cam[0][2]*blues; greenAWBMul = gm = imatrices.rgb_cam[1][0]*reds + imatrices.rgb_cam[1][1]*greens + imatrices.rgb_cam[1][2]*blues; @@ -2560,9 +2609,9 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end) { return ColorTemp (equal); } else { - reds = reds/rn * camwb_red; - greens = greens/rn * camwb_green; - blues = blues/rn * camwb_blue; + reds = reds/rn * refwb_red; + greens = greens/rn * refwb_green; + blues = blues/rn * refwb_blue; double rm = imatrices.rgb_cam[0][0]*reds + imatrices.rgb_cam[0][1]*greens + imatrices.rgb_cam[0][2]*blues; double gm = imatrices.rgb_cam[1][0]*reds + imatrices.rgb_cam[1][1]*greens + imatrices.rgb_cam[1][2]*blues; diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 5ecf11b62..ca4f22bcb 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -72,14 +72,14 @@ class RawImageSource : public ImageSource { MyMutex getImageMutex; // locks getImage int W, H; - ColorTemp wb; + ColorTemp camera_wb; ProgressListener* plistener; float scale_mul[4]; // multiplier for each color float c_black[4]; // copy of cblack Dcraw for black level float cblacksom[4]; - double camwb_red; - double camwb_green; - double camwb_blue; + double refwb_red; + double refwb_green; + double refwb_blue; double rgb_cam[3][3]; double cam_rgb[3][3]; double xyz_cam[3][3]; @@ -153,7 +153,7 @@ class RawImageSource : public ImageSource { void scaleColors (int winx,int winy,int winw,int winh, const RAWParams &raw);// raw for cblack void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw); - ColorTemp getWB () { return wb; } + ColorTemp getWB () { return camera_wb; } void getAutoWBMultipliers (double &rm, double &gm, double &bm); ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal); bool isWBProviderReady () { return rawData; } @@ -174,7 +174,7 @@ class RawImageSource : public ImageSource { void getAutoExpHistogram (LUTu & histogram, int& histcompr); void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); - void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, RAWParams raw); + void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw); //static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName); static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, ColorTemp &wb, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) { colorSpaceConversion (im, cmp, wb, 0.0f, embedded, camprofile, cam, camName); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index bb05ea3db..b21802960 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -125,7 +125,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (params.dirpyrDenoise.enabled) { ipf.RGB_denoise(baseImg, baseImg, imgsrc->isRAW(), params.dirpyrDenoise, params.defringe, imgsrc->getDirPyrDenoiseExpComp()); } - imgsrc->convertColorSpace(baseImg, params.icm, params.raw); + imgsrc->convertColorSpace(baseImg, params.icm, currWB, params.raw); // perform first analysis LUTu hist16 (65536); diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc old mode 100644 new mode 100755 index 96e226cf0..9bf54b17b --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -211,7 +211,7 @@ void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre image->vflip(); } -void StdImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, RAWParams raw) { +void StdImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw) { colorSpaceConversion (image, cmp, embProfile, img->getSampleFormat()); } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index a4766aa2c..afca09492 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -65,7 +65,7 @@ class StdImageSource : public ImageSource { void setProgressListener (ProgressListener* pl) { plistener = pl; } - void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, RAWParams raw);// RAWParams raw will not be used for non-raw files (see imagesource.h) + void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb, RAWParams raw);// RAWParams raw will not be used for non-raw files (see imagesource.h) static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); //static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded);