From cd16505cbcd216a4329fece734bd02096352e24b Mon Sep 17 00:00:00 2001 From: Oliver Duis Date: Fri, 27 May 2011 16:31:20 +0200 Subject: [PATCH] New highlight recovery method ported from DCRAW in teamwork with Jacques, see issue #697 --- rtdata/languages/default | 1 + rtengine/rawimagesource.cc | 78 +++++++++++++++++++++++++++++++++++++- rtengine/rawimagesource.h | 3 +- rtgui/hlrec.cc | 9 ++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 1e7995542..83dd58ef9 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -767,6 +767,7 @@ TP_HLREC_CIELAB;CIELab Blending TP_HLREC_COLOR;Color Propagation TP_HLREC_LABEL;Highlight Reconstruction TP_HLREC_LUMINANCE;Luminance Recovery +TP_HLREC_BLEND;Blend TP_HLREC_METHOD;Method: TP_HSVEQUALIZER1;Red TP_HSVEQUALIZER2;Yellow diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 9285c8a37..2d0a9e36e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -355,7 +355,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre } if (hrp.enabled) - hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip); + hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw); transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw); @@ -1744,7 +1744,76 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// derived from Dcraw "blend_highlights()" +// very effective to reduce (or remove) the magenta, but with levels of grey ! +void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int width, float maxval, float* pre_mul, const RAWParams &raw) +{ + const int ColorCount=3; + int clip=INT_MAX; + // Transform matrixes rgb>lab and back + static const float trans[2][ColorCount][ColorCount] = + { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } }, + { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; + static const float itrans[2][ColorCount][ColorCount] = + { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } }, + { { 1,1,1 }, { 1,-1,1 }, { 1,1,-1 } } }; + +#define FOREACHCOLOR for (int c=0; c < ColorCount; c++) +#define SQR(x) ((x)*(x)) + + // Determine the maximum level (clip) of all channels + int i; + FOREACHCOLOR if (clip > (i = (int) maxval * pre_mul[c] * raw.expos)) clip = i; + +#pragma omp parallel for + for (int col=0; col clip) break; } + if (c == ColorCount) continue; + + // Initialize cam with raw input [0] and potentially clipped input [1] + FOREACHCOLOR { + cam[0][c] = rgb[c]; + cam[1][c] = MIN(cam[0][c],clip); + } + + // Calculate the lightness correction ration (chratio) + for (int i=0; i<2; i++) { + FOREACHCOLOR { + lab[i][c]=0; + for (int j=0; j < ColorCount; j++) + lab[i][c] += trans[ColorCount-3][c][j] * cam[i][j]; + } + + sum[i]=0; + for (int c=1; c < ColorCount; c++) + sum[i] += SQR(lab[i][c]); + } + chratio = sqrt(sum[1]/sum[0]); + + // Apply ratio to lightness in lab space + for (int c=1; c < ColorCount; c++) lab[0][c] *= chratio; + + // Transform back from lab to RGB + FOREACHCOLOR { + cam[0][c]=0; + for (int j=0; j < ColorCount; j++) { + cam[0][c] += itrans[ColorCount-3][c][j] * lab[0][j]; + } + } + FOREACHCOLOR rgb[c] = cam[0][c] / ColorCount; + + // Copy converted pixel back + rin[col]=rgb[0]; gin[col]=rgb[1]; bin[col]=rgb[2]; + } +} void RawImageSource::HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval) { @@ -1838,7 +1907,7 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip) { +void RawImageSource::hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip,const RAWParams &raw ) { if (method=="Luminance") HLRecovery_Luminance (red, green, blue, red, green, blue, width, 65535.0); @@ -1846,6 +1915,11 @@ void RawImageSource::hlRecovery (std::string method, float* red, float* green, f HLRecovery_CIELab (red, green, blue, red, green, blue, width, 65535.0, xyz_cam, cam_xyz); else if (method=="Color") HLRecovery_ColorPropagation (red, green, blue, i, sx1, width, skip); + else if (method=="Blend") // derived from Dcraw + { float pre_mul[4]; + for(int c=0;c<4;c++) pre_mul[c]=ri->get_pre_mul(c); + HLRecovery_blend(red, green, blue, width, 65535.0, pre_mul, raw );} + } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 594d1fc8d..23c4fcc36 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -99,7 +99,7 @@ class RawImageSource : public ImageSource { void hphd_horizontal (float** hpmap, int row_from, int row_to); void hphd_green (float** hpmap); void correction_YIQ_LQ_ (Imagefloat* im, int row_from, int row_to); - void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip); + void hlRecovery (std::string method, float* red, float* green, float* blue, int i, int sx1, int width, int skip, const RAWParams &raw); int defTransform (int tran); void rotateLine (float* line, float** channel, int tran, int i, int w, int h); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); @@ -144,6 +144,7 @@ class RawImageSource : public ImageSource { static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval); static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]); + static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* pre_mul, const RAWParams &raw); protected: typedef unsigned short ushort; diff --git a/rtgui/hlrec.cc b/rtgui/hlrec.cc index 378caf57d..d5c18422e 100644 --- a/rtgui/hlrec.cc +++ b/rtgui/hlrec.cc @@ -32,6 +32,8 @@ HLRecovery::HLRecovery () : Gtk::VBox(), FoldableToolPanel(this) { method->append_text (M("TP_HLREC_LUMINANCE")); method->append_text (M("TP_HLREC_CIELAB")); method->append_text (M("TP_HLREC_COLOR")); + method->append_text (M("TP_HLREC_BLEND")); + method->set_active (0); Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_HLREC_METHOD"))); @@ -57,13 +59,15 @@ void HLRecovery::read (const ProcParams* pp, const ParamsEdited* pedited) { enaconn.block (false); if (pedited && !pedited->hlrecovery.method) - method->set_active (3); + method->set_active (4); else if (pp->hlrecovery.method=="Luminance") method->set_active (0); else if (pp->hlrecovery.method=="CIELab blending") method->set_active (1); else if (pp->hlrecovery.method=="Color") method->set_active (2); + else if (pp->hlrecovery.method=="Blend") + method->set_active (3); lastEnabled = pp->hlrecovery.enabled; @@ -84,6 +88,9 @@ void HLRecovery::write (ProcParams* pp, ParamsEdited* pedited) { pp->hlrecovery.method = "CIELab blending"; else if (method->get_active_row_number()==2) pp->hlrecovery.method = "Color"; + else if (method->get_active_row_number()==3) + pp->hlrecovery.method = "Blend"; + } void HLRecovery::enabledChanged () {