#include "kernels/gauss.h"
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <iostream>
#define NUM_THREADS 16
#define NUM_BLOCKS 32
void writePPM(Pixel *pixels, const char *filename, int width, int height) {
std::ofstream outputFile(filename, std::ios::binary);
outputFile << "P6\n" << width << " " << height << "\n255\n";
outputFile.write(reinterpret_cast<const char *>(pixels),
sizeof(Pixel) * width * height);
}
Pixel *readPPM(const char *filename, int *width, int *height) {
std::ifstream inputFile(filename, std::ios::binary);
inputFile.ignore(2, '\n');
while (inputFile.peek() == '#') {
inputFile.ignore(1024, '\n');
}
inputFile >> (*width);
inputFile.ignore(1, ' ');
inputFile >> (*height);
inputFile.ignore(1, '\n');
while (inputFile.peek() == '#') {
inputFile.ignore(1024, '\n');
}
inputFile.ignore(3, '\n');
Pixel *data = new Pixel[(*width) * (*height)];
inputFile.read(reinterpret_cast<char *>(data),
sizeof(Pixel) * (*width) * (*height));
return data;
}
void calculateWeights(float weights[5][5]) {
float sigma = 1.0;
float r, s = 2.0 * sigma * sigma;
float sum = 0.0;
for (int x = -2; x <= 2; x++) {
for (int y = -2; y <= 2; y++) {
r = x * x + y * y;
weights[x + 2][y + 2] = exp(-(r / s)) / (M_PI * s);
sum += weights[x + 2][y + 2];
}
}
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
weights[i][j] /= sum;
}
}
}
int main(int argc, char **argv) {
const char *inFilename = (argc > 1) ? argv[1] : "examples/kernels/lena.ppm";
const char *outFilename = (argc > 2) ? argv[2] : "examples/kernels/output.ppm";
float weights[5][5];
calculateWeights(weights);
int width;
int height;
Pixel *image = readPPM(inFilename, &width, &height);
try {
Headers headers;
headers.insert(Header{"examples/kernels/gauss.h"});
Source source{load("examples/kernels/gauss.cu"), headers};
size_t size_pixel = height * width * sizeof(Pixel);
size_t size_weights = 5 * 5 * sizeof(float);
std::vector<KernelArg> args;
args.emplace_back(KernelArg{image, size_pixel, true});
args.emplace_back(KernelArg{weights, size_weights});
args.emplace_back(KernelArg{&width});
args.emplace_back(KernelArg{&height});
dim3 block;
dim3 grid(width, height);
source.program("gaussFilterKernel")
.compile()
.configure(grid, block)
.launch(args);
} catch (const std::exception &e) {
std::cerr << "Error:\n" << e.what() << std::endl;
}
writePPM(image, outFilename, width, height);
free(image);
return 0;
}