Now actually fix the scaling function.

This commit is contained in:
2017-10-13 15:14:15 +02:00
parent 5df5c1c13c
commit f413c30279
2 changed files with 30 additions and 9 deletions

View File

@@ -64,7 +64,7 @@ void PNGDumper::dumpImageSeries(const LayerData &layer)
// advance the buffer; // advance the buffer;
data += imagePixels; data += imagePixels;
clamp(buffer.begin(), buffer.end(), 0.0, 255.0); rescale(buffer.begin(), buffer.end(), 0.0, 255.0);
for (int y = 0; y < height; ++y) { for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width; ++x) {

View File

@@ -86,18 +86,39 @@ namespace fmri
return res; return res;
} }
/**
* @brief Scales a range of values into a fixed range of values.
*
* This method traverses the range twice, once to determine maximum
* and minimum, and once again to modify all the values.
*
* @tparam It Iterator type. Will be used to determine value type.
* @param first The start of the range to scale
* @param last The end of the range to scale
* @param minimum The desired minimum of the range.
* @param maximum The desired maximum of the range.
*/
template<class It> template<class It>
void clamp(It begin, It end, void rescale(const It first, const It last,
typename std::iterator_traits<It>::value_type minimum, typename std::iterator_traits<It>::value_type minimum,
typename std::iterator_traits<It>::value_type maximum) typename std::iterator_traits<It>::value_type maximum)
{ {
const auto[minElem, maxElem] = std::minmax(begin, end); const auto[minElem, maxElem] = std::minmax_element(first, last);
const auto diff = *maxElem - *minElem; const auto rangeWidth = maximum - minimum;
const auto valWidth = *maxElem - *minElem;
const auto offset = minimum - *minElem; if (valWidth == 0) {
const auto scaling = (maximum - minimum) / diff; // Just fill the range with the minimum value, since
std::fill(first, last, minimum);
} else {
const auto scaling = rangeWidth / valWidth;
std::for_each(begin, end, [offset, scaling] (typename std::iterator_traits<It>::reference v) { v = (v + offset) * scaling;}); const auto minVal = *minElem;
std::for_each(first, last, [=](typename std::iterator_traits<It>::reference v) {
v = std::clamp((v - minVal) * scaling + minimum, minimum, maximum);
});
}
} }
} }