blob: 21faf73df2a6a33d1d4024ca1aebb7fffef80b17 [file] [log] [blame]
/**
Pankaj Kukreja
github.com/proton0001
Indian Institute of Technology Hyderabad
*/
#include "ImageHelper.h"
#include "dither.h"
#include <cmath>
#include <cstdlib>
#include <iostream> // std::cerr
#define BENCHMARK_LIB
#ifdef BENCHMARK_LIB
#include "benchmark/benchmark.h"
#endif
int *inputImage;
extern "C" {
void orderedDitherKernel(int height, int width, int *inpImage, int *outImage,
int *temp, int n, int m);
void floydDitherKernel(int height, int width, int *inpImage, int *outImage);
}
int main(int argc, char **argv) {
#ifdef BENCHMARK_LIB
::benchmark::Initialize(&argc, argv);
#endif
const char *orderedOutputFilename = (char *)"./orderedOutput.txt";
const char *floydOutputFilename = (char *)"./floydOutput.txt";
inputImage = (int *)malloc(sizeof(int) * HEIGHT * WIDTH);
if (inputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
initializeRandomImage(inputImage, HEIGHT, WIDTH);
#ifdef BENCHMARK_LIB
::benchmark::RunSpecifiedBenchmarks();
#endif
int *outputImage = (int *)malloc(sizeof(int) * HEIGHT * WIDTH);
int *temp = (int *)malloc(sizeof(int) * HEIGHT * WIDTH);
if (outputImage == NULL || temp == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
orderedDitherKernel(HEIGHT, WIDTH, inputImage, outputImage, temp, 16, 4);
saveImage(outputImage, orderedOutputFilename, HEIGHT, WIDTH);
floydDitherKernel(HEIGHT, WIDTH, inputImage, outputImage);
for (int i = 0; i < HEIGHT; i++) {
outputImage[(i)*WIDTH + 0] = 0;
outputImage[(i)*WIDTH + WIDTH - 1] = 0;
}
for (int j = 0; j < WIDTH; j++) {
outputImage[(0) * WIDTH + j] = 0;
outputImage[(HEIGHT - 1) * WIDTH + j] = 0;
}
saveImage(outputImage, floydOutputFilename, HEIGHT, WIDTH);
free(temp);
free(outputImage);
free(inputImage);
return EXIT_SUCCESS;
}
#ifdef BENCHMARK_LIB
void BENCHMARK_ORDERED_DITHER(benchmark::State &state) {
int height = state.range(0);
int width = state.range(0);
int m = state.range(1);
int n = pow(m, 2);
int *outputImage = (int *)malloc(sizeof(int) * height * width);
int *temp = (int *)malloc(sizeof(int) * height * width);
if (outputImage == NULL) {
std::cerr << "Insufficient memory\n";
exit(1);
}
/* This call is to warm up the cache */
orderedDitherKernel(height, width, inputImage, outputImage, temp, n, m);
while (state.KeepRunning()) {
orderedDitherKernel(height, width, inputImage, outputImage, temp, n, m);
}
/* Since we are not passing state.range as 20 this if case will always be
* false. This call is to make compiler think that outputImage may be used
* later so that above kernel calls will not optimize out */
if (state.range(0) == 20) {
saveImage(outputImage, (const char *)"failedCase.txt", height, width);
}
free(temp);
free(outputImage);
}
#if (HEIGHT < WIDTH)
#define MINIMUM_DIM HEIGHT
#else
#define MINIMUM_DIM WIDTH
#endif
static void CustomArguments(benchmark::internal::Benchmark *b) {
int limit = MINIMUM_DIM;
int start = 1;
if (limit > 128) {
start = 128;
}
for (int i = start; i <= limit; i <<= 1) {
b->ArgPair(i, 2);
b->ArgPair(i, 3);
b->ArgPair(i, 4);
b->ArgPair(i, 8);
}
}
BENCHMARK(BENCHMARK_ORDERED_DITHER)
->Apply(CustomArguments)
->Unit(benchmark::kMicrosecond);
void BENCHMARK_FLOYD_DITHER(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 */
floydDitherKernel(height, width, inputImage, outputImage);
while (state.KeepRunning()) {
floydDitherKernel(height, width, inputImage, outputImage);
}
/* Since we are not passing state.range as 20 this if case will always be
* false. This call is to make compiler think that outputImage may be used
* later so that above kernel calls will not optimize out */
if (state.range(0) == 20) {
saveImage(outputImage, (const char *)"failedCase.txt", height, width);
}
free(outputImage);
}
#if MINIMUM_DIM > 128
BENCHMARK(BENCHMARK_FLOYD_DITHER)
->RangeMultiplier(2)
->Range(128, MINIMUM_DIM)
->Unit(benchmark::kMicrosecond);
#else
BENCHMARK(BENCHMARK_FLOYD_DITHER)
->RangeMultiplier(2)
->Range(1, MINIMUM_DIM)
->Unit(benchmark::kMicrosecond);
#endif
#endif