From 874ed1245517c14004813e23ff4ffe970d251cbd Mon Sep 17 00:00:00 2001 From: Emil Martinec Date: Fri, 24 Sep 2010 14:48:01 -0500 Subject: [PATCH] Patch to fix auto white balance and spot balance behavior. Previous code used the average of the sixth power of tonal values to determine the average tonality, giving far too much weight to highlights; in addition there was no exclusion of clipped regions, which combined with the sixth power averaging resulted in WB being determined almost entirely by clipped patches (eg blown skies). The present patch excludes blown regions from the autoWB routine, and uses a simple average of tonal values to determine the WB. Also, a similar patch to prevent the use of blown regions to determine spot WB was added; if the spot color picker is set on a blown region, the WB is not changed. --- rtengine/improccoordinator.cc | 10 +- rtengine/rawimagesource.cc | 339 +++++++++++++++++----------------- 2 files changed, 182 insertions(+), 167 deletions(-) diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 3f12e2cd8..e361afec4 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -450,9 +450,15 @@ void ImProcCoordinator::getSpotWB (int x, int y, int rect, double& temp, double& if (params.coarse.vflip) tr |= TR_VFLIP; ColorTemp ret = imgsrc->getSpotWB (red, green, blue, tr); + currWB = ColorTemp (params.wb.temperature, params.wb.green); mProcessing.unlock (); - temp = ret.getTemp (); - tgreen = ret.getGreen (); + if (ret.getTemp() > 0) { + temp = ret.getTemp (); + tgreen = ret.getGreen (); + } else { + temp = currWB.getTemp (); + tgreen = currWB.getGreen (); + } } void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &h) { diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 1fd0d9740..7b6be804d 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1815,111 +1815,114 @@ int RawImageSource::getAEHistogram (unsigned int* histogram, int& histcompr) { } } return 1; -} - -ColorTemp RawImageSource::getAutoWB () { - - double avg_r = 0; - double avg_g = 0; - double avg_b = 0; - int rn = 0, gn = 0, bn = 0; - - if (fuji) { - for (int i=32; iheight-32; i++) { - int fw = ri->fuji_width; - int start = ABS(fw-i) + 32; - int end = MIN(ri->height+ri->width-fw-i, fw+i) - 32; - for (int j=start; jfilters) { - double d = CLIP(ri->defgain*ri->data[i][3*j]); - if (d>64000) - continue; - avg_r += d*d*d*d*d*d; rn++; - d = CLIP(ri->defgain*ri->data[i][3*j+1]); - if (d>64000) - continue; - avg_g += d*d*d*d*d*d; gn++; - d = CLIP(ri->defgain*ri->data[i][3*j+2]); - if (d>64000) - continue; - avg_b += d*d*d*d*d*d; bn++; - } - else { - double d = CLIP(ri->defgain*ri->data[i][j]); - if (d>64000) - continue; - double dp = d*d*d*d*d*d; - if (ISRED(ri,i,j)) { - avg_r += dp; - rn++; - } - else if (ISGREEN(ri,i,j)) { - avg_g += dp; - gn++; - } - else if (ISBLUE(ri,i,j)) { - avg_b += dp; - bn++; - } - } - } - } - } - else { - for (int i=32; iheight-32; i++) - for (int j=32; jwidth-32; j++) { - if (!ri->filters) { - double d = CLIP(ri->defgain*ri->data[i][3*j]); - if (d>64000) - continue; - avg_r += d*d*d*d*d*d; rn++; - d = CLIP(ri->defgain*ri->data[i][3*j+1]); - if (d>64000) - continue; - avg_g += d*d*d*d*d*d; gn++; - d = CLIP(ri->defgain*ri->data[i][3*j+2]); - if (d>64000) - continue; - avg_b += d*d*d*d*d*d; bn++; - } - else { - double d = CLIP(ri->defgain*ri->data[i][j]); - if (d>64000) - continue; - double dp = d*d*d*d*d*d; - if (ISRED(ri,i,j)) { - avg_r += dp; - rn++; - } - else if (ISGREEN(ri,i,j)) { - avg_g += dp; - gn++; - } - else if (ISBLUE(ri,i,j)) { - avg_b += dp; - bn++; - } - } - } - } - - printf ("AVG: %g %g %g\n", avg_r/rn, avg_g/gn, avg_b/bn); - -// double img_r, img_g, img_b; -// wb.getMultipliers (img_r, img_g, img_b); - -// 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 = pow (avg_r/rn, 1.0/6.0) * ri->camwb_red; - double greens = pow (avg_g/gn, 1.0/6.0) * ri->camwb_green; - double blues = pow (avg_b/bn, 1.0/6.0) * ri->camwb_blue; - - double rm = coeff[0][0]*reds + coeff[0][1]*greens + coeff[0][2]*blues; - double gm = coeff[1][0]*reds + coeff[1][1]*greens + coeff[1][2]*blues; - double bm = coeff[2][0]*reds + coeff[2][1]*greens + coeff[2][2]*blues; - - return ColorTemp (rm, gm, bm); -} +} + + ColorTemp RawImageSource::getAutoWB () { + + double avg_r = 0; + double avg_g = 0; + double avg_b = 0; + int rn = 0, gn = 0, bn = 0; + + if (fuji) { + for (int i=32; iheight-32; i++) { + int fw = ri->fuji_width; + int start = ABS(fw-i) + 32; + int end = MIN(ri->height+ri->width-fw-i, fw+i) - 32; + for (int j=start; jfilters) { + double d = CLIP(ri->defgain*ri->data[i][3*j]); + if (d>64000) + continue; + avg_r += d; rn++; + d = CLIP(ri->defgain*ri->data[i][3*j+1]); + if (d>64000) + continue; + avg_g += d; gn++; + d = CLIP(ri->defgain*ri->data[i][3*j+2]); + if (d>64000) + continue; + avg_b += d; bn++; + } + else { + double d = CLIP(ri->defgain*ri->data[i][j]); + if (d>64000) + continue; + double dp = d; + if (ISRED(ri,i,j)) { + avg_r += dp; + rn++; + } + else if (ISGREEN(ri,i,j)) { + avg_g += dp; + gn++; + } + else if (ISBLUE(ri,i,j)) { + avg_b += dp; + bn++; + } + } + } + } + } + else { + if (!ri->filters) { + for (int i=32; iheight-32; i++) + for (int j=32; jwidth-32; j++) { + double dr = CLIP(ri->defgain*ri->data[i][3*j]); + double dg = CLIP(ri->defgain*ri->data[i][3*j+1]); + double db = CLIP(ri->defgain*ri->data[i][3*j+2]); + if (dr>64000 || dg>64000 || db>64000) continue; + avg_r += dr; rn++; + avg_g += dg; + avg_b += db; + } + gn = rn; bn=rn; + } else { + //determine GRBG coset; (ey,ex) is the offset of the R subarray + int ey, ex; + if (ISGREEN(ri,0,0)) {//first pixel is G + if (ISRED(ri,0,1)) {ey=0; ex=1;} else {ey=1; ex=0;} + } else {//first pixel is R or B + if (ISRED(ri,0,0)) {ey=0; ex=0;} else {ey=1; ex=1;} + } + double d[2][2]; + for (int i=32; iheight-32; i+=2) + for (int j=32; jwidth-32; j+=2) { + //average a Bayer quartet if nobody is clipped + d[0][0] = CLIP(ri->defgain*ri->data[i][j]); + d[0][1] = CLIP(ri->defgain*ri->data[i][j+1]); + d[1][0] = CLIP(ri->defgain*ri->data[i+1][j]); + d[1][1] = CLIP(ri->defgain*ri->data[i+1][j+1]); + if ( d[0][0]>64000 || d[0][1]>64000 || d[1][0]>64000 || d[1][1]>64000 ) continue; + avg_r += d[ey][ex]; + avg_g += d[1-ey][ex] + d[ey][1-ex]; + avg_b += d[1-ey][1-ex]; + rn++; + } + gn = 2*rn; + bn = rn; + } + } + + printf ("AVG: %g %g %g\n", avg_r/rn, avg_g/gn, avg_b/bn); + + // double img_r, img_g, img_b; + // wb.getMultipliers (img_r, img_g, img_b); + + // 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 * ri->camwb_red; + double greens = avg_g/gn * ri->camwb_green; + double blues = avg_b/bn * ri->camwb_blue; + + double rm = coeff[0][0]*reds + coeff[0][1]*greens + coeff[0][2]*blues; + double gm = coeff[1][0]*reds + coeff[1][1]*greens + coeff[1][2]*blues; + double bm = coeff[2][0]*reds + coeff[2][1]*greens + coeff[2][2]*blues; + + return ColorTemp (rm, gm, bm); + } + void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& tty) { @@ -1977,77 +1980,83 @@ void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& t tty = ty; } } + ColorTemp RawImageSource::getSpotWB (std::vector red, std::vector green, std::vector& blue, int tran) { int x; int y; - int d[9][2] = {{0,0}, {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}}; double reds = 0, greens = 0, blues = 0; - int rn = 0, gn = 0, bn = 0; + int rn = 0; if (!ri->filters) { + int xmin, xmax, ymin, ymax; + int xr, xg, xb, yr, yg, yb; for (int i=0; i=0 && y>=0 && xdata[y][3*x]; - rn++; - } - transformPosition (green[i].x, green[i].y, tran, x, y); - if (x>=0 && y>=0 && xdata[y][3*x+1]; - gn++; - } - transformPosition (blue[i].x, blue[i].y, tran, x, y); - if (x>=0 && y>=0 && xdata[y][3*x+2]; - bn++; + transformPosition (red[i].x, red[i].y, tran, xr, yr); + transformPosition (green[i].x, green[i].y, tran, xg, yg); + transformPosition (blue[i].x, blue[i].y, tran, xb, yb); + if (ri->defgain*ri->data[y][3*x]>52500 || ri->defgain*ri->data[y][3*x+1]>52500 || ri->defgain*ri->data[y][3*x+2]>52500) continue; + xmin = MIN(xr,MIN(xg,xb)); + xmax = MAX(xr,MAX(xg,xb)); + ymin = MIN(yr,MIN(yg,yb)); + ymax = MAX(yr,MAX(yg,yb)); + if (xmin>=0 && ymin>=0 && xmaxdata[yr][3*xr]; + greens += ri->data[yg][3*xg+1]; + blues += ri->data[yb][3*xb+2]; + rn++; } } + + } else { + + int d[9][2] = {{0,0}, {-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}}; + int rloc, gloc, bloc, rnbrs, gnbrs, bnbrs; + for (int i=0; i=0 && yv>=0 && xvdata[yv][xv]; + rnbrs++; + continue; + } + if (ISGREEN(ri,yv,xv) && xv>=0 && yv>=0 && xvdata[yv][xv]; + gnbrs++; + continue; + } + if (ISBLUE(ri,yv,xv) && xv>=0 && yv>=0 && xvdata[yv][xv]; + bnbrs++; + continue; + } + } + rloc /= rnbrs; gloc /= gnbrs; bloc /= bnbrs; + if (rloc*ri->defgain<64000 && gloc*ri->defgain<64000 && bloc*ri->defgain<64000) { + reds += rloc; greens += gloc; blues += bloc; rn++; + } + //transformPosition (green[i].x, green[i].y, tran, x, y);//these are redundant now ??? if not, repeat for these blocks same as for red[] + //transformPosition (blue[i].x, blue[i].y, tran, x, y); + } } - else { - for (int i=0; i=0 && yv>=0 && xvdata[yv][xv]; - rn++; - break; - } - } - transformPosition (green[i].x, green[i].y, tran, x, y); - for (int k=0; k<9; k++) { - int xv = x + d[k][0]; - int yv = y + d[k][1]; - if (ISGREEN(ri,yv,xv) && xv>=0 && yv>=0 && xvdata[yv][xv]; - gn++; - break; - } - } - transformPosition (blue[i].x, blue[i].y, tran, x, y); - for (int k=0; k<9; k++) { - int xv = x + d[k][0]; - int yv = y + d[k][1]; - if (ISBLUE(ri,yv,xv) && xv>=0 && yv>=0 && xvdata[yv][xv]; - bn++; - break; - } - } - } - } - - reds = reds/rn * ri->camwb_red; - greens = greens/gn * ri->camwb_green; - blues = blues/bn * ri->camwb_blue; - - double rm = coeff[0][0]*reds + coeff[0][1]*greens + coeff[0][2]*blues; - double gm = coeff[1][0]*reds + coeff[1][1]*greens + coeff[1][2]*blues; - double bm = coeff[2][0]*reds + coeff[2][1]*greens + coeff[2][2]*blues; - - return ColorTemp (rm, gm, bm); + + if (2*rn < red.size()) { + return ColorTemp (); + } + else { + reds = reds/rn * ri->camwb_red; + greens = greens/rn * ri->camwb_green; + blues = blues/rn * ri->camwb_blue; + + double rm = coeff[0][0]*reds + coeff[0][1]*greens + coeff[0][2]*blues; + double gm = coeff[1][0]*reds + coeff[1][1]*greens + coeff[1][2]*blues; + double bm = coeff[2][0]*reds + coeff[2][1]*greens + coeff[2][2]*blues; + + return ColorTemp (rm, gm, bm); + } } #define FORCC for (c=0; c < colors; c++)