blob: 028e007d788a8b17ab79029abd5134dd5fb02d08 [file] [log] [blame]
/**
Pankaj Kukreja
github.com/proton0001
Indian Institute of Technology Hyderabad
*/
#include "ImageHelper.h"
#include "blur.h"
#include <cstdlib>
#include <iostream>
#define BENCHMARK_LIB
#ifdef BENCHMARK_LIB
#include "benchmark/benchmark.h"
#endif
extern "C" void boxBlurKernel(int height, int width, int *inpImage,
int *outpImage);
extern "C" void gaussianBlurKernel(int height, int width, int *inpImage,
int *outpImage);
int *inputImage;
int main(int argc, char *argv[]) {
#ifdef BENCHMARK_LIB
::benchmark::Initialize(&argc, argv);
#endif
const char *boxBlurOutputFileName = (const char *)"./boxBlurOutput.txt";
const char *gaussianBlurOutputFileName =
(const char *)"./gaussianBlurOutput.txt";
inputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH));
if (inputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
initializeRandomImage(inputImage, HEIGHT, WIDTH);
// Run Kernels Using Benchmark Library
#ifdef BENCHMARK_LIB
::benchmark::RunSpecifiedBenchmarks();
#endif
// Run Kernels once more and save output in a file for Verification
int *outputImage;
outputImage = (int *)malloc(sizeof(int) * (HEIGHT) * (WIDTH));
if (outputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
boxBlurKernel(HEIGHT, WIDTH, inputImage, outputImage);
// Blur not applied on edges so we add a black border
// Otherwise we may get garbage value which may create problem in output
// verification
int offset = (BOX_SIZE - 1) / 2;
// Top Edge
for (int i = 0; i < offset; i++) {
for (int j = 0; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Bottom Edge
for (int i = HEIGHT - offset; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Left Edge
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < offset; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Right Edge
for (int i = 0; i < HEIGHT; i++) {
for (int j = WIDTH - offset; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
saveImage(outputImage, boxBlurOutputFileName, HEIGHT, WIDTH);
gaussianBlurKernel(HEIGHT, WIDTH, inputImage, outputImage);
// Top Edge
for (int i = 0; i < offset; i++) {
for (int j = 0; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Bottom Edge
for (int i = HEIGHT - offset; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Left Edge
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < offset; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
// Right Edge
for (int i = 0; i < HEIGHT; i++) {
for (int j = WIDTH - offset; j < WIDTH; j++) {
outputImage[i * WIDTH + j] = 0;
}
}
saveImage(outputImage, gaussianBlurOutputFileName, HEIGHT, WIDTH);
free(outputImage);
free(inputImage);
return EXIT_SUCCESS;
}
#ifdef BENCHMARK_LIB
void BENCHMARK_boxBlurKernel(benchmark::State &state) {
int height = state.range(0);
int width = state.range(0);
int *outputImage = (int *)malloc(sizeof(int) * (height) * (width));
if (outputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
/* This call is to warm up the cache */
boxBlurKernel(height, width, inputImage, outputImage);
while (state.KeepRunning()) {
boxBlurKernel(height, width, inputImage, outputImage);
}
/* Since we are not passing state.range as 20 this if case will always be
* false. This if case is to prevent above kernel calls from getting optimized
* out */
if (state.range(0) == 20) {
saveImage(outputImage, (const char *)"testFailed.txt", height, width);
}
free(outputImage);
}
BENCHMARK(BENCHMARK_boxBlurKernel)
->Arg(128)
->Arg(256)
->Arg(512)
->Arg(1024)
->Unit(benchmark::kMicrosecond);
void BENCHMARK_GAUSSIAN_BLUR(benchmark::State &state) {
int height = state.range(0);
int width = state.range(0);
int *outputImage = (int *)malloc(sizeof(int) * (height) * (width));
if (outputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
/* This call is to warm up the cache */
gaussianBlurKernel(height, width, inputImage, outputImage);
while (state.KeepRunning()) {
gaussianBlurKernel(height, width, inputImage, outputImage);
}
/* Since we are not passing state.range as 20 this if case will always be
* false. This if case is to prevent above kernel calls from getting optimized
* out */
if (state.range(0) == 20) {
saveImage(outputImage, (const char *)"testFailed.txt", height, width);
}
free(outputImage);
}
BENCHMARK(BENCHMARK_GAUSSIAN_BLUR)
->Arg(128)
->Arg(256)
->Arg(512)
->Arg(1024)
->Unit(benchmark::kMicrosecond);
#endif