132 lines
4.5 KiB
C++
132 lines
4.5 KiB
C++
|
|
////////////////////////////////////////////////////////////////
|
|
//
|
|
// //exposure correction before interpolation
|
|
//
|
|
// code dated: December 27, 2010
|
|
//
|
|
// Expo_before.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/>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Jacques Desmis <jdesmis@gmail.com>
|
|
// use fast-demo(provisional) from Emil Martinec
|
|
// inspired from work Guillermo Luijk and Manuel LLorens(Perfectraw)
|
|
//
|
|
// This function uses parameters:
|
|
// exposure (linear): 2^(-8..0..8): currently 0.5 +3
|
|
// preserve (log) : 0..8 : currently 0.1 1
|
|
|
|
void RawImageSource::processRawWhitepoint(float expos, float preser) {
|
|
MyTime t1e,t2e;
|
|
t1e.set();
|
|
|
|
int width=W, height=H;
|
|
|
|
// exposure correction inspired from G.Luijk
|
|
if (fabs(preser)<0.001) {
|
|
// No highlight protection - simple mutiplication
|
|
for (int c=0; c<4; c++) {
|
|
chmax[c] *= expos;
|
|
}
|
|
#pragma omp parallel for shared(expos)
|
|
for (int row=0;row<height;row++)
|
|
for (int col=0;col<width;col++) {
|
|
rawData[row][col] *= expos;
|
|
}
|
|
} else {
|
|
// save old image as it's overwritten by demosaic
|
|
float** imgd = allocArray< float >(W,H);
|
|
|
|
// with memcpy it's faster than for (...)
|
|
for (int i=0; i<H; i++) memcpy (imgd[i], rawData[i], W*sizeof(**imgd));
|
|
|
|
// Demosaic to calc luminosity
|
|
fast_demosaic (0,0,W,H);
|
|
|
|
// calculate CIE luminosity
|
|
float* luminosity = (float *) new float[width*height];
|
|
|
|
#pragma omp parallel default(shared)
|
|
{
|
|
// CIE luminosity
|
|
#pragma omp for
|
|
for(int row=0;row<height;row++)
|
|
for(int col=0;col<width;col++)
|
|
luminosity[row*width+col] =
|
|
0.299f * (float)red[row][col] + 0.587f * (float)green[row][col] + 0.114f * (float)blue[row][col];
|
|
}
|
|
|
|
// restore image destroyed by demosaic
|
|
for (int i=0; i<H; i++) memcpy (rawData[i], imgd[i], W*sizeof(**imgd));
|
|
freeArray<float>(imgd, H);
|
|
|
|
// Find maximum to adjust LUTs. New float engines clips only at the very end
|
|
int maxVal=0;
|
|
for(int row=0;row<height;row++)
|
|
for(int col=0;col<width;col++)
|
|
if (rawData[row][col]>maxVal) maxVal = rawData[row][col];
|
|
|
|
// Exposure correction with highlight preservation
|
|
LUTf lut(maxVal+1);
|
|
if(expos>1){
|
|
float K = (float) maxVal / expos*exp(-preser*log(2.0));
|
|
for (int j=0;j<=maxVal;j++)
|
|
lut[(int)j]=(((float)maxVal-K*expos)/((float)maxVal-K)*(j-maxVal)+(float) maxVal) / j;
|
|
|
|
for (int c=0; c<4; c++) {
|
|
chmax[c] *= expos;
|
|
}
|
|
|
|
#pragma omp parallel for shared(expos)
|
|
for(int row=0;row<height;row++)
|
|
for(int col=0;col<width;col++){
|
|
if (luminosity[row*width + col] < K) {
|
|
rawData[row][col] *= expos;
|
|
} else {
|
|
rawData[row][col] *= lut[luminosity[row*width+col]];
|
|
}
|
|
}
|
|
} else {
|
|
// Negative exposure
|
|
float EV=log(expos)/log(2.0); // Convert exp. linear to EV
|
|
float K = (float)maxVal * exp(-preser * log(2.0));
|
|
|
|
for (int j=0;j<=maxVal;j++)
|
|
lut[(int)j] = exp(EV*((float)maxVal-j) / ((float)maxVal-K) * log(2.0));
|
|
|
|
#pragma omp parallel for shared(expos)
|
|
for(int row=0;row<height;row++)
|
|
for(int col=0;col<width;col++){
|
|
if (luminosity[row*width+col]<K) {
|
|
rawData[row][col] *= expos;
|
|
} else {
|
|
rawData[row][col] *= lut[luminosity[row*width+col]];
|
|
}
|
|
}
|
|
for (int c=0; c<4; c++) {
|
|
chmax[c] *= expos;
|
|
}
|
|
}
|
|
|
|
|
|
delete[] luminosity;
|
|
}
|
|
t2e.set();
|
|
if( settings->verbose )
|
|
printf("Exposure before %d usec\n", t2e.etime(t1e));
|
|
|
|
} |