diff --git a/include/workaround.hpp b/include/workaround.hpp index 18ffbc4..2a06d9e 100644 --- a/include/workaround.hpp +++ b/include/workaround.hpp @@ -4,4 +4,10 @@ class MatrixProcessor { public: void Threshold(unsigned char* const data, const int width, const int height, const int threshold); + + void Averaging(unsigned char* const data, const int width, const int height, + const int surroundings); + + void MedianFilter(unsigned char* const data, const int width, + const int height, const int surroundings); }; diff --git a/src/workaround.cpp b/src/workaround.cpp index 2eba458..694c7b5 100644 --- a/src/workaround.cpp +++ b/src/workaround.cpp @@ -1,10 +1,74 @@ +#include +#include +#include #include "workaround.hpp" -#include -using namespace std; void MatrixProcessor::Threshold(unsigned char* const data, const int width, const int height, const int threshold) { - // TODO: Add thresholding logic here. + for (int i = 0; i < width * height; i++) + if (data[i] < threshold) + data[i] = 0; +} + +void MatrixProcessor::Averaging(unsigned char* const data, const int width, + const int height, const int surroundings) { + unsigned char* dst = new unsigned char[width * height]; + + for (int i = 0; i < width * height; i++) { + int sum = 0, count = 0; + + for (int k = -surroundings; k <= surroundings; k++) { + if (i / width < 1 && k < 0 || i / width == width - 1 && k > 0) + continue; + + for (int l = -surroundings; l <= surroundings; l++) { + if (i % width == 0 && l < 0 || (i + 1) % width == 0 && l > 0) + continue; + + int index = i + k * width + l; + + sum += data[index]; + count++; + } + } + + dst[i] = sum / count; + } + + memcpy(data, dst, width * height); + delete[] dst; +} + +void MatrixProcessor::MedianFilter(unsigned char* const data, const int width, + const int height, const int surroundings) { + unsigned char* dst = new unsigned char[width * height]; + + for (int i = 0; i < width * height; i++) { + std::vector vect; + + for (int k = -surroundings; k <= surroundings; k++) { + if (i / width < 1 && k < 0 || i / width == width - 1 && k > 0) + continue; + + for (int l = -surroundings; l <= surroundings; l++) { + if (i % width == 0 && l < 0 || (i + 1) % width == 0 && l > 0) + continue; + + int index = i + k * width + l; + + vect.push_back(data[index]); + } + } + + std::sort(vect.begin(), vect.end()); + if (vect.size() % 2 == 0) + dst[i] = (vect[vect.size() / 2 - 1] + vect[vect.size() / 2]) / 2; + else + dst[i] = vect[vect.size() / 2]; + } + + memcpy(data, dst, width * height); + delete[] dst; } diff --git a/test/test_workaround.cpp b/test/test_workaround.cpp new file mode 100644 index 0000000..307f153 --- /dev/null +++ b/test/test_workaround.cpp @@ -0,0 +1,96 @@ +#include + +#include "workaround.hpp" + +TEST(Threshold, No_Throw_When_DataOK) { + MatrixProcessor mp; + int width = 4, height = 4; + unsigned char* data; + unsigned char threshold = 5; + + data = new unsigned char[width * height]; + for (int i = 0; i < width * height; i++) + data[i] = i; + + EXPECT_NO_THROW(mp.Threshold(data, width, height, threshold)); +} + +TEST(Threshold, Correct_Work) { + MatrixProcessor mp; + int width = 4, height = 4; + unsigned char* data; + unsigned char threshold = 5; + + data = new unsigned char[width * height]; + for (int i = 0; i < width * height; i++) + data[i] = i; + + mp.Threshold(data, width, height, threshold); + EXPECT_EQ(0, data[0]); +} + +TEST(Threshold, Correct_Work_With_One_Element) { + MatrixProcessor mp; + int width = 1, height = 1; + unsigned char* data; + unsigned char threshold = 6; + + data = new unsigned char[width * height]; + data[0] = threshold + 1; + + mp.Threshold(data, width, height, threshold); + EXPECT_EQ(threshold + 1, data[0]); +} + +TEST(Averaging, Correct_Work) { + MatrixProcessor mp; + const int width = 3, height = 3; + unsigned char* data; + int surroundings = 1; + + data = new unsigned char[width * height]; + for (int i = 0; i < width * height; i++) + data[i] = i; + + unsigned char expected[width * height] = { 2,2,3,3,4,4,5,5,6 }; + mp.Averaging(data, width, height,surroundings); + + for (int i = 0; i < width * height; i++) + EXPECT_EQ(expected[i], data[i]); +} + +TEST(Averaging, Correct_Work_With_Big_Surroudings) { + MatrixProcessor mp; + const int width = 5, height = 5; + unsigned char* data; + int surroundings = 4; + int expected = 0; + + data = new unsigned char[width * height]; + for (int i = 0; i < width * height; i++) { + data[i] = i; + expected += i; + } + + expected /= width * height; + mp.Averaging(data, width, height, surroundings); + + EXPECT_EQ(expected, data[0]); +} + +TEST(MefianFilter, Correct_Work) { + MatrixProcessor mp; + const int width = 3, height = 3; + unsigned char* data; + int surroundings = 1; + + data = new unsigned char[width * height]; + for (int i = 0; i < width * height; i++) + data[i] = i; + + unsigned char expected[width * height] = { 2,2,3,3,4,4,5,5,6 }; + mp.MedianFilter(data, width, height,surroundings); + + for (int i = 0; i < width * height; i++) + EXPECT_EQ(expected[i], data[i]); +}