1 // Unit tests for ResampleEffect.
6 #include "effect_chain.h"
7 #include "flat_input.h"
9 #include "gtest/gtest.h"
10 #include "image_format.h"
11 #include "resample_effect.h"
12 #include "test_util.h"
18 return sin(M_PI * x) / (M_PI * x);
21 float lanczos(float x, float a)
26 return sinc(x) * sinc(x / a);
32 TEST(ResampleEffectTest, IdentityTransformDoesNothing) {
35 float data[size * size] = {
41 float out_data[size * size];
43 EffectChainTester tester(data, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
44 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
45 ASSERT_TRUE(resample_effect->set_int("width", 4));
46 ASSERT_TRUE(resample_effect->set_int("height", 4));
47 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
49 expect_equal(data, out_data, size, size);
52 TEST(ResampleEffectTest, UpscaleByTwoGetsCorrectPixelCenters) {
55 float data[size * size] = {
56 0.0, 0.0, 0.0, 0.0, 0.0,
57 0.0, 0.0, 0.0, 0.0, 0.0,
58 0.0, 0.0, 1.0, 0.0, 0.0,
59 0.0, 0.0, 0.0, 0.0, 0.0,
60 0.0, 0.0, 0.0, 0.0, 0.0,
62 float expected_data[size * size * 4], out_data[size * size * 4];
64 for (int y = 0; y < size * 2; ++y) {
65 for (int x = 0; x < size * 2; ++x) {
66 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
67 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
68 expected_data[y * (size * 2) + x] = weight;
72 EffectChainTester tester(NULL, size * 2, size * 2, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
75 format.color_space = COLORSPACE_sRGB;
76 format.gamma_curve = GAMMA_LINEAR;
78 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
79 input->set_pixel_data(data);
80 tester.get_chain()->add_input(input);
82 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
83 ASSERT_TRUE(resample_effect->set_int("width", size * 2));
84 ASSERT_TRUE(resample_effect->set_int("height", size * 2));
85 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
87 expect_equal(expected_data, out_data, size * 2, size * 2);
90 TEST(ResampleEffectTest, DownscaleByTwoGetsCorrectPixelCenters) {
93 // This isn't a perfect dot, since the Lanczos filter has a slight
94 // sharpening effect; the most important thing is that we have kept
95 // the texel center right (everything is nicely symmetric).
96 // The approximate magnitudes have been checked against ImageMagick.
97 float expected_data[size * size] = {
98 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
99 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
100 -0.0598, 0.0886, 0.7930, 0.0886, -0.0598,
101 -0.0067, 0.0099, 0.0886, 0.0099, -0.0067,
102 0.0045, -0.0067, -0.0598, -0.0067, 0.0045,
104 float data[size * size * 4], out_data[size * size];
106 for (int y = 0; y < size * 2; ++y) {
107 for (int x = 0; x < size * 2; ++x) {
108 float weight = lanczos((x - size + 0.5f) * 0.5f, 3.0f);
109 weight *= lanczos((y - size + 0.5f) * 0.5f, 3.0f);
110 data[y * (size * 2) + x] = weight;
114 EffectChainTester tester(NULL, size, size, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
117 format.color_space = COLORSPACE_sRGB;
118 format.gamma_curve = GAMMA_LINEAR;
120 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size * 2, size * 2);
121 input->set_pixel_data(data);
122 tester.get_chain()->add_input(input);
124 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
125 ASSERT_TRUE(resample_effect->set_int("width", size));
126 ASSERT_TRUE(resample_effect->set_int("height", size));
127 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
129 expect_equal(expected_data, out_data, size, size);
132 TEST(ResampleEffectTest, UpscaleByThreeGetsCorrectPixelCenters) {
135 float data[size * size] = {
136 0.0, 0.0, 0.0, 0.0, 0.0,
137 0.0, 0.0, 0.0, 0.0, 0.0,
138 0.0, 0.0, 1.0, 0.0, 0.0,
139 0.0, 0.0, 0.0, 0.0, 0.0,
140 0.0, 0.0, 0.0, 0.0, 0.0,
142 float out_data[size * size * 9];
144 EffectChainTester tester(NULL, size * 3, size * 3, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
147 format.color_space = COLORSPACE_sRGB;
148 format.gamma_curve = GAMMA_LINEAR;
150 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, size, size);
151 input->set_pixel_data(data);
152 tester.get_chain()->add_input(input);
154 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
155 ASSERT_TRUE(resample_effect->set_int("width", size * 3));
156 ASSERT_TRUE(resample_effect->set_int("height", size * 3));
157 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
159 // We only bother checking that the middle pixel is still correct,
160 // and that symmetry holds.
161 EXPECT_FLOAT_EQ(1.0, out_data[7 * (size * 3) + 7]);
162 for (unsigned y = 0; y < size * 3; ++y) {
163 for (unsigned x = 0; x < size * 3; ++x) {
164 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[(size * 3 - y - 1) * (size * 3) + x]);
165 EXPECT_FLOAT_EQ(out_data[y * (size * 3) + x], out_data[y * (size * 3) + (size * 3 - x - 1)]);