New highlight recovery method

ported from DCRAW in teamwork with Jacques, see issue #697
This commit is contained in:
Oliver Duis 2011-05-27 16:31:20 +02:00
parent ae0cfe4d9d
commit cd16505cbc
4 changed files with 87 additions and 4 deletions

View File

@ -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

View File

@ -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<width; col++) {
float rgb[ColorCount], cam[2][ColorCount], lab[2][ColorCount], sum[2], chratio;
// Copy input pixel to rgb so it's easier to access in loops
rgb[0] = rin[col]; rgb[1] = gin[col]; rgb[2] = bin[col];
// If no channel is clipped, do nothing on pixel
int c;
for (c=0; c<ColorCount; c++) { if (rgb[c] > 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 );}
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View File

@ -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;

View File

@ -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 () {