Index: MicroBenchmarks/CMakeLists.txt =================================================================== --- MicroBenchmarks/CMakeLists.txt +++ MicroBenchmarks/CMakeLists.txt @@ -5,5 +5,5 @@ add_subdirectory(XRay) add_subdirectory(LCALS) add_subdirectory(harris) - + add_subdirectory(ImageProcessing) endif() Index: MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/Blur/CMakeLists.txt @@ -0,0 +1,16 @@ +set(IMAGEPROC_UTILS MicroBenchmarks/ImageProcessing/utils) +list(APPEND CPPFLAGS -I ${CMAKE_SOURCE_DIR}/${IMAGEPROC_UTILS} -std=c++11 -ffast-math) + + + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/boxBlurOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/boxBlurOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/boxBlur.reference_output") + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/gaussianBlurOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/gaussianBlurOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/gaussianBlur.reference_output") + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) + +llvm_test_executable(blur ../utils/ImageHelper.cpp main.cpp boxBlurKernel.cpp gaussianBlurKernel.cpp) + +target_link_libraries(blur benchmark) Index: MicroBenchmarks/ImageProcessing/Blur/blur.h =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/blur.h +++ MicroBenchmarks/ImageProcessing/Blur/blur.h @@ -0,0 +1,30 @@ +#ifndef _BOX_BLUR_H +#define _BOX_BLUR_H + +#include +#include +#include +#include + + +#ifndef HEIGHT +#define HEIGHT 1024 +#endif + +#ifndef WIDTH +#define WIDTH 1024 +#endif + + + +// Bigger the box size +// More is blur +#define BOX_SIZE 9 + +void boxBlurKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[HEIGHT][WIDTH], int height, int width); +void gaussianBlurKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[HEIGHT][WIDTH], int height, int width); + +#endif +// _BOX_BLUR_H end Index: MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output +++ MicroBenchmarks/ImageProcessing/Blur/boxBlur.reference_output @@ -0,0 +1 @@ +d976614a6d0487da6873eb9de4044480 Index: MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.cpp +++ MicroBenchmarks/ImageProcessing/Blur/boxBlurKernel.cpp @@ -0,0 +1,20 @@ +#include "blur.h" +void boxBlurKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[HEIGHT][WIDTH], int height, int width) { + int sum_in_window = 0; + int offset = (BOX_SIZE - 1) / 2; + int n = BOX_SIZE * BOX_SIZE; + + for (int i = offset; i < height - offset; i++) { + for (int j = offset; j < width - offset; j++) { + /* Computing sum of elements in window centered at i,j */ + sum_in_window = 0; + for (int k = -1 * offset; k < offset; k++) { + for (int l = -1 * offset; l < offset; l++) { + sum_in_window += inputImage[i + k][j + l]; + } + } + outputImage[i][j] = (sum_in_window) / (n); + } + } +} \ No newline at end of file Index: MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output +++ MicroBenchmarks/ImageProcessing/Blur/gaussianBlur.reference_output @@ -0,0 +1 @@ +bf45e940640684676f0175304b9c249a Index: MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.cpp +++ MicroBenchmarks/ImageProcessing/Blur/gaussianBlurKernel.cpp @@ -0,0 +1,40 @@ +#include "blur.h" + +void gaussianBlurKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[HEIGHT][WIDTH], int height, int width) { + // Allocating memory for output inputImage + int(*__restrict__ img2dblur)[HEIGHT][WIDTH]; + img2dblur = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * (HEIGHT) * + (WIDTH)); + + float sigma = 9; + float s = 2.0 * sigma * sigma; // 2 * (sigma)^2 + int offset = (BOX_SIZE - 1) / 2; + + // generating kernel + float sumGaussianKernel = 0; + float gaussianFilter[BOX_SIZE][BOX_SIZE] = {0}; + + for (int x = -1 * offset; x <= offset; x++) { + for (int y = -1 * offset; y <= offset; y++) { + gaussianFilter[x + offset][y + offset] = + (exp(-(x * x + y * y) / s)) / (M_PI * s); + sumGaussianKernel += gaussianFilter[x + offset][y + offset]; + } + } + + float sum_in_window = 0; + for (int i = offset; i < height - offset; i++) { + for (int j = offset; j < width - offset; j++) { + /* Computing sum of elements in window centered at i,j */ + sum_in_window = 0; + for (int k = -1 * offset; k <= offset; k++) { + for (int l = -1 * offset; l <= offset; l++) { + sum_in_window += (inputImage[i + k][j + l] * + gaussianFilter[k + offset][l + offset]); + } + } + outputImage[i][j] = (sum_in_window) / sumGaussianKernel; + } + } +} Index: MicroBenchmarks/ImageProcessing/Blur/main.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Blur/main.cpp +++ MicroBenchmarks/ImageProcessing/Blur/main.cpp @@ -0,0 +1,165 @@ +#include "ImageHelper.h" +#include "blur.h" + +#define BENCHMARK_LIB +#ifdef BENCHMARK_LIB +#include "benchmark/benchmark.h" +#endif + +int (*__restrict__ inputImage)[HEIGHT][WIDTH]; +int main(int argc, char *argv[]) { + +#ifdef BENCHMARK_LIB + ::benchmark::Initialize(&argc, argv); +#endif + + char *boxBlurOutputFileName = (char *)"./boxBlurOutput.txt"; + char *gaussianBlurOutputFileName = (char *)"./gaussianBlurOutput.txt"; + + inputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + initializeRandomImage((int *)(*inputImage), HEIGHT, WIDTH); + +// Run Kernels Using Benchmark Library +#ifdef BENCHMARK_LIB + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + // Run Box Blur + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + boxBlurKernel(*inputImage, *outputImage, HEIGHT, WIDTH); + + // 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][j] = 0; + } + } + + // Bottom Edge + for (int i = HEIGHT - offset; i < HEIGHT; i++) { + for (int j = 0; j < WIDTH; j++) { + (*outputImage)[i][j] = 0; + } + } + + // Left Edge + for (int i = 0; i < HEIGHT; i++) { + for (int j = 0; j < offset; j++) { + (*outputImage)[i][j] = 0; + } + } + // Right Edge + for (int i = 0; i < HEIGHT; i++) { + for (int j = WIDTH - offset; j < WIDTH; j++) { + (*outputImage)[i][j] = 0; + } + } + + saveImage((int *)(*outputImage), boxBlurOutputFileName, HEIGHT, WIDTH); + free((void *)outputImage); + + // Run Gaussian Blur + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + gaussianBlurKernel(*inputImage, *outputImage, HEIGHT, WIDTH); + + // Top Edge + for (int i = 0; i < offset; i++) { + for (int j = 0; j < WIDTH; j++) { + (*outputImage)[i][j] = 0; + } + } + + // Bottom Edge + for (int i = HEIGHT - offset; i < HEIGHT; i++) { + for (int j = 0; j < WIDTH; j++) { + (*outputImage)[i][j] = 0; + } + } + + // Left Edge + for (int i = 0; i < HEIGHT; i++) { + for (int j = 0; j < offset; j++) { + (*outputImage)[i][j] = 0; + } + } + // Right Edge + for (int i = 0; i < HEIGHT; i++) { + for (int j = WIDTH - offset; j < WIDTH; j++) { + (*outputImage)[i][j] = 0; + } + } + + saveImage((int *)(*outputImage), gaussianBlurOutputFileName, HEIGHT, WIDTH); + free((void *)outputImage); + + free((void *)inputImage); + return EXIT_SUCCESS; +} + +#ifdef BENCHMARK_LIB +void BENCHMARK_boxBlurKernel(benchmark::State &state) { + + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + int height = state.range(0); + int width = state.range(1); + boxBlurKernel(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + boxBlurKernel(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + // Anyway should never reach here + saveImage((int *)(*outputImage), (char *)"testFailed.txt", HEIGHT, WIDTH); + } + + free((void *)outputImage); +} + +// We read entire Image, but only convert a part of image to blur to see how it +// Scales +BENCHMARK(BENCHMARK_boxBlurKernel) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Args({1024, 1024}) + ->Unit(benchmark::kMicrosecond); + +void BENCHMARK_gaussianBlurKernel(benchmark::State &state) { + + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + int height = state.range(0); + int width = state.range(1); + gaussianBlurKernel(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + gaussianBlurKernel(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + saveImage((int *)(*outputImage), (char *)"testFailed.txt", HEIGHT, WIDTH); + } + + free((void *)outputImage); +} + +BENCHMARK(BENCHMARK_gaussianBlurKernel) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Args({1024, 1024}) + ->Unit(benchmark::kMicrosecond); +#endif Index: MicroBenchmarks/ImageProcessing/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Blur) +add_subdirectory(Dither) +add_subdirectory(Interpolation) +add_subdirectory(RGBtoGrayScale) \ No newline at end of file Index: MicroBenchmarks/ImageProcessing/Dither/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/Dither/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/Dither/CMakeLists.txt @@ -0,0 +1,15 @@ +set(IMAGEPROC_UTILS MicroBenchmarks/ImageProcessing/utils) +list(APPEND CPPFLAGS -I ${CMAKE_SOURCE_DIR}/${IMAGEPROC_UTILS} -std=c++11 -ffast-math) + + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/orderedOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/orderedOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/orderedDither.reference_output") + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) +llvm_test_executable(dither main.cpp orderedDitherKernel.cpp ../utils/ImageHelper.cpp) + +target_link_libraries(dither benchmark) + + + + Index: MicroBenchmarks/ImageProcessing/Dither/dither.h =================================================================== --- MicroBenchmarks/ImageProcessing/Dither/dither.h +++ MicroBenchmarks/ImageProcessing/Dither/dither.h @@ -0,0 +1,32 @@ +#ifndef _DITHER_H_ +#define _DITHER_H_ + +#include +#include +#include +#include +#include +#include + + +#define MaxGray 255 +#define MXGRAY 256 + + +#define N 16 +#define M 4 +#define GAMMA 0.5 + +#ifndef HEIGHT +#define HEIGHT 1024 +#endif + +#ifndef WIDTH +#define WIDTH 1024 +#endif + + + +void orderedDitherKernel(int inputImage[HEIGHT][WIDTH], int outputImage[HEIGHT][WIDTH], int height, int width); +#endif +// _DITHER_H_ end Index: MicroBenchmarks/ImageProcessing/Dither/main.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Dither/main.cpp +++ MicroBenchmarks/ImageProcessing/Dither/main.cpp @@ -0,0 +1,66 @@ +#include "ImageHelper.h" +#include "dither.h" + +#define BENCHMARK_LIB +#ifdef BENCHMARK_LIB +#include "benchmark/benchmark.h" +#endif + +int (*__restrict__ inputImage)[HEIGHT][WIDTH]; + +using namespace std; + +int main(int argc, char **argv) { +#ifdef BENCHMARK_LIB + ::benchmark::Initialize(&argc, argv); +#endif + + char *orderedOutputFilename = (char *)"./orderedOutput.txt"; + + inputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + + initializeRandomImage((int *)(*inputImage), HEIGHT, WIDTH); + +#ifdef BENCHMARK_LIB + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + orderedDitherKernel(*inputImage, *outputImage, HEIGHT, WIDTH); + + saveImage((int *)(*outputImage), orderedOutputFilename, HEIGHT, WIDTH); + + free((void *)outputImage); + free((void *)inputImage); + return 0; +} + +#ifdef BENCHMARK_LIB +void BENCHMARK_ORDERED_DITHER(benchmark::State &state) { + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + int height = state.range(0); + int width = state.range(1); + orderedDitherKernel(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + orderedDitherKernel(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + saveImage((int *)(*outputImage), (char *)"failedCase.txt", HEIGHT, WIDTH); + } + + free((void *)outputImage); +} +BENCHMARK(BENCHMARK_ORDERED_DITHER) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Args({1024, 1024}) + ->Unit(benchmark::kMicrosecond); +#endif \ No newline at end of file Index: MicroBenchmarks/ImageProcessing/Dither/orderedDither.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/Dither/orderedDither.reference_output +++ MicroBenchmarks/ImageProcessing/Dither/orderedDither.reference_output @@ -0,0 +1 @@ +c36c928731bafb3568f0f7c6c24a99be Index: MicroBenchmarks/ImageProcessing/Dither/orderedDitherKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Dither/orderedDitherKernel.cpp +++ MicroBenchmarks/ImageProcessing/Dither/orderedDitherKernel.cpp @@ -0,0 +1,64 @@ +#include "dither.h" +void orderedDitherKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[HEIGHT][WIDTH], int height, + int width) { + int scale; + + // initialize the dither matrices + int dither2[2][2] = {{0, 2}, {3, 1}}; + + int dither3[3][3] = {{6, 8, 4}, {1, 0, 3}, {5, 2, 7}}; + + int dither4[4][4] = { + {0, 8, 2, 10}, {12, 4, 14, 6}, {3, 11, 1, 9}, {15, 7, 13, 5}}; + + int dither8[8][8] = { + {0, 48, 12, 60, 3, 51, 15, 63}, {32, 16, 44, 28, 35, 19, 47, 31}, + {8, 56, 4, 52, 11, 59, 7, 55}, {40, 24, 36, 20, 43, 27, 39, 23}, + {2, 50, 14, 62, 1, 49, 13, 61}, {34, 18, 46, 30, 33, 17, 45, 29}, + {10, 58, 6, 54, 9, 57, 5, 53}, {42, 26, 38, 22, 41, 25, 37, 21}}; + + int(*__restrict__ tmp_out)[HEIGHT][WIDTH]; + tmp_out = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * (HEIGHT) * + (WIDTH)); + + if (tmp_out == NULL) { + std::cerr << "Insufficient memory\n"; + exit(1); + } + + // this should produce gamma corrected image from look up table. + // and store the image in tmp_out; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + (*tmp_out)[i][j] = + (int)(pow((double)inputImage[i][j] / 255.0, (1.0 / GAMMA)) * 255.0); + } + } + + scale = 256 / N; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + outputImage[i][j] = (int)(scale * ((*tmp_out)[i][j] / scale)) / scale; + } + } + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int i = x % M; + int j = y % M; + if (M == 2) { + outputImage[y][x] = ((outputImage[y][x] > dither2[i][j]) ? 255 : 0); + } else if (M == 3) { + outputImage[y][x] = ((outputImage[y][x] > dither3[i][j]) ? 255 : 0); + } else if (M == 4) { + outputImage[y][x] = ((outputImage[y][x] > dither4[i][j]) ? 255 : 0); + } else if (M == 8) { + outputImage[y][x] = ((outputImage[y][x] > dither8[i][j]) ? 255 : 0); + } else { + std::cerr + << " Error: selected M not allowed, choose M from [2, 3, 4, 8]\n"; + } + } + } +} Index: MicroBenchmarks/ImageProcessing/Interpolation/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/Interpolation/CMakeLists.txt @@ -0,0 +1,12 @@ +set(IMAGEPROC_UTILS MicroBenchmarks/ImageProcessing/utils) +list(APPEND CPPFLAGS -I ${CMAKE_SOURCE_DIR}/${IMAGEPROC_UTILS} -std=c++11 -ffast-math) + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/bicubicOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/bicubicOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/bicubic.reference_output") + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/bilinearOutput.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/bilinearOutput.txt ${CMAKE_CURRENT_SOURCE_DIR}/bilinear.reference_output") + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) +llvm_test_executable(interpolation bicubicKernel.cpp bilinearKernel.cpp main.cpp ../utils/ImageHelper.cpp) +target_link_libraries(interpolation benchmark) Index: MicroBenchmarks/ImageProcessing/Interpolation/bicubic.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/bicubic.reference_output +++ MicroBenchmarks/ImageProcessing/Interpolation/bicubic.reference_output @@ -0,0 +1 @@ +85b325b971e5244594e462adc2c81f48 Index: MicroBenchmarks/ImageProcessing/Interpolation/bicubicKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/bicubicKernel.cpp +++ MicroBenchmarks/ImageProcessing/Interpolation/bicubicKernel.cpp @@ -0,0 +1,75 @@ +#include "interpolation.h" +// bicubic-interpolation-image-processing... github/google code archive +void bicubicKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[NEWHEIGHT][NEWWIDTH], int height, + int width) { + float Cc; + float C[5] = {0}; + float a, b, c, d, e, f, g; + int x, y; + + const int newheight = ZOOM * height; + const int newwidth = ZOOM * width; + + // const float tx = (float)1/(float)ZOOM; + // const float ty = (float)1/(float)ZOOM; + for (int i = 0; i < newheight; i++) { + for (int j = 0; j < newwidth; j++) { + y = i / ZOOM; + x = j / ZOOM; + + const float dx = j / (float)ZOOM - x; + const float dy = i / (float)ZOOM - y; + + for (int jj = 0; jj <= 3; jj++) { + + // These if//else to make sure we are in array bounds... + if ((y + jj - 1) < 0) { + a = 0; + b = 0; + c = 0; + d = 0; + } else if ((x - 1) < 0) { + a = inputImage[y + jj - 1][x]; + b = -1 * a; + c = inputImage[y + jj - 1][x + 1] - a; + d = inputImage[y + jj - 1][x + 2] - a; + } else if ((x + 1) >= width) { + a = inputImage[y + jj - 1][x]; + b = inputImage[y + jj - 1][x - 1] - a; + c = -1 * a; + d = inputImage[y + jj - 1][x + 2] - a; + } else if ((x + 2) >= width) { + a = inputImage[y + jj - 1][x]; + b = inputImage[y + jj - 1][x - 1] - a; + c = inputImage[y + jj - 1][x + 1] - a; + d = -1 * a; + } else { + a = inputImage[y + jj - 1][x]; + b = inputImage[y + jj - 1][x - 1] - a; + c = inputImage[y + jj - 1][x + 1] - a; + d = inputImage[y + jj - 1][x + 2] - a; + } + + e = -1.0 / 3 * b + c - 1.0 / 6 * d; + f = 1.0 / 2 * b + 1.0 / 2 * c; + g = -1.0 / 6 * b - 1.0 / 2 * c + 1.0 / 6 * d; + + C[jj] = a + e * dx + f * dx * dx + g * dx * dx * dx; + + a = C[1]; + b = C[0] - C[1]; + c = C[2] - C[1]; + d = C[3] - C[1]; + + e = -1.0 / 3 * b + c - 1.0 / 6 * d; + f = 1.0 / 2 * b + 1.0 / 2 * c; + g = -1.0 / 6 * b - 1.0 / 2 * c + 1.0 / 6 * d; + + Cc = a + e * dy + f * dy * dy + g * dy * dy * dy; + + outputImage[i][j] = (int)Cc; + } + } + } +} Index: MicroBenchmarks/ImageProcessing/Interpolation/bilinear.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/bilinear.reference_output +++ MicroBenchmarks/ImageProcessing/Interpolation/bilinear.reference_output @@ -0,0 +1 @@ +ae0245749e85e1bb6674515250308a75 Index: MicroBenchmarks/ImageProcessing/Interpolation/bilinearKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/bilinearKernel.cpp +++ MicroBenchmarks/ImageProcessing/Interpolation/bilinearKernel.cpp @@ -0,0 +1,37 @@ +#include "interpolation.h" + +void bilinearKernel(int inputImage[HEIGHT][WIDTH], + int outputImage[NEWHEIGHT][NEWWIDTH], int height, + int width) { + int x, y; + + // float tx = (float)NEWWIDTH/(WIDTH); + // float ty = (float)NEWHEIGHT/(HEIGHT); + + float x_diff, y_diff; + int i, j; + int newHeight = ZOOM * height; + int newWidth = ZOOM * width; + + for (i = 0; i < newHeight; i++) { + for (j = 0; j < newWidth; j++) { + x = j / ZOOM; + y = i / ZOOM; + + x_diff = ((j / (float)ZOOM) - x); + y_diff = ((i / (float)ZOOM) - y); + if ((x + 1) < width && (y + 1) < height) { + outputImage[i][j] = inputImage[y][x] * (1 - x_diff) * (1 - y_diff) + + inputImage[y][x + 1] * (1 - y_diff) * (x_diff) + + inputImage[y + 1][x] * (y_diff) * (1 - x_diff) + + inputImage[y + 1][x + 1] * (y_diff) * (x_diff); + } else if ((x + 1) < width) { + outputImage[i][j] = inputImage[y][x] * (1 - x_diff) * (1 - y_diff) + + inputImage[y][x + 1] * (1 - y_diff) * (x_diff); + } else { + outputImage[i][j] = inputImage[y][x] * (1 - x_diff) * (1 - y_diff) + + inputImage[y + 1][x] * (y_diff) * (1 - x_diff); + } + } + } +} \ No newline at end of file Index: MicroBenchmarks/ImageProcessing/Interpolation/interpolation.h =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/interpolation.h +++ MicroBenchmarks/ImageProcessing/Interpolation/interpolation.h @@ -0,0 +1,34 @@ +#ifndef _INTERPOLATION_H_ +#define _INTERPOLATION_H_ + +#include +#include +#include +#include +#include +#include + +#ifndef HEIGHT +#define HEIGHT 1024 +#endif + +#ifndef WIDTH +#define WIDTH 1024 +#endif + + +#define OLDHEIGHT HEIGHT +#define OLDWIDTH WIDTH + +// 4x zoom +// ZOOM > 1 .... +#define ZOOM 4 + +#define NEWHEIGHT (int)(ZOOM*HEIGHT) +#define NEWWIDTH (int)(ZOOM*WIDTH) + +void bicubicKernel(int inputImage[HEIGHT][WIDTH], int outputImage[NEWHEIGHT][NEWWIDTH], int height, int width); +void bilinearKernel(int inputImage[HEIGHT][WIDTH], int outputImage[NEWHEIGHT][NEWWIDTH], int height, int width); + +#endif +// _INTERPOLATION_H_ end Index: MicroBenchmarks/ImageProcessing/Interpolation/main.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/Interpolation/main.cpp +++ MicroBenchmarks/ImageProcessing/Interpolation/main.cpp @@ -0,0 +1,102 @@ +#include "ImageHelper.h" +#include "interpolation.h" + +#define BENCHMARK_LIB +#ifdef BENCHMARK_LIB +#include "benchmark/benchmark.h" +#endif + +int (*__restrict__ inputImage)[HEIGHT][WIDTH]; + +int main(int argc, char **argv) { +#ifdef BENCHMARK_LIB + ::benchmark::Initialize(&argc, argv); +#endif + + char *bicubicOutputFilename = (char *)"./bicubicOutput.txt"; + char *bilinearOutputFileName = (char *)"./bilinearOutput.txt"; + + inputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + + int(*__restrict__ outputImage)[NEWHEIGHT][NEWWIDTH]; + outputImage = (int(*__restrict__)[NEWHEIGHT][NEWWIDTH])malloc( + sizeof(int) * (NEWHEIGHT) * (NEWWIDTH)); + + initializeRandomImage((int *)*inputImage, HEIGHT, WIDTH); + +#ifdef BENCHMARK_LIB + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + bicubicKernel(*inputImage, *outputImage, HEIGHT, WIDTH); + + saveImage((int *)(*outputImage), bicubicOutputFilename, NEWHEIGHT, NEWWIDTH); + + free((void *)outputImage); + + outputImage = (int(*__restrict__)[NEWHEIGHT][NEWWIDTH])malloc( + sizeof(int) * (NEWHEIGHT) * (NEWWIDTH)); + bilinearKernel(*inputImage, *outputImage, HEIGHT, WIDTH); + + saveImage((int *)(*outputImage), bilinearOutputFileName, NEWHEIGHT, NEWWIDTH); + + free((void *)inputImage); + free((void *)outputImage); + return 0; +} + +#ifdef BENCHMARK_LIB +void BENCHMARK_BICUBIC_INTERPOLATION(benchmark::State &state) { + int(*__restrict__ outputImage)[NEWHEIGHT][NEWWIDTH]; + outputImage = (int(*__restrict__)[NEWHEIGHT][NEWWIDTH])malloc( + sizeof(int) * (NEWHEIGHT) * (NEWWIDTH)); + int height = state.range(0); + int width = state.range(1); + bicubicKernel(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + bicubicKernel(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + saveImage((int *)(*outputImage), (char *)"failedCase.txt", NEWHEIGHT, + NEWWIDTH); + } + + free((void *)outputImage); +} +BENCHMARK(BENCHMARK_BICUBIC_INTERPOLATION) + ->Args({64, 64}) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Unit(benchmark::kMicrosecond); + +void BENCHMARK_BILINEAR_INTERPOLATION(benchmark::State &state) { + int(*__restrict__ outputImage)[NEWHEIGHT][NEWWIDTH]; + outputImage = (int(*__restrict__)[NEWHEIGHT][NEWWIDTH])malloc( + sizeof(int) * (NEWHEIGHT) * (NEWWIDTH)); + int height = state.range(0); + int width = state.range(1); + bilinearKernel(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + bilinearKernel(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + saveImage((int *)(*outputImage), (char *)"failedCase.txt", NEWHEIGHT, + NEWWIDTH); + } + + free((void *)outputImage); +} +BENCHMARK(BENCHMARK_BILINEAR_INTERPOLATION) + ->Args({64, 64}) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Unit(benchmark::kMicrosecond); + +#endif \ No newline at end of file Index: MicroBenchmarks/ImageProcessing/RGBtoGrayScale/CMakeLists.txt =================================================================== --- MicroBenchmarks/ImageProcessing/RGBtoGrayScale/CMakeLists.txt +++ MicroBenchmarks/ImageProcessing/RGBtoGrayScale/CMakeLists.txt @@ -0,0 +1,16 @@ +set(IMAGEPROC_UTILS MicroBenchmarks/ImageProcessing/utils) +list(APPEND CPPFLAGS -I ${CMAKE_SOURCE_DIR}/${IMAGEPROC_UTILS} -std=c++11 -ffast-math) + +llvm_test_verify("${CMAKE_SOURCE_DIR}/HashProgramOutput.sh ${CMAKE_CURRENT_BINARY_DIR}/grayImage.txt") +llvm_test_verify("${FPCMP} ${CMAKE_CURRENT_BINARY_DIR}/grayImage.txt ${CMAKE_CURRENT_SOURCE_DIR}/cvtcolor.reference_output") + + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) +llvm_test_executable(cvtColor cvtColorKernel.cpp main.cpp ../utils/ImageHelper.cpp) + +target_link_libraries(cvtColor benchmark) + + + + + Index: MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColor.h =================================================================== --- MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColor.h +++ MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColor.h @@ -0,0 +1,21 @@ +#ifndef _BOX_BLUR_H +#define _BOX_BLUR_H + +#include +#include +#include +#include + +#ifndef HEIGHT +#define HEIGHT 1024 +#endif + +#ifndef WIDTH +#define WIDTH 1024 +#endif + + +void rgbToGray(int inputImage[HEIGHT][WIDTH][3], int outputImage[HEIGHT][WIDTH], int height, int width); + +#endif +// _BOX_BLUR_H end Index: MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColorKernel.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColorKernel.cpp +++ MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtColorKernel.cpp @@ -0,0 +1,14 @@ +#include "cvtColor.h" + +// Using Averaging +void rgbToGray(int inputImage[HEIGHT][WIDTH][3], int outputImage[HEIGHT][WIDTH], + int height, int width) { + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + // 0.21 R + 0.72 G + 0.07 B + outputImage[i][j] = 0.21 * inputImage[i][j][0] + + 0.72 * inputImage[i][j][1] + + 0.07 * inputImage[i][j][2]; + } + } +} Index: MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtcolor.reference_output =================================================================== --- MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtcolor.reference_output +++ MicroBenchmarks/ImageProcessing/RGBtoGrayScale/cvtcolor.reference_output @@ -0,0 +1 @@ +d1032182b69683b2596411df8040a3d7 Index: MicroBenchmarks/ImageProcessing/RGBtoGrayScale/main.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/RGBtoGrayScale/main.cpp +++ MicroBenchmarks/ImageProcessing/RGBtoGrayScale/main.cpp @@ -0,0 +1,70 @@ +#include "ImageHelper.h" +#include "cvtColor.h" + +#define BENCHMARK_LIB +#ifdef BENCHMARK_LIB +#include "benchmark/benchmark.h" +#endif + +int (*__restrict__ inputImage)[HEIGHT][WIDTH][3]; +int main(int argc, char *argv[]) { +#ifdef BENCHMARK_LIB + ::benchmark::Initialize(&argc, argv); +#endif + + char *grayImageOutput = (char *)"./grayImage.txt"; + + inputImage = (int(*__restrict__)[HEIGHT][WIDTH][3])malloc( + sizeof(int) * (HEIGHT) * (WIDTH) * (3)); + + initializeRandomColouredImage((int *)*inputImage, HEIGHT, WIDTH); + +// Run Kernels Using Benchmark Library +#ifdef BENCHMARK_LIB + ::benchmark::RunSpecifiedBenchmarks(); +#endif + + // Run Box Blur + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + + rgbToGray(*inputImage, *outputImage, HEIGHT, WIDTH); + + saveImage((int*)(*outputImage), grayImageOutput, HEIGHT, WIDTH); + free((void *)outputImage); + + return EXIT_SUCCESS; +} + +#ifdef BENCHMARK_LIB +void BENCHMARK_RGBTOGRAYSCALE(benchmark::State &state) { + + int(*__restrict__ outputImage)[HEIGHT][WIDTH]; + outputImage = (int(*__restrict__)[HEIGHT][WIDTH])malloc(sizeof(int) * + (HEIGHT) * (WIDTH)); + int height = state.range(0); + int width = state.range(1); + rgbToGray(*inputImage, *outputImage, height, width); + + for (auto _ : state) { + rgbToGray(*inputImage, *outputImage, height, width); + } + + if (state.range(0) == 20) { + // Anyway should never reach here + saveImage((int*)(*outputImage), (char *)"testFailed.txt", HEIGHT, WIDTH); + } + + free((void *)outputImage); +} + +// We read entire Image, but only convert a part of image to blur to see how it +// Scales +BENCHMARK(BENCHMARK_RGBTOGRAYSCALE) + ->Args({128, 128}) + ->Args({256, 256}) + ->Args({512, 512}) + ->Args({1024, 1024}) + ->Unit(benchmark::kMicrosecond); +#endif Index: MicroBenchmarks/ImageProcessing/utils/ImageHelper.h =================================================================== --- MicroBenchmarks/ImageProcessing/utils/ImageHelper.h +++ MicroBenchmarks/ImageProcessing/utils/ImageHelper.h @@ -0,0 +1,18 @@ +#ifndef _IMAGEHELPER_H_ +#define _IMAGEHELPER_H_ + +// This File contains some helper functions to initialize +#include +#include +#include +#include +#include +#include + + +void initializeRandomImage(int *image, int height, int width); +void initializeRandomColouredImage(int *image, int height, int width); +void saveImage(int *image, char *outputFile, int height, int width); + +#endif +//_IMAGEHELPER_H_ end Index: MicroBenchmarks/ImageProcessing/utils/ImageHelper.cpp =================================================================== --- MicroBenchmarks/ImageProcessing/utils/ImageHelper.cpp +++ MicroBenchmarks/ImageProcessing/utils/ImageHelper.cpp @@ -0,0 +1,45 @@ +#include "ImageHelper.h" + +// Initializes a random Image +void initializeRandomImage(int *image, int height, int width) { + srand(7); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + image[i * width + j] = rand() % 256; + } + } +} + +void saveImage(int *image, char *outputFile, int height, int width) { + std::ofstream outfile; + outfile.open(outputFile, std::ios::out | std::ios::trunc); + + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + // Just for safety + if (image[i * width + j] > 255) { + outfile << 255 << " "; + ; + } else if (image[i * width + j] < 0) { + outfile << 0 << " "; + ; + } else { + outfile << image[i * width + j] << " "; + ; + } + } + outfile << std::endl; + } +} + +// Initializes a random Image +void initializeRandomColouredImage(int *image, int height, int width) { + srand(7); + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + image[i * (width * 3) + j * 3 + 0] = rand() % 256; + image[i * (width * 3) + j * 3 + 1] = rand() % 256; + image[i * (width * 3) + j * 3 + 2] = rand() % 256; + } + } +} \ No newline at end of file