1 // Unit tests for ResampleEffect.
6 #include "effect_chain.h"
7 #include "flat_input.h"
8 #include "gtest/gtest.h"
9 #include "image_format.h"
10 #include "resample_effect.h"
11 #include "test_util.h"
17 return sin(M_PI * x) / (M_PI * x);
20 float lanczos(float x, float a)
25 return sinc(x) * sinc(x / a);
31 TEST(ResampleEffectTest, IdentityTransformDoesNothing) {
34 float data[size * size] = {
40 float out_data[size * size];
42 EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
43 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
44 ASSERT_TRUE(resample_effect->set_int("width", 4));
45 ASSERT_TRUE(resample_effect->set_int("height", 4));
46 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
48 expect_equal(data, out_data, size, size);
51 TEST(ResampleEffectTest, UpscaleByTwoGetsCorrectPixelCenters) {
54 float data[size * size] = {
55 0.0, 0.0, 0.0, 0.0, 0.0,
56 0.0, 0.0, 0.0, 0.0, 0.0,
57 0.0, 0.0, 1.0, 0.0, 0.0,
58 0.0, 0.0, 0.0, 0.0, 0.0,
59 0.0, 0.0, 0.0, 0.0, 0.0,
61 float expected_data[size * size * 4], out_data[size * size * 4];
63 for (int y = 0; y < size * 2; ++y) {
64 for (int x = 0; x < size * 2; ++x) {
65 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
66 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
67 expected_data[y * (size * 2) + x] = weight;
71 EffectChainTester tester(NULL, size * 2, size * 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
74 format.color_space = COLORSPACE_sRGB;
75 format.gamma_curve = GAMMA_LINEAR;
77 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
78 input->set_pixel_data(data);
79 tester.get_chain()->add_input(input);
81 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
82 ASSERT_TRUE(resample_effect->set_int("width", size * 2));
83 ASSERT_TRUE(resample_effect->set_int("height", size * 2));
84 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
86 expect_equal(expected_data, out_data, size * 2, size * 2);
89 TEST(ResampleEffectTest, DownscaleByTwoGetsCorrectPixelCenters) {
92 // This isn't a perfect dot, since the Lanczos filter has a slight
93 // sharpening effect; the most important thing is that we have kept
94 // the texel center right (everything is nicely symmetric).
95 // The approximate magnitudes have been checked against ImageMagick.
96 float expected_data[size * size] = {
97 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
98 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
99 -0.0598, 0.0886, 0.7930, 0.0886, -0.0598,
100 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
101 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
103 float data[size * size * 4], out_data[size * size];
105 for (int y = 0; y < size * 2; ++y) {
106 for (int x = 0; x < size * 2; ++x) {
107 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
108 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
109 data[y * (size * 2) + x] = weight;
113 EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
116 format.color_space = COLORSPACE_sRGB;
117 format.gamma_curve = GAMMA_LINEAR;
119 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size * 2, size * 2);
120 input->set_pixel_data(data);
121 tester.get_chain()->add_input(input);
123 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
124 ASSERT_TRUE(resample_effect->set_int("width", size));
125 ASSERT_TRUE(resample_effect->set_int("height", size));
126 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
128 expect_equal(expected_data, out_data, size, size);
131 TEST(ResampleEffectTest, UpscaleByThreeGetsCorrectPixelCenters) {
134 float data[size * size] = {
135 0.0, 0.0, 0.0, 0.0, 0.0,
136 0.0, 0.0, 0.0, 0.0, 0.0,
137 0.0, 0.0, 1.0, 0.0, 0.0,
138 0.0, 0.0, 0.0, 0.0, 0.0,
139 0.0, 0.0, 0.0, 0.0, 0.0,
141 float out_data[size * size * 9];
143 EffectChainTester tester(NULL, size * 3, size * 3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
146 format.color_space = COLORSPACE_sRGB;
147 format.gamma_curve = GAMMA_LINEAR;
149 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
150 input->set_pixel_data(data);
151 tester.get_chain()->add_input(input);
153 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
154 ASSERT_TRUE(resample_effect->set_int("width", size * 3));
155 ASSERT_TRUE(resample_effect->set_int("height", size * 3));
156 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
158 // We only bother checking that the middle pixel is still correct,
159 // and that symmetry holds.
160 EXPECT_FLOAT_EQ(1.0, out_data[7 * (size * 3) + 7]);
161 for (unsigned y = 0; y < size * 3; ++y) {
162 for (unsigned x = 0; x < size * 3; ++x) {
163 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[(size * 3 - y - 1) * (size * 3) + x]);
164 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[y * (size * 3) + (size * 3 - x - 1)]);