From: Steinar H. Gunderson Date: Sat, 25 Jan 2014 11:42:56 +0000 (+0100) Subject: Rescale resampling weights so that the sum becomes one. X-Git-Tag: 1.0~55 X-Git-Url: https://git.sesse.net/?p=movit;a=commitdiff_plain;h=aa3e630eb0c455921c721f9ccd84e872bc9757bc Rescale resampling weights so that the sum becomes one. For some reason, I had forgotten this, and it showed up because Qt has buggy handling of pixels with alpha != 0xff. Add unit test so it doesn't happen again. I'm a bit concerned that rounding might cause problems so that we should perhaps renormalize after the bilinear conversion, but we can deal with that later if it should show up. --- diff --git a/resample_effect.cpp b/resample_effect.cpp index 6c490f1..10dc59c 100644 --- a/resample_effect.cpp +++ b/resample_effect.cpp @@ -299,11 +299,18 @@ void SingleResamplePassEffect::update_texture(GLuint glsl_program_num, const str int base_src_y = lrintf(center_src_y); // Now sample pixels on each side around that point. + double sum = 0.0; 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); 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); + sum += weights[(y * src_samples + i) * 2 + 0]; + } + + // Normalize so that the sum becomes one. + for (int i = 0; i < src_samples; ++i) { + weights[(y * src_samples + i) * 2 + 0] /= sum; } } diff --git a/resample_effect_test.cpp b/resample_effect_test.cpp index 9525536..e4c23b1 100644 --- a/resample_effect_test.cpp +++ b/resample_effect_test.cpp @@ -166,3 +166,38 @@ TEST(ResampleEffectTest, UpscaleByThreeGetsCorrectPixelCenters) { } } } + +TEST(ResampleEffectTest, HeavyResampleGetsSumRight) { + const int swidth = 1280, sheight = 720; + const int dwidth = 36, dheight = 20; + + float data[swidth * sheight], out_data[dwidth * dheight], expected_data[dwidth * dheight]; + for (int y = 0; y < sheight; ++y) { + for (int x = 0; x < swidth; ++x) { + data[y * swidth + x] = 0.5f; + } + } + for (int y = 0; y < dheight; ++y) { + for (int x = 0; x < dwidth; ++x) { + expected_data[y * dwidth + x] = 0.5f; + } + } + + EffectChainTester tester(NULL, dwidth, dheight, 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, swidth, sheight); + 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", dwidth)); + ASSERT_TRUE(resample_effect->set_int("height", dheight)); + tester.run(out_data, GL_RED, COLORSPACE_sRGB, GAMMA_LINEAR); + + expect_equal(expected_data, out_data, dwidth, dheight, 0.001); +} +