various fixes to Fattal, and moved it later in the pipeline
This commit is contained in:
@@ -808,6 +808,10 @@ void Crop::update (int todo)
|
||||
parent->ipf.chromiLuminanceCurve (this, 1, labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
|
||||
parent->ipf.vibrance (labnCrop);
|
||||
|
||||
if (params.fattal.enabled) {
|
||||
parent->ipf.ToneMapFattal02(labnCrop, 3);
|
||||
}
|
||||
|
||||
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
|
||||
parent->ipf.EPDToneMap (labnCrop, 5, skip);
|
||||
}
|
||||
@@ -1077,6 +1081,11 @@ void Crop::freeAll ()
|
||||
namespace
|
||||
{
|
||||
|
||||
bool check_need_full_image(const ProcParams ¶ms)
|
||||
{
|
||||
return params.fattal.enabled; // agriggio - maybe we can do this for wavelets too?
|
||||
}
|
||||
|
||||
bool check_need_larger_crop_for_lcp_distortion (int fw, int fh, int x, int y, int w, int h, const ProcParams ¶ms)
|
||||
{
|
||||
if (x == 0 && y == 0 && w == fw && h == fh) {
|
||||
@@ -1139,6 +1148,14 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
|
||||
ory = by1;
|
||||
orw = bw;
|
||||
orh = bh;
|
||||
|
||||
if (check_need_full_image(parent->params)) {
|
||||
orx = bx1 = 0;
|
||||
ory = by1 = 0;
|
||||
orw = bw = parent->fullw;
|
||||
orh = bh = parent->fullh;
|
||||
}
|
||||
|
||||
ProcParams& params = parent->params;
|
||||
|
||||
parent->ipf.transCoord (parent->fw, parent->fh, bx1, by1, bw, bh, orx, ory, orw, orh);
|
||||
@@ -1178,7 +1195,6 @@ bool Crop::setCropSizes (int rcx, int rcy, int rcw, int rch, int skip, bool inte
|
||||
orh = min (y2 - y1, parent->fh - ory);
|
||||
}
|
||||
|
||||
|
||||
PreviewProps cp (orx, ory, orw, orh, skip);
|
||||
int orW, orH;
|
||||
parent->imgsrc->getSize (cp, orW, orH);
|
||||
|
@@ -636,6 +636,10 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
|
||||
ipf.chromiLuminanceCurve (nullptr, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histLCurve);
|
||||
ipf.vibrance (nprevl);
|
||||
|
||||
if (params.fattal.enabled) {
|
||||
ipf.ToneMapFattal02(nprevl, 3);
|
||||
}
|
||||
|
||||
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
|
||||
ipf.EPDToneMap (nprevl, 5, scale);
|
||||
}
|
||||
|
@@ -3119,19 +3119,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Imagefloat> fattal;
|
||||
if (params->fattal.enabled) {
|
||||
fattal.reset(working->copy());
|
||||
int detail_level = 3;
|
||||
if (scale < 8) {
|
||||
detail_level = 3;
|
||||
} else {
|
||||
detail_level = 0;
|
||||
}
|
||||
ToneMapFattal02(fattal.get(), detail_level);
|
||||
working = fattal.get();
|
||||
}
|
||||
|
||||
int h_th = 0, s_th = 0;
|
||||
|
||||
if (shmap) {
|
||||
|
@@ -347,7 +347,7 @@ public:
|
||||
void Badpixelscam (CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad);
|
||||
void BadpixelsLab (LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom);
|
||||
|
||||
void ToneMapFattal02(Imagefloat *rgb, int detail_level);
|
||||
void ToneMapFattal02(LabImage *lab, int detail_level);
|
||||
|
||||
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
|
||||
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga = nullptr);
|
||||
|
@@ -1275,6 +1275,10 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
||||
|
||||
ipf.vibrance (labView);
|
||||
|
||||
if (params.fattal.enabled) {
|
||||
ipf.ToneMapFattal02(labView, 0);
|
||||
}
|
||||
|
||||
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) {
|
||||
ipf.EPDToneMap (labView, 5, 6);
|
||||
}
|
||||
|
@@ -1013,6 +1013,10 @@ private:
|
||||
|
||||
ipf.chromiLuminanceCurve (nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
|
||||
|
||||
if (params.fattal.enabled) {
|
||||
ipf.ToneMapFattal02(labView, 3);
|
||||
}
|
||||
|
||||
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
|
||||
ipf.EPDToneMap (labView, 5, 1);
|
||||
}
|
||||
|
@@ -68,6 +68,8 @@
|
||||
#include "array2D.h"
|
||||
#include "improcfun.h"
|
||||
#include "settings.h"
|
||||
#include "iccstore.h"
|
||||
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
@@ -155,6 +157,15 @@ void gaussianBlur(const Array2Df& I, Array2Df& L)
|
||||
|
||||
Array2Df T(width,height);
|
||||
|
||||
if (width < 3 || height < 3) {
|
||||
if (&I != &L) {
|
||||
for (int i = 0, n = width*height; i < n; ++i) {
|
||||
L(i) = I(i);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//--- X blur
|
||||
//#pragma omp parallel for shared(I, T)
|
||||
for ( int y=0 ; y<height ; y++ )
|
||||
@@ -202,10 +213,20 @@ void createGaussianPyramids( Array2Df* H, Array2Df** pyramids, int nlevels)
|
||||
|
||||
for ( int k=1 ; k<nlevels ; k++ )
|
||||
{
|
||||
if (width > 2 && height > 2) {
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
pyramids[k] = new Array2Df(width,height);
|
||||
downSample(*L, *pyramids[k]);
|
||||
} else {
|
||||
// RT - now nlevels is fixed in tmo_fattal02 (see the comment in
|
||||
// there), so it might happen that we have to add some padding to
|
||||
// the gaussian pyramids
|
||||
pyramids[k] = new Array2Df(width,height);
|
||||
for (int j = 0, n = width*height; j < n; ++j) {
|
||||
(*pyramids[k])(j) = (*L)(j);
|
||||
}
|
||||
}
|
||||
|
||||
delete L;
|
||||
L = new Array2Df(width,height);
|
||||
@@ -379,7 +400,7 @@ void findMaxMinPercentile(const Array2Df& I,
|
||||
maxLum = vI.at( int(maxPrct*vI.size()) );
|
||||
}
|
||||
|
||||
void solve_pde_fft(Array2Df *F, Array2Df *U);
|
||||
void solve_pde_fft(Array2Df *F, Array2Df *U, bool multithread);
|
||||
|
||||
void tmo_fattal02(size_t width,
|
||||
size_t height,
|
||||
@@ -388,7 +409,8 @@ void tmo_fattal02(size_t width,
|
||||
float alfa,
|
||||
float beta,
|
||||
float noise,
|
||||
int detail_level)
|
||||
int detail_level,
|
||||
bool multithread)
|
||||
{
|
||||
// #ifdef TIMER_PROFILING
|
||||
// msec_timer stop_watch;
|
||||
@@ -404,15 +426,21 @@ void tmo_fattal02(size_t width,
|
||||
// ph.setValue(2);
|
||||
// if (ph.canceled()) return;
|
||||
|
||||
int MSIZE = 32; // minimum size of gaussian pyramid
|
||||
// I believe a smaller value than 32 results in slightly better overall
|
||||
// quality but I'm only applying this if the newly implemented fft solver
|
||||
// is used in order not to change behaviour of the old version
|
||||
// TODO: best let the user decide this value
|
||||
// if (fftsolver)
|
||||
{
|
||||
MSIZE = 8;
|
||||
}
|
||||
/* RT -- we use a hardcoded value of 8 for nlevels, to limit the
|
||||
* dependency of the result on the image size. When using an auto computed
|
||||
* nlevels value, you would get vastly different results with different
|
||||
* image sizes, making it essentially impossible to preview the tool
|
||||
* inside RT. With a hardcoded value, the results for the preview are much
|
||||
* closer to those for the final image */
|
||||
// int MSIZE = 32; // minimum size of gaussian pyramid
|
||||
// // I believe a smaller value than 32 results in slightly better overall
|
||||
// // quality but I'm only applying this if the newly implemented fft solver
|
||||
// // is used in order not to change behaviour of the old version
|
||||
// // TODO: best let the user decide this value
|
||||
// // if (fftsolver)
|
||||
// {
|
||||
// MSIZE = 8;
|
||||
// }
|
||||
|
||||
int size = width*height;
|
||||
// unsigned int x,y;
|
||||
@@ -435,16 +463,17 @@ void tmo_fattal02(size_t width,
|
||||
// ph.setValue(4);
|
||||
|
||||
// create gaussian pyramids
|
||||
int mins = (width<height) ? width : height; // smaller dimension
|
||||
int nlevels = 0;
|
||||
while ( mins >= MSIZE )
|
||||
{
|
||||
nlevels++;
|
||||
mins /= 2;
|
||||
}
|
||||
// std::cout << "DEBUG: nlevels = " << nlevels << ", mins = " << mins << std::endl;
|
||||
// The following lines solves a bug with images particularly small
|
||||
if (nlevels == 0) nlevels = 1;
|
||||
// int mins = (width<height) ? width : height; // smaller dimension
|
||||
// int nlevels = 0;
|
||||
// while ( mins >= MSIZE )
|
||||
// {
|
||||
// nlevels++;
|
||||
// mins /= 2;
|
||||
// }
|
||||
// // std::cout << "DEBUG: nlevels = " << nlevels << ", mins = " << mins << std::endl;
|
||||
// // The following lines solves a bug with images particularly small
|
||||
// if (nlevels == 0) nlevels = 1;
|
||||
const int nlevels = 7; // RT -- see above
|
||||
|
||||
Array2Df** pyramids = new Array2Df*[nlevels];
|
||||
createGaussianPyramids(H, pyramids, nlevels);
|
||||
@@ -551,7 +580,7 @@ void tmo_fattal02(size_t width,
|
||||
Array2Df U(width, height);
|
||||
// if (fftsolver)
|
||||
{
|
||||
solve_pde_fft(&DivG, &U);//, ph);
|
||||
solve_pde_fft(&DivG, &U, multithread);//, ph);
|
||||
}
|
||||
// else
|
||||
// {
|
||||
@@ -798,7 +827,7 @@ std::vector<double> get_lambda(int n)
|
||||
// not modified and the equation might not have a solution but an
|
||||
// approximate solution with a minimum error is then calculated
|
||||
// double precision version
|
||||
void solve_pde_fft(Array2Df *F, Array2Df *U)/*, pfs::Progress &ph,
|
||||
void solve_pde_fft(Array2Df *F, Array2Df *U, bool multithread)/*, pfs::Progress &ph,
|
||||
bool adjust_bound)*/
|
||||
{
|
||||
// ph.setValue(20);
|
||||
@@ -809,8 +838,10 @@ void solve_pde_fft(Array2Df *F, Array2Df *U)/*, pfs::Progress &ph,
|
||||
|
||||
// activate parallel execution of fft routines
|
||||
#ifdef RT_FFTW3F_OMP
|
||||
if (multithread) {
|
||||
fftwf_init_threads();
|
||||
fftwf_plan_with_nthreads( omp_get_max_threads() );
|
||||
}
|
||||
// #else
|
||||
// fftwf_plan_with_nthreads( 2 );
|
||||
#endif
|
||||
@@ -883,7 +914,9 @@ void solve_pde_fft(Array2Df *F, Array2Df *U)/*, pfs::Progress &ph,
|
||||
|
||||
// fft parallel threads cleanup, better handled outside this function?
|
||||
#ifdef RT_FFTW3F_OMP
|
||||
if (multithread) {
|
||||
fftwf_cleanup_threads();
|
||||
}
|
||||
#endif
|
||||
|
||||
// ph.setValue(90);
|
||||
@@ -916,10 +949,7 @@ void solve_pde_fft(Array2Df *F, Array2Df *U)/*, pfs::Progress &ph,
|
||||
// }
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, int detail_level)
|
||||
void tmo_fattal02_RT(Imagefloat *rgb, float alpha, float beta, int detail_level, bool multiThread)
|
||||
{
|
||||
int w = rgb->getWidth();
|
||||
int h = rgb->getHeight();
|
||||
@@ -936,8 +966,8 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, int detail_level)
|
||||
}
|
||||
}
|
||||
|
||||
float alpha = params->fattal.alpha;
|
||||
float beta = params->fattal.beta;
|
||||
// float alpha = params->fattal.alpha;
|
||||
// float beta = params->fattal.beta;
|
||||
float noise = alpha * 0.01f;
|
||||
|
||||
if (settings->verbose) {
|
||||
@@ -945,7 +975,7 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, int detail_level)
|
||||
<< ", detail_level = " << detail_level << std::endl;
|
||||
}
|
||||
|
||||
tmo_fattal02(w, h, Yr, L, alpha, beta, noise, detail_level);
|
||||
tmo_fattal02(w, h, Yr, L, alpha, beta, noise, detail_level, multiThread);
|
||||
|
||||
const float epsilon = 1e-4f;
|
||||
for (int y = 0; y < h; y++) {
|
||||
@@ -961,4 +991,15 @@ void ImProcFunctions::ToneMapFattal02(Imagefloat *rgb, int detail_level)
|
||||
rgb->normalizeFloatTo65535();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void ImProcFunctions::ToneMapFattal02(LabImage *lab, int detail_level)
|
||||
{
|
||||
Imagefloat tmp(lab->W, lab->H);
|
||||
lab2rgb(*lab, tmp, params->icm.working);
|
||||
tmo_fattal02_RT(&tmp, params->fattal.alpha, params->fattal.beta, detail_level, multiThread);
|
||||
rgb2lab(tmp, *lab, params->icm.working);
|
||||
}
|
||||
|
||||
} // namespace rtengine
|
||||
|
Reference in New Issue
Block a user