cloudy-raytracer/post_processing/bloom.cpp

75 lines
2.2 KiB
C++

#include <iostream>
#include "bloom.h"
Bloom::Bloom(CImg<float> &image, float threshold, Texture& thresholdImg) : image(image), threshold(threshold) {}
CImg<float> Bloom::bloom(int kernelSize, float sigma, float intensity) {
CImg<float> brightPixels = image.get_threshold(threshold);
// Apply gaussian blur to bright pixels
CImg<float> kernel = computeGaussianKernel(kernelSize, sigma);
CImg<float> blurred = convolution(image, kernel);
blurred *= intensity;
// Add blurred image back to original image
cimg_forXYC(image, x, y, c) {
float value = image(x, y, 0, c) + blurred(x, y, 0, c);
image(x, y, 0, c) = (value > 1.0f) ? 1.0f : value;
}
return image;
}
// Function to compute Gaussian kernel
CImg<float> Bloom::computeGaussianKernel(int kernelSize, float sigma) {
// Create kernel
CImg<float> kernel(kernelSize, kernelSize, 1, 1);
// Compute Gaussian kernel
float sum = 0.0f;
int i, j;
for (i = 0; i < kernelSize; i++) {
for (j = 0; j < kernelSize; j++) {
kernel(i, j) = exp(-0.5f * (pow((i - kernelSize / 2.f) / sigma, 2.f) +
pow((j - kernelSize / 2.f) / sigma, 2.f))) / (2 * M_PI * sigma * sigma);
sum += kernel(i, j);
}
}
// Normalize kernel
kernel /= sum;
return kernel;
}
// Function to perform convolution
CImg<float> Bloom::convolution(CImg<float> &img, CImg<float> &kernel) {
int kernelSize = kernel.width();
int imgRows = img.height();
int imgCols = img.width();
CImg<float> result(imgCols, imgRows, 1, 3);
float sum;
int i, j, m, n;
int kernelRadius = kernelSize / 2;
// Perform convolution
cimg_forXYC(img, i, j, c) {
sum = 0;
cimg_forY(kernel, m) {
cimg_forX(kernel, n) {
int x = i + n - kernelRadius;
int y = j + m - kernelRadius;
if (x >= 0 && x < imgCols && y >= 0 && y < imgRows) {
sum += img(x, y, 0, c) * kernel(n, m);
}
}
}
result(i, j, 0, c) = sum;
}
return result;
}