49 if (!image || width == 0 || height == 0 || sigma_pixels <= 0)
52 const size_t Npix = width * height;
55 const size_t W = fft::next_power_of_two(width);
56 const size_t H = fft::next_power_of_two(height);
57 const size_t Npix_padded = W * H;
60 auto freq_coord = [](
int k,
int dim) ->
double {
61 return (k <= dim / 2) ? double(k) / dim : double(k - dim) / dim;
65 const double two_pi2_sigma2 = 2.0 * M_PI * M_PI * sigma_pixels * sigma_pixels;
67 for (
int channel = 0; channel < 3; channel++) {
69 std::vector<fft::cd> data(Npix_padded, {0.0, 0.0});
72 for (
size_t y = 0; y < height; y++)
73 for (
size_t x = 0; x < width; x++)
74 data[y * W + x] = fft::cd(image[(y * width + x) * 4 + channel], 0.0);
77 fft::iterative_fft_2d(data, W, H,
false);
80 for (
size_t y = 0; y < H; y++) {
81 double fy2 = freq_coord(y, H) * freq_coord(y, H);
82 for (
size_t x = 0; x < W; x++) {
83 double fx2 = freq_coord(x, W) * freq_coord(x, W);
84 double gain = std::exp(-two_pi2_sigma2 * (fx2 + fy2));
85 data[y * W + x] *= gain;
90 fft::iterative_fft_2d(data, W, H,
true);
93 for (
size_t y = 0; y < height; y++)
94 for (
size_t x = 0; x < width; x++) {
95 double v = data[y * W + x].real();
96 v = std::clamp(v, 0.0, 255.0);
97 image[(y * width + x) * 4 + channel] =
static_cast<uint8_t
>(std::lrint(v));
119void threshold_image(uint8_t* ptr,
const int width,
const int height,
const int num_thresholds) {
120 if (num_thresholds <= 0) {
123 const uint8_t REGION_SIZE(255 / num_thresholds);
126 img.loadFromBuffer(ptr, width, height, ImageLib::RGBA_CONVERTER<uint8_t>);
128 const auto imgWidth {img.getWidth()}, imgHeight {img.getHeight()};
130 p.red = quantize(p.red, REGION_SIZE);
131 p.green = quantize(p.green, REGION_SIZE);
132 p.blue = quantize(p.blue, REGION_SIZE);
135 const auto& modified = img.getData();
140 uint8_t* ptr,
const int width,
const int height,
const int num_thresholds
142 if (num_thresholds <= 0) {
146 img.loadFromBuffer(ptr, width, height, ImageLib::RGBA_CONVERTER<uint8_t>);
148 const auto imgWidth {img.getWidth()}, imgHeight {img.getHeight()};
150 const bool R {p.red < num_thresholds};
151 const bool G {p.green < num_thresholds};
152 const bool B {p.blue < num_thresholds};
158 const auto& modified = img.getData();
void black_threshold_image(uint8_t *ptr, const int width, const int height, const int num_thresholds)
Apply black-thresholding to an image.
void gaussian_blur_fft(uint8_t *image, size_t width, size_t height, double sigma)
Apply a Gaussian blur to an image using FFT.
void threshold_image(uint8_t *ptr, const int width, const int height, const int num_thresholds)
Apply a thresholding operation to an image.