Limit sigma for software blurs

The value (window + 1)^3 * 255 < 2^32.
window = floor(sigma * 3 * sqrt(2 * kPi) / 4)
So, max sigma = 135.

Bug: skia:9454
Change-Id: I1df5137013da3e80d1e8af9ed6ac2b688ef95e7d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243430
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Herb Derby 2019-09-23 16:46:09 -04:00 committed by Skia Commit-Bot
parent 867ab81687
commit f07a363413
3 changed files with 40 additions and 12 deletions

View File

@ -18,6 +18,7 @@
#include "include/core/SkScalar.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/effects/SkBlurImageFilter.h"
#include "src/core/SkBlurMask.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"
@ -129,3 +130,11 @@ DEF_SIMPLE_GM(BlurDrawImage, canvas, 256, 256) {
canvas->drawImage(image, 256, 256, &paint);
}
}
DEF_SIMPLE_GM(BlurBigSigma, canvas, 1024, 1024) {
SkPaint layerPaint, p;
p.setImageFilter(SkBlurImageFilter::Make(0, 500, nullptr));
canvas->drawRect(SkRect::MakeWH(700, 800), p);
}

View File

@ -236,21 +236,23 @@ public:
} // namespace
// NB 136 is the largest sigma that will not cause a buffer full of 255 mask values to overflow
// using the Gauss filter. It also limits the size of buffers used hold intermediate values.
// NB 135 is the largest sigma that will not cause a buffer full of 255 mask values to overflow
// using the Gauss filter. It also limits the size of buffers used hold intermediate values. The
// additional + 1 added to window represents adding one more leading element before subtracting the
// trailing element.
// Explanation of maximums:
// sum0 = window * 255
// sum1 = window * sum0 -> window * window * 255
// sum2 = window * sum1 -> window * window * window * 255 -> window^3 * 255
// sum0 = (window + 1) * 255
// sum1 = (window + 1) * sum0 -> (window + 1) * (window + 1) * 255
// sum2 = (window + 1) * sum1 -> (window + 1) * (window + 1) * (window + 1) * 255 -> window^3 * 255
//
// The value window^3 * 255 must fit in a uint32_t. So,
// window^3 < 2^32. window = 255.
// The value (window + 1)^3 * 255 must fit in a uint32_t. So,
// (window + 1)^3 * 255 < 2^32. window = 255.
//
// window = floor(sigma * 3 * sqrt(2 * kPi) / 4 + 0.5)
// For window <= 255, the largest value for sigma is 136.
// window = floor(sigma * 3 * sqrt(2 * kPi) / 4)
// For window <= 255, the largest value for sigma is 135.
SkMaskBlurFilter::SkMaskBlurFilter(double sigmaW, double sigmaH)
: fSigmaW{SkTPin(sigmaW, 0.0, 136.0)}
, fSigmaH{SkTPin(sigmaH, 0.0, 136.0)}
: fSigmaW{SkTPin(sigmaW, 0.0, 135.0)}
, fSigmaH{SkTPin(sigmaH, 0.0, 135.0)}
{
SkASSERT(sigmaW >= 0);
SkASSERT(sigmaH >= 0);

View File

@ -605,7 +605,7 @@ sk_sp<SkSpecialImage> SkBlurImageFilterImpl::onFilterImage(const Context& ctx,
inputBounds.offset(-inputOffset);
dstBounds.offset(-inputOffset);
const SkVector sigma = map_sigma(fSigma, ctx.ctm());
SkVector sigma = map_sigma(fSigma, ctx.ctm());
if (sigma.x() < 0 || sigma.y() < 0) {
return nullptr;
}
@ -621,6 +621,23 @@ sk_sp<SkSpecialImage> SkBlurImageFilterImpl::onFilterImage(const Context& ctx,
} else
#endif
{
// NB 135 is the largest sigma that will not cause a buffer full of 255 mask values to overflow
// using the Gauss filter. It also limits the size of buffers used hold intermediate values. The
// additional + 1 added to window represents adding one more leading element before subtracting the
// trailing element.
// Explanation of maximums:
// sum0 = (window + 1) * 255
// sum1 = (window + 1) * sum0 -> (window + 1) * (window + 1) * 255
// sum2 = (window + 1) * sum1 -> (window + 1) * (window + 1) * (window + 1) * 255 -> window^3 * 255
//
// The value (window + 1)^3 * 255 must fit in a uint32_t. So,
// (window + 1)^3 * 255 < 2^32. window = 255.
//
// window = floor(sigma * 3 * sqrt(2 * kPi) / 4)
// For window <= 255, the largest value for sigma is 135.
sigma.fX = SkTPin(sigma.fX, 0.0f, 135.0f);
sigma.fY = SkTPin(sigma.fY, 0.0f, 135.0f);
result = cpu_blur(ctx, sigma, input, inputBounds, dstBounds);
}