vcl/source/bitmap/BitmapFilterStackBlur.cxx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
New commits: commit c28b3286435851ce82875ab6d3551f673de4a3eb Author: Mike Kaganski <[email protected]> AuthorDate: Wed Apr 29 10:25:32 2020 +0300 Commit: Mike Kaganski <[email protected]> CommitDate: Wed Apr 29 10:40:01 2020 +0200 Fix row/column pre-initialization in stack blur The changed code is used to initialize data before processing first pixel of each row/column of the bitmap, since in order to blur it, we need some information about assumed previous pixels. But previous code assumed that information for the first pixel or each row and each column is taken from first pixels of first column, not from first pixels of respective row or respective column. This doesn't make practical difference for the pre-extended bitmap with a solid color of the border (see centerExtendBitmap; it's the only actual case ATM). But in case of not pre-extended bitmap with non-solid border color, that would result in wrong blur of first pixels. Consider this bitmap (* is white, 0 is black): *00000000 *00000000 *00000000 *00000000 *00000000 000000000 ... For this bitmap, existing code pre-initialized each row and each column as if it were prepended with "******" from column 0, and so each first pixel of each column and each row would be blurred with white, even where it's all black (consider columns >=1, and rows >=5). Additionally, the existing initialization assumed that there's always at least as many scanlines as min(radius, bmpWidth), which might be false. See how aArrays was initialized using nLastIndexX in stackBlurHorizontal, and then that value affected the index passed to pReadAccess->GetScanline. This changes the code to consistently consider first pixels of respective rows/columns for pre-initialization data. Change-Id: Ibe3be8750fe5347302eca782a00b36096d99820c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93118 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Mike Kaganski <[email protected]> diff --git a/vcl/source/bitmap/BitmapFilterStackBlur.cxx b/vcl/source/bitmap/BitmapFilterStackBlur.cxx index adac14248753..fde6ab089a3b 100644 --- a/vcl/source/bitmap/BitmapFilterStackBlur.cxx +++ b/vcl/source/bitmap/BitmapFilterStackBlur.cxx @@ -98,7 +98,7 @@ public: { for (long i = 0; i < maShared.mnDiv; i++) { - maPositionTable[i] = std::min(nLastIndex, std::max(0L, i - maShared.mnRadius)); + maPositionTable[i] = std::clamp(i - maShared.mnRadius, 0L, nLastIndex); maWeightTable[i] = maShared.mnRadius + 1 - std::abs(i - maShared.mnRadius); } } @@ -261,9 +261,15 @@ void stackBlurHorizontal(BlurSharedData const& rShared, long nStart, long nEnd) SumFunction::set(nInSum, 0L); SumFunction::set(nOutSum, 0L); + // Pre-initialize blur data for first pixel. + // aArrays.maPositionTable contains values like (for radius of 5): [0,0,0,0,0,0,1,2,3,4,5], + // which are used as pixels indices in the current row that we use to prepare information + // for the first pixel; aArrays.maWeightTable has [1,2,3,4,5,6,5,4,3,2,1]. Before looking at + // the first row pixel, we pretend to have processed fake previous pixels, as if the row was + // extended to the left with the same color as that of the first pixel. for (long i = 0; i < nDiv; i++) { - pSourcePointer = pReadAccess->GetScanline(pPositionPointer[i]); + pSourcePointer = pReadAccess->GetScanline(y) + nComponentWidth * pPositionPointer[i]; pStackPtr = &pStack[nComponentWidth * i]; @@ -374,9 +380,15 @@ void stackBlurVertical(BlurSharedData const& rShared, long nStart, long nEnd) SumFunction::set(nInSum, 0L); SumFunction::set(nOutSum, 0L); + // Pre-initialize blur data for first pixel. + // aArrays.maPositionTable contains values like (for radius of 5): [0,0,0,0,0,0,1,2,3,4,5], + // which are used as pixels indices in the current column that we use to prepare information + // for the first pixel; aArrays.maWeightTable has [1,2,3,4,5,6,5,4,3,2,1]. Before looking at + // the first column pixels, we pretend to have processed fake previous pixels, as if the + // column was extended to the top with the same color as that of the first pixel. for (long i = 0; i < nDiv; i++) { - pSourcePointer = pReadAccess->GetScanline(pPositionPointer[i]); + pSourcePointer = pReadAccess->GetScanline(pPositionPointer[i]) + nComponentWidth * x; pStackPtr = &pStack[nComponentWidth * i]; _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
