]> git.sesse.net Git - movit/blobdiff - fft_convolution_effect_test.cpp
Add an FFT convolution effect.
[movit] / fft_convolution_effect_test.cpp
diff --git a/fft_convolution_effect_test.cpp b/fft_convolution_effect_test.cpp
new file mode 100644 (file)
index 0000000..f0f8527
--- /dev/null
@@ -0,0 +1,211 @@
+// Unit tests for FFTConvolutionEffect.
+
+#include <GL/glew.h>
+#include <math.h>
+
+#include "effect_chain.h"
+#include "gtest/gtest.h"
+#include "image_format.h"
+#include "test_util.h"
+#include "fft_convolution_effect.h"
+
+namespace movit {
+
+TEST(FFTConvolutionEffectTest, Identity) {
+       const int size = 4;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float out_data[size * size];
+
+       for (int convolve_size = 1; convolve_size < 10; ++convolve_size) {
+               float kernel[convolve_size * convolve_size];
+               for (int i = 0; i < convolve_size * convolve_size; ++i) {
+                       kernel[i] = 0.0f;
+               }
+               kernel[0] = 1.0f;
+
+               EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+               tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+               FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
+               tester.get_chain()->add_effect(fft_effect);
+               fft_effect->set_convolution_kernel(kernel);
+               tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+               expect_equal(data, out_data, size, size, 0.02, 0.003);
+       }
+}
+
+TEST(FFTConvolutionEffectTest, Constant) {
+       const int size = 4, convolve_size = 17;
+       const float f = 7.0f;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float expected_data[size * size] = {
+               f * 0.1, f * 1.1, f * 2.1, f * 3.1,
+               f * 0.2, f * 1.2, f * 2.2, f * 3.2,
+               f * 0.3, f * 1.3, f * 2.3, f * 3.3,
+               f * 0.4, f * 1.4, f * 2.4, f * 3.4,
+       };
+       float out_data[size * size];
+       float kernel[convolve_size * convolve_size];
+       for (int i = 0; i < convolve_size * convolve_size; ++i) {
+               kernel[i] = 0.0f;
+       }
+       kernel[0] = f;
+
+       EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+       FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
+       tester.get_chain()->add_effect(fft_effect);
+       fft_effect->set_convolution_kernel(kernel);
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+       // Somewhat looser bounds due to the higher magnitude.
+       expect_equal(expected_data, out_data, size, size, f * 0.03, f * 0.004);
+}
+
+TEST(FFTConvolutionEffectTest, MoveRight) {
+       const int size = 4, convolve_size = 3;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float kernel[convolve_size * convolve_size] = {
+               0.0, 1.0, 0.0,
+               0.0, 0.0, 0.0,
+               0.0, 0.0, 0.0,
+       };
+       float expected_data[size * size] = {
+               0.1, 0.1, 1.1, 2.1,
+               0.2, 0.2, 1.2, 2.2,
+               0.3, 0.3, 1.3, 2.3,
+               0.4, 0.4, 1.4, 2.4,
+       };
+       float out_data[size * size];
+
+       EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+       FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
+       tester.get_chain()->add_effect(fft_effect);
+       fft_effect->set_convolution_kernel(kernel);
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+       expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
+}
+
+TEST(FFTConvolutionEffectTest, MoveDown) {
+       const int size = 4, convolve_size = 3;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float kernel[convolve_size * convolve_size] = {
+               0.0, 0.0, 0.0,
+               1.0, 0.0, 0.0,
+               0.0, 0.0, 0.0,
+       };
+       float expected_data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+       };
+       float out_data[size * size];
+
+       EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+       FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
+       tester.get_chain()->add_effect(fft_effect);
+       fft_effect->set_convolution_kernel(kernel);
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+       expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
+}
+
+TEST(FFTConvolutionEffectTest, MergeWithLeft) {
+       const int size = 4, convolve_size = 3;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float kernel[convolve_size * convolve_size] = {
+               1.0, 1.0, 0.0,
+               0.0, 0.0, 0.0,
+               0.0, 0.0, 0.0,
+       };
+       float expected_data[size * size] = {
+               0.1 + 0.1,  0.1 + 1.1,  1.1 + 2.1,  2.1 + 3.1,
+               0.2 + 0.2,  0.2 + 1.2,  1.2 + 2.2,  2.2 + 3.2,
+               0.3 + 0.3,  0.3 + 1.3,  1.3 + 2.3,  2.3 + 3.3,
+               0.4 + 0.4,  0.4 + 1.4,  1.4 + 2.4,  2.4 + 3.4,
+       };
+       float out_data[size * size];
+
+       EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+       FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
+       tester.get_chain()->add_effect(fft_effect);
+       fft_effect->set_convolution_kernel(kernel);
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+       expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
+}
+
+TEST(FFTConvolutionEffectTest, NegativeCoefficients) {
+       const int size = 4;
+       const int convolve_width = 3, convolve_height = 2;
+
+       float data[size * size] = {
+               0.1, 1.1, 2.1, 3.1,
+               0.2, 1.2, 2.2, 3.2,
+               0.3, 1.3, 2.3, 3.3,
+               0.4, 1.4, 2.4, 3.4,
+       };
+       float kernel[convolve_width * convolve_height] = {
+               1.0, 0.0,  0.0,
+               0.0, 0.0, -0.5,
+       };
+       float expected_data[size * size] = {
+               0.1 - 0.5 * 0.1,  1.1 - 0.5 * 0.1,  2.1 - 0.5 * 0.1,  3.1 - 0.5 * 1.1,
+               0.2 - 0.5 * 0.1,  1.2 - 0.5 * 0.1,  2.2 - 0.5 * 0.1,  3.2 - 0.5 * 1.1,
+               0.3 - 0.5 * 0.2,  1.3 - 0.5 * 0.2,  2.3 - 0.5 * 0.2,  3.3 - 0.5 * 1.2,
+               0.4 - 0.5 * 0.3,  1.4 - 0.5 * 0.3,  2.4 - 0.5 * 0.3,  3.4 - 0.5 * 1.3,
+       };
+       float out_data[size * size];
+
+       EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+       tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
+
+       FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_width, convolve_height);
+       tester.get_chain()->add_effect(fft_effect);
+       fft_effect->set_convolution_kernel(kernel);
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
+
+       expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
+}
+
+}  // namespace movit