10#include <QtConcurrent>
18T median(std::vector<T> &values)
20 const int middle = values.size() / 2;
21 std::nth_element(values.begin(), values.begin() +
middle, values.end());
30 for (
int i = 0; i < size; i +=
sampleBy)
39T median(T
const *values,
int size,
int sampleBy)
44 samples[i] = values[index];
45 return median(samples);
58 int input_range,
int image_height,
int image_width,
int sampling)
66 const float maxInput = input_range > 1 ? input_range - 1 : input_range;
74 const float hsRangeFactor = highlights == shadows ? 1.0f : 1.0f / (highlights - shadows);
83 for (
int j = 0,
jout = 0;
j < image_height;
j += sampling,
jout++)
90 for (
int i = 0,
iout = 0; i < image_width; i += sampling,
iout++)
104 future.waitForFinished();
116 const StretchParams &stretchParams,
117 int inputRange,
int imageHeight,
int imageWidth,
int sampling)
127 const float midtonesR = stretchParams.grey_red.midtones;
128 const float highlightsR = stretchParams.grey_red.highlights;
129 const float shadowsR = stretchParams.grey_red.shadows;
130 const float midtonesG = stretchParams.green.midtones;
131 const float highlightsG = stretchParams.green.highlights;
132 const float shadowsG = stretchParams.green.shadows;
133 const float midtonesB = stretchParams.blue.midtones;
134 const float highlightsB = stretchParams.blue.highlights;
135 const float shadowsB = stretchParams.blue.shadows;
157 const int size = imageWidth * imageHeight;
159 for (
int j = 0,
jout = 0;
j < imageHeight;
j += sampling,
jout++)
168 auto * scanLine =
reinterpret_cast<QRgb*
>(
outputImage->scanLine(
jout));
170 for (
int i = 0,
iout = 0; i < imageWidth; i += sampling,
iout++)
201 scanLine[
iout] = qRgb(red, green, blue);
206 future.waitForFinished();
212 int input_range,
int image_height,
int image_width,
int num_channels,
int sampling)
216 image_height, image_width, sampling);
219 image_height, image_width, sampling);
228 constexpr int maxSamples = 500000;
229 const int sampleBy = width * height < maxSamples ? 1 : width * height / maxSamples;
233 const int numSamples = width * height /
sampleBy;
235 for (
int index = 0, i = 0; i < numSamples; ++i, index +=
sampleBy)
257 constexpr float B = 0.25;
269 if (X == 0) midtones = 0.0f;
270 else if (X == M) midtones = 0.5f;
271 else if (X == 1) midtones = 1.0f;
272 else midtones = ((M - 1) * X) / ((2 * M - 1) * X - M);
275 params->shadows = shadows;
276 params->highlights = highlights;
277 params->midtones = midtones;
278 params->shadows_expansion = 0.0;
279 params->highlights_expansion = 1.0;
311Stretch::Stretch(
int width,
int height,
int channels,
int data_type)
314 image_height = height;
315 image_channels = channels;
317 input_range = getRange(dataType);
324 recalculateInputRange(input);
330 input_range, image_height, image_width, image_channels, sampling);
334 input_range, image_height, image_width, image_channels, sampling);
338 input_range, image_height, image_width, image_channels, sampling);
342 input_range, image_height, image_width, image_channels, sampling);
346 input_range, image_height, image_width, image_channels, sampling);
350 input_range, image_height, image_width, image_channels, sampling);
354 input_range, image_height, image_width, image_channels, sampling);
363void Stretch::recalculateInputRange(uint8_t
const *input)
365 if (input_range <= 1)
return;
370 mx =
sampledMax(
reinterpret_cast<float const*
>(input), image_height * image_width, 1000);
372 mx =
sampledMax(
reinterpret_cast<double const*
>(input), image_height * image_width, 1000);
373 if (mx <= 1.01f) input_range = 1;
376StretchParams Stretch::computeParams(uint8_t
const *input)
378 recalculateInputRange(input);
379 StretchParams result;
380 for (
int channel = 0; channel < image_channels; ++channel)
382 int offset = channel * image_width * image_height;
383 StretchParams1Channel *params = channel == 0 ? &result.grey_red :
384 (channel == 1 ? &result.green : &result.blue);
389 auto buffer =
reinterpret_cast<uint8_t
const*
>(input);
391 image_height, image_width);
396 auto buffer =
reinterpret_cast<short const*
>(input);
398 image_height, image_width);
403 auto buffer =
reinterpret_cast<unsigned short const*
>(input);
405 image_height, image_width);
410 auto buffer =
reinterpret_cast<long const*
>(input);
412 image_height, image_width);
417 auto buffer =
reinterpret_cast<float const*
>(input);
419 image_height, image_width);
424 auto buffer =
reinterpret_cast<long long const*
>(input);
426 image_height, image_width);
431 auto buffer =
reinterpret_cast<double const*
>(input);
433 image_height, image_width);
QFuture< T > run(Function function,...)