diff options
author | 2017-11-20 14:04:15 -0500 | |
---|---|---|
committer | 2017-11-21 22:43:50 +0000 | |
commit | a0ec54829eb77ec51747d2c8fd1ecfb7c0587965 (patch) | |
tree | 140d25af068b7a7e025400589ed7273b39ad98a8 /src/core/SkBlurImageFilter.cpp | |
parent | d46e85ff6903ca4d0d5d97bdfdde364b8559c0f4 (diff) |
Eliminate the use of a tmp buffer for image blur
Because the blur_one_direction routine, only reads the
source buffer once for each result, it can be used to
blur inplace. This allows the code to avoid using
a temporary buffer for the intermediate result.
This produces the same pixels according to skdiff, and
has the same speed.
Change-Id: I6485a71f0eb39936d69b8a98ab429a2cf592a7cd
Reviewed-on: https://skia-review.googlesource.com/74520
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkBlurImageFilter.cpp')
-rw-r--r-- | src/core/SkBlurImageFilter.cpp | 68 |
1 files changed, 29 insertions, 39 deletions
diff --git a/src/core/SkBlurImageFilter.cpp b/src/core/SkBlurImageFilter.cpp index 2f0759cfd5..088462b964 100644 --- a/src/core/SkBlurImageFilter.cpp +++ b/src/core/SkBlurImageFilter.cpp @@ -459,45 +459,35 @@ static sk_sp<SkSpecialImage> combined_pass_blur( SkSTArenaAlloc<1024> alloc; Sk4u* buffer = alloc.makeArrayDefault<Sk4u>(std::max(bufferSizeW, bufferSizeH)); - if (windowW > 1 && windowH > 1) { - // Blur both directions. - - auto tmpW = srcH, - tmpH = dstW; - - auto tmp = alloc.makeArrayDefault<uint32_t>(tmpW * tmpH); - - // Blur horizontally, and transpose. - blur_one_direction( - buffer, windowW, - srcBounds.left(), srcBounds.right(), dstBounds.right(), - static_cast<uint32_t*>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH, - tmp, tmpW, 1); - - // Blur vertically (scan in memory order because of the transposition), - // and transpose back to the original orientation. - blur_one_direction( - buffer, windowH, - srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(), - tmp, 1, tmpW, tmpH, - static_cast<uint32_t*>(dst.getPixels()), dst.rowBytesAsPixels(), 1); - } else if (windowW > 1) { - // Blur only horizontally. - - blur_one_direction( - buffer, windowW, - srcBounds.left(), srcBounds.right(), dstBounds.right(), - static_cast<uint32_t*>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH, - static_cast<uint32_t*>(dst.getPixels()), 1, dst.rowBytesAsPixels()); - } else if (windowH > 1) { - // Blur only vertically. - - blur_one_direction( - buffer, windowH, - srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(), - static_cast<uint32_t*>(src.getPixels()), src.rowBytesAsPixels(), 1, srcW, - static_cast<uint32_t*>(dst.getPixels()), dst.rowBytesAsPixels(), 1); - } else { + if (windowW > 1 || windowH > 1) { + auto intermediateSrc = static_cast<uint32_t *>(src.getPixels()); + auto intermediateRowBytesAsPixels = src.rowBytesAsPixels(); + auto intermediateWidth = srcW; + + if (windowW > 1) { + // For the horizontal blur, start part way down in anticipation of the vertical blur. + // If this is a horizontal only blur, then shift will be zero. + auto shift = (srcBounds.top() - dstBounds.top()); + intermediateSrc = static_cast<uint32_t *>(dst.getPixels()) + + (shift > 0 ? shift * dst.rowBytesAsPixels() : 0); + intermediateRowBytesAsPixels = dst.rowBytesAsPixels(); + intermediateWidth = dstW; + + blur_one_direction( + buffer, windowW, + srcBounds.left(), srcBounds.right(), dstBounds.right(), + static_cast<uint32_t *>(src.getPixels()), 1, src.rowBytesAsPixels(), srcH, + intermediateSrc, 1, intermediateRowBytesAsPixels); + } + + if (windowH > 1) { + blur_one_direction( + buffer, windowH, + srcBounds.top(), srcBounds.bottom(), dstBounds.bottom(), + intermediateSrc, intermediateRowBytesAsPixels, 1, intermediateWidth, + static_cast<uint32_t *>(dst.getPixels()), dst.rowBytesAsPixels(), 1); + } + } else { // There is no blurring to do, but we still need to copy the source while accounting for the // dstBounds. Remember that the src was intersected with the dst. int y = 0; |