diff --git a/rtengine/rt_algo.cc b/rtengine/rt_algo.cc index 07de2882f..872699120 100644 --- a/rtengine/rt_algo.cc +++ b/rtengine/rt_algo.cc @@ -17,38 +17,41 @@ * along with RawTherapee. If not, see . */ -#include -#include -#include #include -#include +#include +#include #include +#include + #ifdef _OPENMP #include #endif +#include "rt_algo.h" + namespace rtengine { -void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multithread) -{ - // we need to find the (minPrct*size) smallest value and the (maxPrct*size) smallest value in data - // We use a histogram based search for speed and to reduce memory usage - // memory usage of this method is histoSize * sizeof(uint32_t) * (t + 1) byte, - // where t is the number of threads and histoSize is in [1;65536] - // The current implementation is not guaranteed to work correctly if size > 2^32 (4294967296) - assert (minPrct <= maxPrct); - if(size == 0) { +void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multithread) +{ + // We need to find the (minPrct*size) smallest value and the (maxPrct*size) smallest value in data. + // We use a histogram based search for speed and to reduce memory usage. + // Memory usage of this method is histoSize * sizeof(uint32_t) * (t + 1) byte, + // where t is the number of threads and histoSize is in [1;65536]. + // The current implementation is not guaranteed to work correctly if size > 2^32 (4294967296). + assert(minPrct <= maxPrct); + + if (size == 0) { return; } size_t numThreads = 1; #ifdef _OPENMP // Because we have an overhead in the critical region of the main loop for each thread - // we make a rough calculation to reduce the number of threads for small data size - // This also works fine for the minmax loop - if(multithread) { - size_t maxThreads = omp_get_max_threads(); + // we make a rough calculation to reduce the number of threads for small data size. + // This also works fine for the minmax loop. + if (multithread) { + const size_t maxThreads = omp_get_max_threads(); while (size > numThreads * numThreads * 16384 && numThreads < maxThreads) { ++numThreads; } @@ -66,14 +69,14 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& maxVal = std::max(maxVal, data[i]); } - if(std::fabs(maxVal - minVal) == 0.f) { // fast exit, also avoids division by zero in calculation of scale factor + if (std::fabs(maxVal - minVal) == 0.f) { // fast exit, also avoids division by zero in calculation of scale factor minOut = maxOut = minVal; return; } - // caution: currently this works correctly only for histoSize in range[1;65536] - // for small data size (i.e. thumbnails) we reduce the size of the histogram to the size of data - const unsigned int histoSize = std::min(static_cast(65536), size); + // Caution: Currently this works correctly only for histoSize in range[1;65536]. + // For small data size (i.e. thumbnails) we reduce the size of the histogram to the size of data. + const unsigned int histoSize = std::min(65536, size); // calculate scale factor to use full range of histogram const float scale = (histoSize - 1) / (maxVal - minVal); @@ -81,11 +84,11 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& // We need one main histogram std::vector histo(histoSize, 0); - if(numThreads == 1) { + if (numThreads == 1) { // just one thread => use main histogram for (size_t i = 0; i < size; ++i) { // we have to subtract minVal and multiply with scale to get the data in [0;histosize] range - histo[ (uint16_t) (scale * (data[i] - minVal))]++; + histo[static_cast(scale * (data[i] - minVal))]++; } } else { #ifdef _OPENMP @@ -98,10 +101,9 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& #ifdef _OPENMP #pragma omp for nowait #endif - for (size_t i = 0; i < size; ++i) { // we have to subtract minVal and multiply with scale to get the data in [0;histosize] range - histothr[ (uint16_t) (scale * (data[i] - minVal))]++; + histothr[static_cast(scale * (data[i] - minVal))]++; } #ifdef _OPENMP @@ -113,7 +115,7 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& #pragma omp simd #endif - for(size_t i = 0; i < histoSize; ++i) { + for (size_t i = 0; i < histoSize; ++i) { histo[i] += histothr[i]; } } @@ -130,9 +132,9 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& } if (k > 0) { // interpolate - size_t count_ = count - histo[k - 1]; - float c0 = count - threshmin; - float c1 = threshmin - count_; + const size_t count_ = count - histo[k - 1]; + const float c0 = count - threshmin; + const float c1 = threshmin - count_; minOut = (c1 * k + c0 * (k - 1)) / (c0 + c1); } else { minOut = k; @@ -148,9 +150,9 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& } if (k > 0) { // interpolate - size_t count_ = count - histo[k - 1]; - float c0 = count - threshmax; - float c1 = threshmax - count_; + const size_t count_ = count - histo[k - 1]; + const float c0 = count - threshmax; + const float c1 = threshmax - count_; maxOut = (c1 * k + c0 * (k - 1)) / (c0 + c1); } else { maxOut = k; @@ -158,6 +160,6 @@ void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& // go back to original range maxOut /= scale; maxOut += minVal; +} } -} diff --git a/rtengine/rt_algo.h b/rtengine/rt_algo.h index 3bc49d102..2630bbf41 100644 --- a/rtengine/rt_algo.h +++ b/rtengine/rt_algo.h @@ -23,6 +23,7 @@ namespace rtengine { -void findMinMaxPercentile (const float *data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multiThread = true); + +void findMinMaxPercentile(const float* data, size_t size, float minPrct, float& minOut, float maxPrct, float& maxOut, bool multiThread = true); }