Bug 1421191. In ConvolutionFilter::ComputeResizeFilter calculate the src pixel every loop iteration. r=lsalzman

If we try to be clever and increment by invScale then floating point inaccuracies can accumulate leaving srcPixel far off from where it should be.
This commit is contained in:
Timothy Nikkel 2017-11-29 02:22:53 -06:00
parent 9d60eea296
commit 9468c9b03a
4 changed files with 31 additions and 9 deletions

View File

@ -113,15 +113,16 @@ ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod, int32_t aSrcS
// filter values for each one. Those values will tell us how to blend the
// source pixels to compute the destination pixel.
// This is the pixel in the source directly under the pixel in the dest.
// Note that we base computations on the "center" of the pixels. To see
// why, observe that the destination pixel at coordinates (0, 0) in a 5.0x
// downscale should "cover" the pixels around the pixel with *its center*
// at coordinates (2.5, 2.5) in the source, not those around (0, 0).
// Hence we need to scale coordinates (0.5, 0.5), not (0, 0).
float srcPixel = 0.5f * invScale;
mFilter->reserveAdditional(aDstSize, int32_t(ceil(aDstSize * srcSupport * 2)));
for (int32_t destI = 0; destI < aDstSize; destI++) {
// This is the pixel in the source directly under the pixel in the dest.
// Note that we base computations on the "center" of the pixels. To see
// why, observe that the destination pixel at coordinates (0, 0) in a 5.0x
// downscale should "cover" the pixels around the pixel with *its center*
// at coordinates (2.5, 2.5) in the source, not those around (0, 0).
// Hence we need to scale coordinates (0.5, 0.5), not (0, 0).
float srcPixel = (static_cast<float>(destI) + 0.5f) * invScale;
// Compute the (inclusive) range of source pixels the filter covers.
float srcBegin = std::max(0.0f, floorf(srcPixel - srcSupport));
float srcEnd = std::min(aSrcSize - 1.0f, ceilf(srcPixel + srcSupport));
@ -165,8 +166,6 @@ ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod, int32_t aSrcS
fixedFilterValues[filterCount / 2] += leftovers;
mFilter->AddFilter(int32_t(srcBegin), fixedFilterValues.begin(), filterCount);
srcPixel += invScale;
}
return mFilter->maxFilter() > 0 && mFilter->numValues() == aDstSize;

View File

@ -0,0 +1,20 @@
<html reftest-zoom="1.6">
<head>
<style>
#xx {
background-image: url("1421191-1.png");
background-position: -61px -797px;
background-position-x: -61px;
background-position-y: -797px;
background-repeat: no-repeat;
background-size: 82px auto;
display: block;
height: 24px;
width: 22px;
}
</style>
</head>
<body>
<span id="xx"></span>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -205,3 +205,6 @@ fuzzy(18,128) == downscale-32px.html?-png-in.ico downscale-32px-ref.html
== huge-1.html?100x32768.jpg,100,32768 huge-1.html?100x100.jpg,100,32768
== huge-1.html?32768x100.jpg,100,100 huge-1.html?100x100.jpg,100,100
== huge-1.html?32768x100.jpg,32768,100 huge-1.html?100x100.jpg,32768,100
# Only need to run this with downscaling on
!= 1421191-1.html about:blank