Pipette and "On Preview Widgets" branch. See issue 227
The pipette part is already working quite nice but need to be finished. The widgets part needs more work...
This commit is contained in:
859
rtengine/hilite_recon.cc
Normal file
859
rtengine/hilite_recon.cc
Normal file
@@ -0,0 +1,859 @@
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Highlight reconstruction
|
||||
//
|
||||
// copyright (c) 2008-2011 Emil Martinec <ejmartin@uchicago.edu>
|
||||
//
|
||||
//
|
||||
// code dated: June 16, 2011
|
||||
//
|
||||
// hilite_recon.cc is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//#include "rtengine.h"
|
||||
#include <cstddef>
|
||||
#include <cmath>
|
||||
#include "curves.h"
|
||||
#include "array2D.h"
|
||||
#include "improcfun.h"
|
||||
#include "rawimagesource.h"
|
||||
//#include "stack1.h"
|
||||
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "rt_math.h"
|
||||
#include "rawimagesource.h"
|
||||
#ifdef __SSE2__
|
||||
#include "sleefsseavx.c"
|
||||
#endif // __SSE2__
|
||||
|
||||
|
||||
|
||||
|
||||
#define FOREACHCOLOR for (int c=0; c < ColorCount; c++)
|
||||
|
||||
//#include "RGBdefringe.cc"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
#if defined( __SSE2__ ) && defined( WIN32 )
|
||||
__attribute__((force_align_arg_pointer)) void RawImageSource::boxblur2(float** src, float** dst, int H, int W, int box )
|
||||
#else
|
||||
void RawImageSource::boxblur2(float** src, float** dst, int H, int W, int box )
|
||||
#endif
|
||||
{
|
||||
|
||||
array2D<float> temp(W,H);
|
||||
|
||||
//box blur image channel; box size = 2*box+1
|
||||
//horizontal blur
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int row = 0; row < H; row++) {
|
||||
int len = box + 1;
|
||||
temp[row][0] = src[row][0]/len;
|
||||
for (int j=1; j<=box; j++) {
|
||||
temp[row][0] += src[row][j]/len;
|
||||
}
|
||||
for (int col=1; col<=box; col++) {
|
||||
temp[row][col] = (temp[row][col-1]*len + src[row][col+box])/(len+1);
|
||||
len ++;
|
||||
}
|
||||
for (int col = box+1; col < W-box; col++) {
|
||||
temp[row][col] = temp[row][col-1] + (src[row][col+box] - src[row][col-box-1])/len;
|
||||
}
|
||||
for (int col=W-box; col<W; col++) {
|
||||
temp[row][col] = (temp[row][col-1]*len - src[row][col-box-1])/(len-1);
|
||||
len --;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __SSE2__
|
||||
//vertical blur
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel
|
||||
#endif
|
||||
{
|
||||
float len = box + 1;
|
||||
__m128 lenv = _mm_set1_ps( len );
|
||||
__m128 lenp1v = _mm_set1_ps( len + 1.0f );
|
||||
__m128 onev = _mm_set1_ps( 1.0f );
|
||||
__m128 tempv;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp for
|
||||
#endif
|
||||
for (int col = 0; col < W-3; col+=4) {
|
||||
tempv = LVFU(temp[0][col]) / lenv;
|
||||
for (int i=1; i<=box; i++) {
|
||||
tempv = tempv + LVFU(temp[i][col]) / lenv;
|
||||
}
|
||||
_mm_storeu_ps( &dst[0][col], tempv);
|
||||
for (int row=1; row<=box; row++) {
|
||||
_mm_storeu_ps( &dst[row][col], (LVFU(dst[(row-1)][col])*lenv + LVFU(temp[(row+box)][col]))/lenp1v);
|
||||
lenv = lenp1v;
|
||||
lenp1v = lenp1v + onev;
|
||||
}
|
||||
for (int row = box+1; row < H-box; row++) {
|
||||
_mm_storeu_ps( &dst[row][col], LVFU(dst[(row-1)][col]) + (LVFU(temp[(row+box)][col]) - LVFU(temp[(row-box-1)][col]))/lenv );
|
||||
}
|
||||
for (int row=H-box; row<H; row++) {
|
||||
lenp1v = lenv;
|
||||
lenv = lenv - onev;
|
||||
_mm_storeu_ps( &dst[row][col], (LVFU(dst[(row-1)][col])*lenp1v - LVFU(temp[(row-box-1)][col])) / lenv );
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int col = W-(W%4); col < W; col++) {
|
||||
int len = box + 1;
|
||||
dst[0][col] = temp[0][col]/len;
|
||||
for (int i=1; i<=box; i++) {
|
||||
dst[0][col] += temp[i][col]/len;
|
||||
}
|
||||
for (int row=1; row<=box; row++) {
|
||||
dst[row][col] = (dst[(row-1)][col]*len + temp[(row+box)][col])/(len+1);
|
||||
len ++;
|
||||
}
|
||||
for (int row = box+1; row < H-box; row++) {
|
||||
dst[row][col] = dst[(row-1)][col] + (temp[(row+box)][col] - temp[(row-box-1)][col])/len;
|
||||
}
|
||||
for (int row=H-box; row<H; row++) {
|
||||
dst[row][col] = (dst[(row-1)][col]*len - temp[(row-box-1)][col])/(len-1);
|
||||
len --;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
//vertical blur
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int col = 0; col < W; col++) {
|
||||
int len = box + 1;
|
||||
dst[0][col] = temp[0][col]/len;
|
||||
for (int i=1; i<=box; i++) {
|
||||
dst[0][col] += temp[i][col]/len;
|
||||
}
|
||||
for (int row=1; row<=box; row++) {
|
||||
dst[row][col] = (dst[(row-1)][col]*len + temp[(row+box)][col])/(len+1);
|
||||
len ++;
|
||||
}
|
||||
for (int row = box+1; row < H-box; row++) {
|
||||
dst[row][col] = dst[(row-1)][col] + (temp[(row+box)][col] - temp[(row-box-1)][col])/len;
|
||||
}
|
||||
for (int row=H-box; row<H; row++) {
|
||||
dst[row][col] = (dst[(row-1)][col]*len - temp[(row-box-1)][col])/(len-1);
|
||||
len --;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void RawImageSource::boxblur_resamp(float **src, float **dst, float & max_f, int H, int W, int box, int samp )
|
||||
{
|
||||
|
||||
array2D<float> temp((W/samp)+ ((W%samp)==0 ? 0 : 1),H);
|
||||
|
||||
float maxtmp=0.0f;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel
|
||||
#endif
|
||||
{
|
||||
float maxtmpthr = 0;
|
||||
float tempval;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp for
|
||||
#endif
|
||||
//box blur image channel; box size = 2*box+1
|
||||
//horizontal blur
|
||||
for (int row = 0; row < H; row++) {
|
||||
int len = box + 1;
|
||||
tempval = src[row][0]/len;
|
||||
maxtmpthr = max(maxtmpthr,src[row][0]);
|
||||
for (int j=1; j<=box; j++) {
|
||||
tempval += src[row][j]/len;
|
||||
maxtmpthr = max(maxtmpthr,src[row][j]);
|
||||
}
|
||||
temp[row][0] = tempval;
|
||||
for (int col=1; col<=box; col++) {
|
||||
tempval = (tempval*len + src[row][col+box])/(len+1);
|
||||
if(col%samp == 0)
|
||||
temp[row][col/samp] = tempval;
|
||||
maxtmpthr = max(maxtmpthr,src[row][col]);
|
||||
len ++;
|
||||
}
|
||||
for (int col = box+1; col < W-box; col++) {
|
||||
tempval = tempval + (src[row][col+box] - src[row][col-box-1])/len;
|
||||
if(col%samp == 0)
|
||||
temp[row][col/samp] = tempval;
|
||||
maxtmpthr = max(maxtmpthr,src[row][col]);
|
||||
}
|
||||
for (int col=W-box; col<W; col++) {
|
||||
tempval = (tempval*len - src[row][col-box-1])/(len-1);
|
||||
if(col%samp == 0)
|
||||
temp[row][col/samp] = tempval;
|
||||
maxtmpthr = max(maxtmpthr,src[row][col]);
|
||||
len --;
|
||||
}
|
||||
}
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical
|
||||
#endif
|
||||
{
|
||||
maxtmp = max(maxtmp,maxtmpthr);
|
||||
}
|
||||
}
|
||||
|
||||
max_f = maxtmp;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel
|
||||
#endif
|
||||
{
|
||||
float tempval;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp for
|
||||
#endif
|
||||
//vertical blur
|
||||
for (int col = 0; col < W/samp; col++) {
|
||||
int len = box + 1;
|
||||
tempval = temp[0][col]/len;
|
||||
for (int i=1; i<=box; i++) {
|
||||
tempval += temp[i][col]/len;
|
||||
}
|
||||
dst[0][col] = tempval;
|
||||
for (int row=1; row<=box; row++) {
|
||||
tempval = (tempval*len + temp[(row+box)][col])/(len+1);
|
||||
if(row%samp == 0)
|
||||
dst[row/samp][col] = tempval;
|
||||
len ++;
|
||||
}
|
||||
for (int row = box+1; row < H-box; row++) {
|
||||
tempval = tempval + (temp[(row+box)][col] - temp[(row-box-1)][col])/len;
|
||||
if(row%samp == 0)
|
||||
dst[row/samp][col] = tempval;
|
||||
}
|
||||
for (int row=H-box; row<H; row++) {
|
||||
tempval = (tempval*len - temp[(row-box-1)][col])/(len-1);
|
||||
if(row%samp == 0)
|
||||
dst[row/samp][col] = tempval;
|
||||
len --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** blue)
|
||||
{
|
||||
double progress = 0.0;
|
||||
|
||||
if (plistener) {
|
||||
plistener->setProgressStr ("HL reconstruction...");
|
||||
plistener->setProgress (progress);
|
||||
}
|
||||
|
||||
int height = H;
|
||||
int width = W;
|
||||
|
||||
const int range = 2;
|
||||
const int pitch = 4;
|
||||
|
||||
|
||||
int hfh = (height-(height%pitch))/pitch;
|
||||
int hfw = (width-(width%pitch))/pitch;
|
||||
|
||||
static const int numdirs = 4;
|
||||
|
||||
static const float threshpct = 0.25;
|
||||
static const float fixthreshpct = 0.7;
|
||||
static const float maxpct = 0.95;
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%
|
||||
//for blend algorithm:
|
||||
static const float blendthresh=1.0;
|
||||
const int ColorCount=3;
|
||||
// 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 } } };
|
||||
//%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
float max_f[3], thresh[3], fixthresh[3], norm[3];
|
||||
|
||||
//float red1, green1, blue1;//diagnostic
|
||||
float chmaxalt[4]={0,0,0,0};//diagnostic
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//halfsize demosaic
|
||||
|
||||
|
||||
multi_array2D<float,3> hfsize (hfw+1,hfh+1,ARRAY2D_CLEAR_DATA);
|
||||
|
||||
boxblur_resamp(red,hfsize[0],chmaxalt[0],height,width,range,pitch);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
boxblur_resamp(green,hfsize[1],chmaxalt[1],height,width,range,pitch);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
boxblur_resamp(blue,hfsize[2],chmaxalt[2],height,width,range,pitch);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
//blur image
|
||||
//for (int m=0; m<3; m++)
|
||||
// boxblur2(hfsize[m],hfsizeblur[m],hfh,hfw,3);
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
for (int c=0; c<3; c++) {
|
||||
thresh[c] = chmax[c]*threshpct;
|
||||
fixthresh[c] = chmax[c]*fixthreshpct;
|
||||
max_f[c] = chmax[c]*maxpct;//min(chmax[0],chmax[1],chmax[2])*maxpct;
|
||||
norm[c] = 1.0/(max_f[c]-fixthresh[c]);
|
||||
}
|
||||
float whitept = max(max_f[0],max_f[1],max_f[2]);
|
||||
float clippt = min(max_f[0],max_f[1],max_f[2]);
|
||||
float medpt = max_f[0]+max_f[1]+max_f[2]-whitept-clippt;
|
||||
float blendpt = blendthresh*clippt;
|
||||
|
||||
float camwb[4];
|
||||
for (int c=0; c<4; c++) camwb[c]=ri->get_cam_mul(c);
|
||||
|
||||
multi_array2D<float,3> channelblur(width,height,ARRAY2D_CLEAR_DATA);
|
||||
multi_array2D<float,5> hilite_full(width,height,ARRAY2D_CLEAR_DATA);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
// blur RGB channels
|
||||
boxblur2(red ,channelblur[0],height,width,4);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
boxblur2(green,channelblur[1],height,width,4);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
boxblur2(blue ,channelblur[2],height,width,4);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
float hipass_sum=0, hipass_norm=0.00;
|
||||
|
||||
// set up which pixels are clipped or near clipping
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for reduction(+:hipass_sum,hipass_norm)
|
||||
#endif
|
||||
for (int i=0; i<height; i++) {
|
||||
for (int j=0; j<width; j++) {
|
||||
|
||||
//if one or more channels is highlight but none are blown, add to highlight accumulator
|
||||
|
||||
if ((red[i][j]>thresh[0] || green[i][j]>thresh[1] || blue[i][j]>thresh[2]) &&
|
||||
(red[i][j]<max_f[0] && green[i][j]<max_f[1] && blue[i][j]<max_f[2])) {
|
||||
|
||||
hipass_sum += fabs(channelblur[0][i][j]-red[i][j]) + fabs(channelblur[1][i][j]-green[i][j]) + fabs(channelblur[2][i][j]-blue[i][j]);
|
||||
hipass_norm++;
|
||||
|
||||
hilite_full[0][i][j] = red[i][j];
|
||||
hilite_full[1][i][j] = green[i][j];
|
||||
hilite_full[2][i][j] = blue[i][j];
|
||||
hilite_full[3][i][j] = 1;
|
||||
hilite_full[4][i][j] = 1;
|
||||
|
||||
}
|
||||
//if (i%100==0 && j%100==0)
|
||||
// printf("row=%d col=%d r=%f g=%f b=%f hilite=%f \n",i,j,hilite_full[0][i][j],hilite_full[1][i][j],hilite_full[2][i][j],hilite_full[3][i][j]);
|
||||
}
|
||||
}//end of filling highlight array
|
||||
|
||||
hipass_norm += 0.01;
|
||||
|
||||
float hipass_ave = (hipass_sum/hipass_norm);
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//blur highlight data
|
||||
boxblur2(hilite_full[4],hilite_full[4],height,width,1);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=0; i<height; i++) {
|
||||
for (int j=0; j<width; j++) {
|
||||
|
||||
float hipass = fabs(channelblur[0][i][j]-red[i][j]) + fabs(channelblur[1][i][j]-green[i][j]) + fabs(channelblur[2][i][j]-blue[i][j]);
|
||||
|
||||
if (hipass > 2*hipass_ave) {
|
||||
//too much variation
|
||||
hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hilite_full[4][i][j]>0.00001 && hilite_full[4][i][j]<0.95) {
|
||||
//too near an edge, could risk using CA affected pixels, therefore omit
|
||||
hilite_full[0][i][j] = hilite_full[1][i][j] = hilite_full[2][i][j] = hilite_full[3][i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int c=0; c<3; c++) channelblur[c](1,1);//free up some memory
|
||||
|
||||
multi_array2D<float,4> hilite(hfw+1,hfh+1,ARRAY2D_CLEAR_DATA);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// blur and resample highlight data; range=size of blur, pitch=sample spacing
|
||||
for (int m=0; m<4; m++) {
|
||||
boxblur_resamp(hilite_full[m],hilite[m],chmaxalt[m],height,width,range,pitch);
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
}
|
||||
for (int c=0; c<5; c++) hilite_full[c](1,1);//free up some memory
|
||||
|
||||
multi_array2D<float,4*numdirs> hilite_dir(hfw,hfh,ARRAY2D_CLEAR_DATA);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//blur highlights
|
||||
//for (int m=0; m<4; m++)
|
||||
// boxblur2(hilite[m],hilite[m],hfh,hfw,4);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
LUTf invfn(0x10000);
|
||||
|
||||
for (int i=0; i<0x10000; i++)
|
||||
invfn[i] = 1.0/(1.0+i);
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
//fill gaps in highlight map by directional extension
|
||||
//raster scan from four corners
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j=1; j<hfw-1; j++)
|
||||
for (int i=2; i<hfh-2; i++) {
|
||||
//from left
|
||||
if (hilite[3][i][j]>0.01) {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[c][i][j] = hilite[c][i][j]/hilite[3][i][j];
|
||||
}
|
||||
} else {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[c][i][j] = 0.1*((hilite_dir[0+c][i-2][j-1]+hilite_dir[0+c][i-1][j-1]+hilite_dir[0+c][i][j-1]+hilite_dir[0+c][i+1][j-1]+hilite_dir[0+c][i+2][j-1])/
|
||||
(hilite_dir[0+3][i-2][j-1]+hilite_dir[0+3][i-1][j-1]+hilite_dir[0+3][i][j-1]+hilite_dir[0+3][i+1][j-1]+hilite_dir[0+3][i+2][j-1]+0.00001));
|
||||
hilite_dir[4+c][i][j+1] += hilite_dir[c][i][j];
|
||||
hilite_dir[8+c][i-2][j] += hilite_dir[c][i][j];
|
||||
hilite_dir[12+c][i+2][j] += hilite_dir[c][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int j=hfw-2; j>0; j--)
|
||||
for (int i=2; i<hfh-2; i++) {
|
||||
//from right
|
||||
if (hilite[3][i][j]>0.01) {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[4+c][i][j] = hilite[c][i][j]/hilite[3][i][j];
|
||||
}
|
||||
} else {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[4+c][i][j] = 0.1*((hilite_dir[4+c][(i-2)][(j+1)]+hilite_dir[4+c][(i-1)][(j+1)]+hilite_dir[4+c][(i)][(j+1)]+hilite_dir[4+c][(i+1)][(j+1)]+hilite_dir[4+c][(i+2)][(j+1)])/
|
||||
(hilite_dir[4+3][(i-2)][(j+1)]+hilite_dir[4+3][(i-1)][(j+1)]+hilite_dir[4+3][(i)][(j+1)]+hilite_dir[4+3][(i+1)][(j+1)]+hilite_dir[4+3][(i+2)][(j+1)]+0.00001));
|
||||
hilite_dir[8+c][i-2][j] += hilite_dir[4+c][i][j];
|
||||
hilite_dir[12+c][i+2][j] += hilite_dir[4+c][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=1; i<hfh-1; i++)
|
||||
for (int j=2; j<hfw-2; j++) {
|
||||
//if (i%100==0 && j%100==0)
|
||||
// printf("row=%d col=%d r=%f g=%f b=%f hilite=%f \n",i,j,hilite[0][i][j],hilite[1][i][j],hilite[2][i][j],hilite[3][i][j]);
|
||||
|
||||
//from top
|
||||
if (hilite[3][i][j]>0.01) {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[8+c][i][j] = hilite[c][i][j]/hilite[3][i][j];
|
||||
}
|
||||
} else {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[8+c][i][j] = 0.1*((hilite_dir[8+c][i-1][j-2]+hilite_dir[8+c][i-1][j-1]+hilite_dir[8+c][i-1][j]+hilite_dir[8+c][i-1][j+1]+hilite_dir[8+c][i-1][j+2])/
|
||||
(hilite_dir[8+3][i-1][j-2]+hilite_dir[8+3][i-1][j-1]+hilite_dir[8+3][i-1][j]+hilite_dir[8+3][i-1][j+1]+hilite_dir[8+3][i-1][j+2]+0.00001));
|
||||
hilite_dir[12+c][i+1][j] += hilite_dir[8+c][i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=hfh-2; i>0; i--)
|
||||
for (int j=2; j<hfw-2; j++) {
|
||||
//from bottom
|
||||
if (hilite[3][i][j]>0.01) {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[12+c][i][j] = hilite[c][i][j]/hilite[3][i][j];
|
||||
}
|
||||
} else {
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[12+c][i][j] = 0.1*((hilite_dir[12+c][(i+1)][(j-2)]+hilite_dir[12+c][(i+1)][(j-1)]+hilite_dir[12+c][(i+1)][(j)]+hilite_dir[12+c][(i+1)][(j+1)]+hilite_dir[12+c][(i+1)][(j+2)])/
|
||||
(hilite_dir[12+3][(i+1)][(j-2)]+hilite_dir[12+3][(i+1)][(j-1)]+hilite_dir[12+3][(i+1)][(j)]+hilite_dir[12+3][(i+1)][(j+1)]+hilite_dir[12+3][(i+1)][(j+2)]+0.00001));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
//fill in edges
|
||||
for (int dir=0; dir<numdirs; dir++) {
|
||||
for (int i=1; i<hfh-1; i++)
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[dir*4+c][i][0] = hilite_dir[dir*4+c][i][1];
|
||||
hilite_dir[dir*4+c][i][hfw-1] = hilite_dir[dir*4+c][i][hfw-2];
|
||||
}
|
||||
|
||||
for (int j=1; j<hfw-1; j++)
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[dir*4+c][0][j] = hilite_dir[dir*4+c][1][j];
|
||||
hilite_dir[dir*4+c][hfh-1][j] = hilite_dir[dir*4+c][hfh-2][j];
|
||||
}
|
||||
|
||||
for (int c=0; c<4; c++) {
|
||||
hilite_dir[dir*4+c][0][0] = hilite_dir[dir*4+c][1][0] = hilite_dir[dir*4+c][0][1] = hilite_dir[dir*4+c][1][1] = hilite_dir[dir*4+c][2][2];
|
||||
hilite_dir[dir*4+c][0][hfw-1] = hilite_dir[dir*4+c][1][hfw-1] = hilite_dir[dir*4+c][0][hfw-2] = hilite_dir[dir*4+c][1][hfw-2] = hilite_dir[dir*4+c][2][hfw-3];
|
||||
hilite_dir[dir*4+c][hfh-1][0] = hilite_dir[dir*4+c][hfh-2][0] = hilite_dir[dir*4+c][hfh-1][1] = hilite_dir[dir*4+c][hfh-2][1] = hilite_dir[dir*4+c][hfh-3][2];
|
||||
hilite_dir[dir*4+c][hfh-1][hfw-1] = hilite_dir[dir*4+c][hfh-2][hfw-1] = hilite_dir[dir*4+c][hfh-1][hfw-2] = hilite_dir[dir*4+c][hfh-2][hfw-2] = hilite_dir[dir*4+c][hfh-3][hfw-3];
|
||||
}
|
||||
}
|
||||
|
||||
if(plistener){
|
||||
progress += 0.05;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
/*for (int m=0; m<4*numdirs; m++) {
|
||||
boxblur2(hilite_dir[m],hilite_dir[m],hfh,hfw,4);
|
||||
}*/
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//now we have highlight data extended in various directions
|
||||
//next step is to build back local data by averaging
|
||||
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// now reconstruct clipped channels using color ratios
|
||||
|
||||
//const float Yclip = 0.3333*(max[0] + max[1] + max[2]);
|
||||
//float sumwt=0, counts=0;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int i=0; i<height; i++) {
|
||||
int i1 = min((i-(i%pitch))/pitch,hfh-1);
|
||||
for (int j=0; j<width; j++) {
|
||||
int j1 = min((j-(j%pitch))/pitch,hfw-1);
|
||||
|
||||
float pixel[3]={red[i][j],green[i][j],blue[i][j]};
|
||||
if (pixel[0]<max_f[0] && pixel[1]<max_f[1] && pixel[2]<max_f[2]) continue;//pixel not clipped
|
||||
//if (pixel[0]<fixthresh[0] && pixel[1]<fixthresh[1] && pixel[2]<fixthresh[2]) continue;//pixel not clipped
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%
|
||||
//estimate recovered values using modified HLRecovery_blend algorithm
|
||||
|
||||
float rgb[ColorCount], rgb_blend[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] = pixel[0]; rgb[1] = pixel[1]; rgb[2] = pixel[2];
|
||||
|
||||
// Initialize cam with raw input [0] and potentially clipped input [1]
|
||||
FOREACHCOLOR {
|
||||
cam[0][c] = rgb[c];
|
||||
cam[1][c] = min(cam[0][c],clippt);
|
||||
}
|
||||
|
||||
// Calculate the lightness correction ratio (chratio)
|
||||
for (int i2=0; i2<2; i2++) {
|
||||
FOREACHCOLOR {
|
||||
lab[i2][c]=0;
|
||||
for (int j=0; j < ColorCount; j++)
|
||||
lab[i2][c] += trans[ColorCount-3][c][j] * cam[i2][j];
|
||||
}
|
||||
|
||||
sum[i2]=0;
|
||||
for (int c=1; c < ColorCount; c++)
|
||||
sum[i2] += SQR(lab[i2][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
|
||||
float rfrac = min(1.0f,max(1.0f,max_f[0]/medpt)*(pixel[0]-blendpt)/(hlmax[0]-blendpt));
|
||||
float gfrac = min(1.0f,max(1.0f,max_f[1]/medpt)*(pixel[1]-blendpt)/(hlmax[1]-blendpt));
|
||||
float bfrac = min(1.0f,max(1.0f,max_f[2]/medpt)*(pixel[2]-blendpt)/(hlmax[2]-blendpt));
|
||||
if (pixel[0] > blendpt) rgb_blend[0]= rfrac*rgb[0]+(1-rfrac)*pixel[0];
|
||||
if (pixel[1] > blendpt) rgb_blend[1]= gfrac*rgb[1]+(1-gfrac)*pixel[1];
|
||||
if (pixel[2] > blendpt) rgb_blend[2]= bfrac*rgb[2]+(1-bfrac)*pixel[2];
|
||||
|
||||
//end of HLRecovery_blend estimation
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//float pixref[3]={min(Yclip,hfsize[0][i1][j1]),min(Yclip,hfsize[1][i1][j1]),min(Yclip,hfsize[2][i1][j1])};
|
||||
|
||||
//there are clipped highlights
|
||||
//first, determine weighted average of unclipped extensions (weighting is by 'hue' proximity)
|
||||
float dirwt, factor, Y;
|
||||
float totwt=0;//0.0003;
|
||||
float clipfix[3]={0,0,0};//={totwt*rgb_blend[0],totwt*rgb_blend[1],totwt*rgb_blend[2]};
|
||||
for (int dir=0; dir<numdirs; dir++) {
|
||||
float Yhi = 0.001+(hilite_dir[dir*4+0][i1][j1] + hilite_dir[dir*4+1][i1][j1] + hilite_dir[dir*4+2][i1][j1]);
|
||||
float Y = 0.001+(rgb_blend[0]+rgb_blend[1]+rgb_blend[2]);
|
||||
if (hilite_dir[dir*4+0][i1][j1]+hilite_dir[dir*4+1][i1][j1]+hilite_dir[dir*4+2][i1][j1]>0.5) {
|
||||
dirwt = invfn[65535*(SQR(rgb_blend[0]/Y-hilite_dir[dir*4+0][i1][j1]/Yhi) +
|
||||
SQR(rgb_blend[1]/Y-hilite_dir[dir*4+1][i1][j1]/Yhi) +
|
||||
SQR(rgb_blend[2]/Y-hilite_dir[dir*4+2][i1][j1]/Yhi))];
|
||||
totwt += dirwt;
|
||||
clipfix[0] += dirwt*hilite_dir[dir*4+0][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001);
|
||||
clipfix[1] += dirwt*hilite_dir[dir*4+1][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001);
|
||||
clipfix[2] += dirwt*hilite_dir[dir*4+2][i1][j1]/(hilite_dir[dir*4+3][i1][j1]+0.00001);
|
||||
}
|
||||
}
|
||||
clipfix[0] /= totwt;
|
||||
clipfix[1] /= totwt;
|
||||
clipfix[2] /= totwt;
|
||||
//sumwt += totwt;
|
||||
//counts ++;
|
||||
|
||||
//now correct clipped channels
|
||||
if (pixel[0]>max_f[0] && pixel[1]>max_f[1] && pixel[2]>max_f[2]) {
|
||||
//all channels clipped
|
||||
float Y = (0.299*clipfix[0] + 0.587*clipfix[1] + 0.114*clipfix[2]);
|
||||
//float Y = (clipfix[0] + clipfix[1] + clipfix[2]);
|
||||
factor = whitept/Y;
|
||||
red[i][j] = clipfix[0]*factor;
|
||||
green[i][j] = clipfix[1]*factor;
|
||||
blue[i][j] = clipfix[2]*factor;
|
||||
} else {//some channels clipped
|
||||
int notclipped[3] = {pixel[0]<max_f[0] ? 1 : 0, pixel[1]<max_f[1] ? 1 : 0, pixel[2]<max_f[2] ? 1 : 0};
|
||||
|
||||
if (notclipped[0]==0) {//red clipped
|
||||
red[i][j] = max(red[i][j],(clipfix[0]*((notclipped[1]*pixel[1] + notclipped[2]*pixel[2])/
|
||||
(notclipped[1]*clipfix[1] + notclipped[2]*clipfix[2]))));
|
||||
}
|
||||
if (notclipped[1]==0) {//green clipped
|
||||
green[i][j] = max(green[i][j],(clipfix[1]*((notclipped[2]*pixel[2] + notclipped[0]*pixel[0])/
|
||||
(notclipped[2]*clipfix[2] + notclipped[0]*clipfix[0]))));
|
||||
}
|
||||
if (notclipped[2]==0) {//blue clipped
|
||||
blue[i][j] = max(blue[i][j],(clipfix[2]*((notclipped[0]*pixel[0] + notclipped[1]*pixel[1])/
|
||||
(notclipped[0]*clipfix[0] + notclipped[1]*clipfix[1]))));
|
||||
}
|
||||
}
|
||||
|
||||
/*if (hilite[3][i1][j1]>0.01) {
|
||||
red[i][j] = (red[i][j] + hilite[0][i1][j1])/(1+hilite[3][i1][j1]);
|
||||
green[i][j] = (green[i][j]+ hilite[1][i1][j1])/(1+hilite[3][i1][j1]);
|
||||
blue[i][j] = (blue[i][j] + hilite[2][i1][j1])/(1+hilite[3][i1][j1]);
|
||||
}*/
|
||||
|
||||
Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]);
|
||||
|
||||
if (Y>whitept) {
|
||||
factor = whitept/Y;
|
||||
|
||||
/*I = (0.596 * red[i][j] - 0.275 * green[i][j] - 0.321 * blue[i][j]);
|
||||
Q = (0.212 * red[i][j] - 0.523 * green[i][j] + 0.311 * blue[i][j]);
|
||||
|
||||
Y *= factor;
|
||||
I *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt)));
|
||||
Q *= factor;//max(0,min(1,(whitept-Y)/(whitept-clippt)));
|
||||
|
||||
red[i][j] = Y + 0.956*I + 0.621*Q;
|
||||
green[i][j] = Y - 0.272*I - 0.647*Q;
|
||||
blue[i][j] = Y - 1.105*I + 1.702*Q;*/
|
||||
|
||||
red[i][j] *= factor;
|
||||
green[i][j] *= factor;
|
||||
blue[i][j] *= factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(plistener) plistener->setProgress(1.00);
|
||||
//printf("ave wt=%f\n",sumwt/counts);
|
||||
|
||||
|
||||
// diagnostic output
|
||||
/*for (int i=0; i<height; i++) {
|
||||
int i1 = min(hfh-1,(i-(i%pitch))/pitch);
|
||||
for (int j=0; j<width; j++) {
|
||||
int j1 = min(hfw-1,(j-(j%pitch))/pitch);
|
||||
|
||||
//red[i][j] =hfsize[0][i1][j1];
|
||||
//green[i][j]=hfsize[1][i1][j1];
|
||||
//blue[i][j] =hfsize[2][i1][j1];
|
||||
|
||||
//red[i][j] =clippt/2+red[i][j]-channelblur[0][i][j];
|
||||
//green[i][j]=clippt/2+green[i][j]-channelblur[1][i][j];
|
||||
//blue[i][j] =clippt/2+blue[i][j]-channelblur[2][i][j];
|
||||
|
||||
red[i][j]= hilite[0][i1][j1]/(hilite[3][i1][j1]+0.001);
|
||||
green[i][j]=hilite[1][i1][j1]/(hilite[3][i1][j1]+0.001);
|
||||
blue[i][j]= hilite[2][i1][j1]/(hilite[3][i1][j1]+0.001);
|
||||
|
||||
//red[i][j]= hilite_dir[0+0][i1][j1]/hilite_dir[0+3][i1][j1];
|
||||
//green[i][j]=hilite_dir[0+1][i1][j1]/hilite_dir[0+3][i1][j1];
|
||||
//blue[i][j]= hilite_dir[0+2][i1][j1]/hilite_dir[0+3][i1][j1];
|
||||
|
||||
//red[i][j]= clipfix[0][i1][j1];
|
||||
//green[i][j]=clipfix[1][i1][j1];
|
||||
//blue[i][j]= clipfix[2][i1][j1];
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
}// end of HLReconstruction
|
||||
|
||||
/*
|
||||
void RawImageSource::halfsize()
|
||||
{
|
||||
int ex,ey;
|
||||
//determine GRBG coset; (ey,ex) is the offset of the R subarray
|
||||
if (FC(0,0)==1) {//first pixel is G
|
||||
if (FC(0,1)==0) {ey=0; ex=1;} else {ey=1; ex=0;}
|
||||
} else {//first pixel is R or B
|
||||
if (FC(0,0)==0) {ey=0; ex=0;} else {ey=1; ex=1;}
|
||||
}
|
||||
|
||||
for (int i=0; i<(H-(H&1)); i++) {
|
||||
for (int j=0; j<(W-(W&1)); j++){
|
||||
red[i][j] = rawData[i+ey-(i&1)][j+ex-(j&1)];
|
||||
green[i][j] = (rawData[i+(1-ey)-(i&1)][j+ex-(j&1)]+rawData[i+ey-(i&1)][j+(1-ex)-(j&1)])/2;
|
||||
blue[i][j] = rawData[i+(1-ey)-(i&1)][j+(1-ex)-(j&1)];
|
||||
}
|
||||
if (W&1) {
|
||||
red[i][W-1]=red[i][W-2];
|
||||
green[i][W-1]=green[i][W-2];
|
||||
blue[i][W-1]=blue[i][W-2];
|
||||
}
|
||||
}
|
||||
if (H&1) {
|
||||
for (int j=0; j<W; j++){
|
||||
red[H-1][j] = red[H-2][j];
|
||||
green[H-1][j] = green[H-2][j];
|
||||
blue[H-1][j] = blue[H-2][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user