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)]);
170 TEST(ResampleEffectTest, HeavyResampleGetsSumRight) {
171 const int swidth = 1280, sheight = 720;
172 const int dwidth = 36, dheight = 20;
174 float data[swidth * sheight], out_data[dwidth * dheight], expected_data[dwidth * dheight];
175 for (int y = 0; y < sheight; ++y) {
176 for (int x = 0; x < swidth; ++x) {
177 data[y * swidth + x] = 0.5f;
180 for (int y = 0; y < dheight; ++y) {
181 for (int x = 0; x < dwidth; ++x) {
182 expected_data[y * dwidth + x] = 0.5f;
186 EffectChainTester tester(NULL, dwidth, dheight, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
189 format.color_space = COLORSPACE_sRGB;
190 format.gamma_curve = GAMMA_LINEAR;
192 FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, swidth, sheight);
193 input->set_pixel_data(data);
195 tester.get_chain()->add_input(input);
196 Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
197 ASSERT_TRUE(resample_effect->set_int("width", dwidth));
198 ASSERT_TRUE(resample_effect->set_int("height", dheight));
199 tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
201 expect_equal(expected_data, out_data, dwidth, dheight, 0.001);