1 // Unit tests for ResampleEffect.
4 #include "gtest/gtest.h"
5 #include "resample_effect.h"
6 #include "flat_input.h"
12 return sin(M_PI * x) / (M_PI * x);
15 float lanczos(float x, float a)
20 return sinc(x) * sinc(x / a);
26 TEST(ResampleEffectTest, IdentityTransformDoesNothing) {
29 float data[size * size] = {
35 float out_data[size * size];
37 EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
38 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
39 ASSERT_TRUE(resample_effect->set_int("width", 4));
40 ASSERT_TRUE(resample_effect->set_int("height", 4));
41 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
43 expect_equal(data, out_data, size, size);
46 TEST(ResampleEffectTest, UpscaleByTwoGetsCorrectPixelCenters) {
49 float data[size * size] = {
50 0.0, 0.0, 0.0, 0.0, 0.0,
51 0.0, 0.0, 0.0, 0.0, 0.0,
52 0.0, 0.0, 1.0, 0.0, 0.0,
53 0.0, 0.0, 0.0, 0.0, 0.0,
54 0.0, 0.0, 0.0, 0.0, 0.0,
56 float expected_data[size * size * 4], out_data[size * size * 4];
58 for (int y = 0; y < size * 2; ++y) {
59 for (int x = 0; x < size * 2; ++x) {
60 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
61 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
62 expected_data[y * (size * 2) + x] = weight;
66 EffectChainTester tester(NULL, size * 2, size * 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
69 format.color_space = COLORSPACE_sRGB;
70 format.gamma_curve = GAMMA_LINEAR;
72 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
73 input->set_pixel_data(data);
74 tester.get_chain()->add_input(input);
76 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
77 ASSERT_TRUE(resample_effect->set_int("width", size * 2));
78 ASSERT_TRUE(resample_effect->set_int("height", size * 2));
79 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
81 expect_equal(expected_data, out_data, size * 2, size * 2);
84 TEST(ResampleEffectTest, DownscaleByTwoGetsCorrectPixelCenters) {
87 // This isn't a perfect dot, since the Lanczos filter has a slight
88 // sharpening effect; the most important thing is that we have kept
89 // the texel center right (everything is nicely symmetric).
90 // The approximate magnitudes have been checked against ImageMagick.
91 float expected_data[size * size] = {
92 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
93 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
94 -0.0598, 0.0886, 0.7930, 0.0886, -0.0598,
95 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
96 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
98 float data[size * size * 4], out_data[size * size];
100 for (int y = 0; y < size * 2; ++y) {
101 for (int x = 0; x < size * 2; ++x) {
102 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
103 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
104 data[y * (size * 2) + x] = weight;
108 EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
111 format.color_space = COLORSPACE_sRGB;
112 format.gamma_curve = GAMMA_LINEAR;
114 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size * 2, size * 2);
115 input->set_pixel_data(data);
116 tester.get_chain()->add_input(input);
118 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
119 ASSERT_TRUE(resample_effect->set_int("width", size));
120 ASSERT_TRUE(resample_effect->set_int("height", size));
121 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
123 expect_equal(expected_data, out_data, size, size);
126 TEST(ResampleEffectTest, UpscaleByThreeGetsCorrectPixelCenters) {
129 float data[size * size] = {
130 0.0, 0.0, 0.0, 0.0, 0.0,
131 0.0, 0.0, 0.0, 0.0, 0.0,
132 0.0, 0.0, 1.0, 0.0, 0.0,
133 0.0, 0.0, 0.0, 0.0, 0.0,
134 0.0, 0.0, 0.0, 0.0, 0.0,
136 float out_data[size * size * 9];
138 EffectChainTester tester(NULL, size * 3, size * 3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
141 format.color_space = COLORSPACE_sRGB;
142 format.gamma_curve = GAMMA_LINEAR;
144 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
145 input->set_pixel_data(data);
146 tester.get_chain()->add_input(input);
148 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
149 ASSERT_TRUE(resample_effect->set_int("width", size * 3));
150 ASSERT_TRUE(resample_effect->set_int("height", size * 3));
151 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
153 // We only bother checking that the middle pixel is still correct,
154 // and that symmetry holds.
155 EXPECT_FLOAT_EQ(1.0, out_data[7 * (size * 3) + 7]);
156 for (unsigned y = 0; y < size * 3; ++y) {
157 for (unsigned x = 0; x < size * 3; ++x) {
158 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[(size * 3 - y - 1) * (size * 3) + x]);
159 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[y * (size * 3) + (size * 3 - x - 1)]);