diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index 7d5a866b1..9d015dfdb 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -401,6 +401,7 @@ void findMaxMinPercentile(const Array2Df& I, } void solve_pde_fft(Array2Df *F, Array2Df *U, bool multithread); +void rescale_bilinear(const Array2Df &src, Array2Df &dst, bool multithread); // RT void tmo_fattal02(size_t width, size_t height, @@ -426,7 +427,7 @@ void tmo_fattal02(size_t width, // ph.setValue(2); // if (ph.canceled()) return; - /* RT -- we use a hardcoded value of 8 for nlevels, to limit the + /* RT -- we use a hardcoded value 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 @@ -441,6 +442,7 @@ void tmo_fattal02(size_t width, // { // MSIZE = 8; // } + int size = width*height; // unsigned int x,y; @@ -462,6 +464,41 @@ void tmo_fattal02(size_t width, } // ph.setValue(4); + /** RT - this is also here to reduce the dependency of the results on the + * input image size, with the primary aim of having a preview in RT that is + * reasonably close to the actual output image. Intuitively, what we do is + * to put a cap on the dimension of the image processed, so that it is close + * in size to the typical preview that you will see on a normal consumer + * monitor. (That's where the 1920 comes from here.) However, we can't + * simply downscale the input Y array and then upscale it on output, because + * that would cause a big loss of sharpness (confirmed by testing). + * So, we use a different method: we downscale the H array, so that we + * compute a downscaled gaussian pyramid and a downscaled FI matrix. Then, + * we upscale the FI matrix later on, before it gets combined with the + * original input luminance array H. This seems to preserve the input + * sharpness and at the same time significantly reduce the dependency of the + * result on the input size. Clearly this is a hack, and keep in mind that I + * do not really know how Fattal works (it comes from LuminanceHDR almost + * verbatim), so this should probably be revised/reviewed by someone who + * knows better... also, we use a quite naive bilinear interpolation + * algorithm (see rescale_bilinear below), which could definitely be + * improved */ + const int RT_dimension_cap = 1920; + int fullwidth = width; + int fullheight = height; + int dim = std::min(width, height); + Array2Df *fullH = nullptr; + if (dim > RT_dimension_cap) { + float s = float(RT_dimension_cap) / float(dim); + Array2Df *HH = new Array2Df(width * s, height * s); + rescale_bilinear(*H, *HH, multithread); + fullH = H; + H = HH; + width = H->getCols(); + height = H->getRows(); + } + /** RT */ + // create gaussian pyramids // int mins = (widthgetWidth();