////////////////////////////////////////////////////////////////
//
// //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 .
//
////////////////////////////////////////////////////////////////
// Jacques Desmis
// 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
#include "rtengine.h"
#include "rawimagesource.h"
#include "mytime.h"
#include "rt_math.h"
#include "../rtgui/options.h"
namespace rtengine {
extern const Settings* settings;
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
for (int row=0;rowisBayer()) {
rawData[row][col] *= expos;
} else {
rawData[row][col*3] *= expos;
rawData[row][col*3+1] *= expos;
rawData[row][col*3+2] *= expos;
}
}
} else {
// calculate CIE luminosity
float* luminosity = (float *) new float[width*height];
if (ri->isBayer()) {
// 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(imgd, H);
} else {
// Non-Bayers are already RGB
// CIE luminosity
#pragma omp parallel for
for(int row=0;rowisBayer()) {
if (rawData[row][col]>maxVal) maxVal = rawData[row][col];
} else {
for (int c=0;c<3;c++) if (rawData[row][col*3+c]>maxVal) maxVal = rawData[row][col*3+c];
}
}
// Exposure correction with highlight preservation
LUTf lut(maxVal+1);
if(expos>1){
// Positive exposure
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
for(int row=0;rowisBayer()) {
rawData[row][col] *= fac;
} else {
for (int c=0;c<3;c++) rawData[row][col*3+c] *= fac;
}
}
} 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
for(int row=0;rowisBayer()) {
rawData[row][col] *= fac;
} else {
for (int c=0;c<3;c++) rawData[row][col*3+c] *= fac;
}
}
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));
}
} //namespace