Fix a bug when scaling and doing offset at the same time. (At least one more remains.)
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 30 Mar 2014 17:12:22 +0000 (19:12 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 30 Mar 2014 17:12:22 +0000 (19:12 +0200)
resample_effect.cpp
resample_effect_test.cpp

index 17745bc..2a6aecf 100644 (file)
@@ -309,13 +309,13 @@ void SingleResamplePassEffect::update_texture(GLuint glsl_program_num, const str
        for (unsigned y = 0; y < dst_samples; ++y) {
                // Find the point around which we want to sample the source image,
                // compensating for differing pixel centers as the scale changes.
-               float center_src_y = (y + subpixel_offset + 0.5f) * float(src_size) / float(dst_size) - 0.5f;
+               float center_src_y = (y + 0.5f) * float(src_size) / float(dst_size) - 0.5f;
                int base_src_y = lrintf(center_src_y);
 
                // Now sample <int_radius> pixels on each side around that point.
                for (int i = 0; i < src_samples; ++i) {
                        int src_y = base_src_y + i - int_radius;
-                       float weight = lanczos_weight(radius_scaling_factor * (src_y - center_src_y), LANCZOS_RADIUS);
+                       float weight = lanczos_weight(radius_scaling_factor * (src_y - center_src_y - subpixel_offset), LANCZOS_RADIUS);
                        weights[(y * src_samples + i) * 2 + 0] = weight * radius_scaling_factor;
                        weights[(y * src_samples + i) * 2 + 1] = (src_y + 0.5) / float(src_size);
                }
index e4b9439..dbb213a 100644 (file)
@@ -304,4 +304,41 @@ TEST(ResampleEffectTest, ReadQuarterPixelFromTop) {
        expect_equal(expected_data, out_data, width, height);
 }
 
+TEST(ResampleEffectTest, ReadHalfPixelFromLeftAndScale) {
+       const int src_width = 4;
+       const int dst_width = 8;
+
+       float data[src_width * 1] = {
+               1.0, 2.0, 3.0, 4.0,
+       };
+       float expected_data[dst_width * 1] = {
+               // Empirical; the real test is that we are the same for 0.499 and 0.501.
+               1.1553, 1.7158, 2.2500, 2.7461, 3.2812, 3.8418, 4.0703, 4.0508
+       };
+       float out_data[dst_width * 1];
+
+       EffectChainTester tester(NULL, dst_width, 1, FORMAT_GRAYSCALE, COLORSPACE_sRGB, GAMMA_LINEAR);
+
+       ImageFormat format;
+       format.color_space = COLORSPACE_sRGB;
+       format.gamma_curve = GAMMA_LINEAR;
+
+       FlatInput *input = new FlatInput(format, FORMAT_GRAYSCALE, GL_FLOAT, src_width, 1);
+       input->set_pixel_data(data);
+       tester.get_chain()->add_input(input);
+
+       Effect *resample_effect = tester.get_chain()->add_effect(new ResampleEffect());
+       ASSERT_TRUE(resample_effect->set_int("width", dst_width));
+       ASSERT_TRUE(resample_effect->set_int("height", 1));
+
+       // Check that we are (almost) the same no matter the rounding.
+       ASSERT_TRUE(resample_effect->set_float("left", 0.499f));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, dst_width, 1);
+
+       ASSERT_TRUE(resample_effect->set_float("left", 0.501f));
+       tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR);
+       expect_equal(expected_data, out_data, dst_width, 1);
+}
+
 }  // namespace movit