Reduce the amount of arithmetic in the BlurEffect shader a bit.
[movit] / fft_convolution_effect_test.cpp
1 // Unit tests for FFTConvolutionEffect.
2
3 #include <GL/glew.h>
4 #include <math.h>
5
6 #include "effect_chain.h"
7 #include "gtest/gtest.h"
8 #include "image_format.h"
9 #include "test_util.h"
10 #include "fft_convolution_effect.h"
11
12 namespace movit {
13
14 TEST(FFTConvolutionEffectTest, Identity) {
15         const int size = 4;
16
17         float data[size * size] = {
18                 0.1, 1.1, 2.1, 3.1,
19                 0.2, 1.2, 2.2, 3.2,
20                 0.3, 1.3, 2.3, 3.3,
21                 0.4, 1.4, 2.4, 3.4,
22         };
23         float out_data[size * size];
24
25         for (int convolve_size = 1; convolve_size < 10; ++convolve_size) {
26                 float kernel[convolve_size * convolve_size];
27                 for (int i = 0; i < convolve_size * convolve_size; ++i) {
28                         kernel[i] = 0.0f;
29                 }
30                 kernel[0] = 1.0f;
31
32                 EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
33                 tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
34
35                 FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
36                 tester.get_chain()->add_effect(fft_effect);
37                 fft_effect->set_convolution_kernel(kernel);
38                 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
39
40                 expect_equal(data, out_data, size, size, 0.02, 0.003);
41         }
42 }
43
44 TEST(FFTConvolutionEffectTest, Constant) {
45         const int size = 4, convolve_size = 17;
46         const float f = 7.0f;
47
48         float data[size * size] = {
49                 0.1, 1.1, 2.1, 3.1,
50                 0.2, 1.2, 2.2, 3.2,
51                 0.3, 1.3, 2.3, 3.3,
52                 0.4, 1.4, 2.4, 3.4,
53         };
54         float expected_data[size * size] = {
55                 f * 0.1, f * 1.1, f * 2.1, f * 3.1,
56                 f * 0.2, f * 1.2, f * 2.2, f * 3.2,
57                 f * 0.3, f * 1.3, f * 2.3, f * 3.3,
58                 f * 0.4, f * 1.4, f * 2.4, f * 3.4,
59         };
60         float out_data[size * size];
61         float kernel[convolve_size * convolve_size];
62         for (int i = 0; i < convolve_size * convolve_size; ++i) {
63                 kernel[i] = 0.0f;
64         }
65         kernel[0] = f;
66
67         EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
68         tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
69
70         FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
71         tester.get_chain()->add_effect(fft_effect);
72         fft_effect->set_convolution_kernel(kernel);
73         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
74
75         // Somewhat looser bounds due to the higher magnitude.
76         expect_equal(expected_data, out_data, size, size, f * 0.03, f * 0.004);
77 }
78
79 TEST(FFTConvolutionEffectTest, MoveRight) {
80         const int size = 4, convolve_size = 3;
81
82         float data[size * size] = {
83                 0.1, 1.1, 2.1, 3.1,
84                 0.2, 1.2, 2.2, 3.2,
85                 0.3, 1.3, 2.3, 3.3,
86                 0.4, 1.4, 2.4, 3.4,
87         };
88         float kernel[convolve_size * convolve_size] = {
89                 0.0, 1.0, 0.0,
90                 0.0, 0.0, 0.0,
91                 0.0, 0.0, 0.0,
92         };
93         float expected_data[size * size] = {
94                 0.1, 0.1, 1.1, 2.1,
95                 0.2, 0.2, 1.2, 2.2,
96                 0.3, 0.3, 1.3, 2.3,
97                 0.4, 0.4, 1.4, 2.4,
98         };
99         float out_data[size * size];
100
101         EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
102         tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
103
104         FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
105         tester.get_chain()->add_effect(fft_effect);
106         fft_effect->set_convolution_kernel(kernel);
107         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
108
109         expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
110 }
111
112 TEST(FFTConvolutionEffectTest, MoveDown) {
113         const int size = 4, convolve_size = 3;
114
115         float data[size * size] = {
116                 0.1, 1.1, 2.1, 3.1,
117                 0.2, 1.2, 2.2, 3.2,
118                 0.3, 1.3, 2.3, 3.3,
119                 0.4, 1.4, 2.4, 3.4,
120         };
121         float kernel[convolve_size * convolve_size] = {
122                 0.0, 0.0, 0.0,
123                 1.0, 0.0, 0.0,
124                 0.0, 0.0, 0.0,
125         };
126         float expected_data[size * size] = {
127                 0.1, 1.1, 2.1, 3.1,
128                 0.1, 1.1, 2.1, 3.1,
129                 0.2, 1.2, 2.2, 3.2,
130                 0.3, 1.3, 2.3, 3.3,
131         };
132         float out_data[size * size];
133
134         EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
135         tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
136
137         FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
138         tester.get_chain()->add_effect(fft_effect);
139         fft_effect->set_convolution_kernel(kernel);
140         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
141
142         expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
143 }
144
145 TEST(FFTConvolutionEffectTest, MergeWithLeft) {
146         const int size = 4, convolve_size = 3;
147
148         float data[size * size] = {
149                 0.1, 1.1, 2.1, 3.1,
150                 0.2, 1.2, 2.2, 3.2,
151                 0.3, 1.3, 2.3, 3.3,
152                 0.4, 1.4, 2.4, 3.4,
153         };
154         float kernel[convolve_size * convolve_size] = {
155                 1.0, 1.0, 0.0,
156                 0.0, 0.0, 0.0,
157                 0.0, 0.0, 0.0,
158         };
159         float expected_data[size * size] = {
160                 0.1 + 0.1,  0.1 + 1.1,  1.1 + 2.1,  2.1 + 3.1,
161                 0.2 + 0.2,  0.2 + 1.2,  1.2 + 2.2,  2.2 + 3.2,
162                 0.3 + 0.3,  0.3 + 1.3,  1.3 + 2.3,  2.3 + 3.3,
163                 0.4 + 0.4,  0.4 + 1.4,  1.4 + 2.4,  2.4 + 3.4,
164         };
165         float out_data[size * size];
166
167         EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
168         tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
169
170         FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_size, convolve_size);
171         tester.get_chain()->add_effect(fft_effect);
172         fft_effect->set_convolution_kernel(kernel);
173         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
174
175         expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
176 }
177
178 TEST(FFTConvolutionEffectTest, NegativeCoefficients) {
179         const int size = 4;
180         const int convolve_width = 3, convolve_height = 2;
181
182         float data[size * size] = {
183                 0.1, 1.1, 2.1, 3.1,
184                 0.2, 1.2, 2.2, 3.2,
185                 0.3, 1.3, 2.3, 3.3,
186                 0.4, 1.4, 2.4, 3.4,
187         };
188         float kernel[convolve_width * convolve_height] = {
189                 1.0, 0.0,  0.0,
190                 0.0, 0.0, -0.5,
191         };
192         float expected_data[size * size] = {
193                 0.1 - 0.5 * 0.1,  1.1 - 0.5 * 0.1,  2.1 - 0.5 * 0.1,  3.1 - 0.5 * 1.1,
194                 0.2 - 0.5 * 0.1,  1.2 - 0.5 * 0.1,  2.2 - 0.5 * 0.1,  3.2 - 0.5 * 1.1,
195                 0.3 - 0.5 * 0.2,  1.3 - 0.5 * 0.2,  2.3 - 0.5 * 0.2,  3.3 - 0.5 * 1.2,
196                 0.4 - 0.5 * 0.3,  1.4 - 0.5 * 0.3,  2.4 - 0.5 * 0.3,  3.4 - 0.5 * 1.3,
197         };
198         float out_data[size * size];
199
200         EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
201         tester.add_input(data, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR, size, size);
202
203         FFTConvolutionEffect *fft_effect = new FFTConvolutionEffect(size, size, convolve_width, convolve_height);
204         tester.get_chain()->add_effect(fft_effect);
205         fft_effect->set_convolution_kernel(kernel);
206         tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR, OUTPUT_ALPHA_FORMAT_PREMULTIPLIED);
207
208         expect_equal(expected_data, out_data, size, size, 0.02, 0.003);
209 }
210
211 }  // namespace movit