-
Notifications
You must be signed in to change notification settings - Fork 0
/
generatebn_hpf.cpp
80 lines (69 loc) · 2.5 KB
/
generatebn_hpf.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "blur.h"
#include "convert.h"
#include "generatebn_hpf.h"
#include "whitenoise.h"
static void NormalizeHistogram(std::mt19937& rng, std::vector<float>& image, size_t width)
{
struct SHistogramHelper
{
float value;
size_t pixelIndex;
};
static std::vector<SHistogramHelper> pixels;
pixels.resize(width*width);
// put all the pixels into the array
for (size_t i = 0, c = pixels.size(); i < c; ++i)
{
pixels[i].value = image[i];
pixels[i].pixelIndex = i;
}
// shuffle the pixels to randomly order ties. not as big a deal with floating point pixel values though
std::shuffle(pixels.begin(), pixels.end(), rng);
// sort the pixels by value
std::sort(
pixels.begin(),
pixels.end(),
[](const SHistogramHelper& a, const SHistogramHelper& b)
{
return a.value < b.value;
}
);
// use the pixel's place in the array as the new value, and write it back to the image
for (size_t i = 0, c = width * width; i < c; ++i)
{
float value = float(i) / float(c - 1);
image[pixels[i].pixelIndex] = value;
}
}
void GenerateBN_HPF(std::vector<uint8_t>& blueNoise, size_t width, size_t numPasses, float sigma, bool makeRed)
{
// first make white noise
std::mt19937 rng(GetRNGSeed());
std::vector<uint8_t> pixels;
MakeWhiteNoise(rng, pixels, width);
// convert from uint8 to float
std::vector<float> pixelsFloat;
ToFloat(pixels, pixelsFloat);
// repeatedly high pass filter and histogram fixup
std::vector<float> pixelsFloatLowPassed;
for (size_t index = 0; index < numPasses; ++index)
{
GaussianBlur(pixelsFloat, pixelsFloatLowPassed, width, sigma);
if (!makeRed)
{
// a blur is a low pass filter, and a high pass filter is the signal minus the low pass filtered signa.
for (size_t pixelIndex = 0, pixelCount = pixelsFloat.size(); pixelIndex < pixelCount; ++pixelIndex)
pixelsFloat[pixelIndex] -= pixelsFloatLowPassed[pixelIndex];
}
else
{
// to make red noise, just use the low pass filter data
for (size_t pixelIndex = 0, pixelCount = pixelsFloat.size(); pixelIndex < pixelCount; ++pixelIndex)
pixelsFloat[pixelIndex] = pixelsFloatLowPassed[pixelIndex];
}
// Do a histogram fixup
NormalizeHistogram(rng, pixelsFloat, width);
}
// convert back to uint8
FromFloat(pixelsFloat, blueNoise);
}