summaryrefslogtreecommitdiff
path: root/vcl/source/bitmap
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2020-05-01 01:05:24 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2020-05-07 21:57:37 +0200
commit08ebcff89f56bec3b0f9b346504748e4eb1687af (patch)
treed511115b648fd5f2340fd88eacc4ad9971ad7348 /vcl/source/bitmap
parenta98bdbae459ad7341bf7f484c402e77e4062cd16 (diff)
tdf#101181: improve glow effect
The shadow of objects must not be scaled: this displaces any internal areas that need blur, e.g. holes. Instead, it needs to dilate the shadow using kernel with radius equal to blur radius: this allows the borders of dilated objects to be in the middle of the blur area. The following blur makes those new margin points to have 50% intensity, and full glow intensity at the point of old object margins. This also removed artifacts when moving objects with glow effect caused by mismatch between scaling and D2D range calculation. The D2D range therefore is not calculated by scaling, but using grow. Blur filter's "extend bitmap by blur radius" option got obsoleted and removed. There's no need to blur the glow color (24-bit RGB). Instead, glow bitmap must be filled by glow color, and have an alpha mask that is blurred accordingly. This makes the glow properly transparent, and also reduces the blur complexity which now only needs to process 8 bits of alpha channel. The object shadow is created using basegfx::BColorModifier_replace inserted into the 2d decomposition of the effect, as before. To make sure that any non-fully-transparent pixel will become black pixel in the shadow, black color is used, and the result is further processed in VclPixelProcessor2D::processGlowPrimitive2D with monochrome filter using threshold 255. Glow transparency attribute is taken into account: the initial value at the margins of the objects. Color replacement filter is used to replace the object shadow with the attribute value before blur pass. Correct blur radius is used, calculated from glow effect radius, instead of hardcoded value of 5 pixels. This makes the glow to fade gradually along the full width of the effect, instead of only fading in narrow outer border previously. Since blur filter is only implemented for radius up to 254 pixels, and since downsampling the shadow before blur increases performance without noticeable quality loss, the image is downsampled before filtering. It should be noted that the glow effect is almost identical to soft shadow effect, likely with the only difference of using dilation in the former, but not in the latter. The code might be reused later to implement soft shadow as well. Change-Id: I728c532f9df7ccf85f353c23c6c7d8352d7b2086 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93235 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'vcl/source/bitmap')
-rw-r--r--vcl/source/bitmap/BitmapFilterStackBlur.cxx46
1 files changed, 1 insertions, 45 deletions
diff --git a/vcl/source/bitmap/BitmapFilterStackBlur.cxx b/vcl/source/bitmap/BitmapFilterStackBlur.cxx
index 9b3c37127fcf..da51daedfacc 100644
--- a/vcl/source/bitmap/BitmapFilterStackBlur.cxx
+++ b/vcl/source/bitmap/BitmapFilterStackBlur.cxx
@@ -558,39 +558,6 @@ void stackBlur8(Bitmap& rBitmap, sal_Int32 nRadius, sal_Int32 nComponentWidth)
pBlurVerticalFn, bParallel);
}
-void centerExtendBitmap(Bitmap& rBitmap, sal_Int32 nExtendSize, Color aColor)
-{
- const Size& rSize = rBitmap.GetSizePixel();
- const Size aNewSize(rSize.Width() + nExtendSize * 2, rSize.Height() + nExtendSize * 2);
-
- Bitmap aNewBitmap(aNewSize, rBitmap.GetBitCount());
-
- {
- Bitmap::ScopedReadAccess pReadAccess(rBitmap);
- BitmapScopedWriteAccess pWriteAccess(aNewBitmap);
-
- long nWidthBorder = nExtendSize + rSize.Width();
- long nHeightBorder = nExtendSize + rSize.Height();
-
- for (long y = 0; y < aNewSize.Height(); y++)
- {
- for (long x = 0; x < aNewSize.Width(); x++)
- {
- if (y < nExtendSize || y >= nHeightBorder || x < nExtendSize || x >= nWidthBorder)
- {
- pWriteAccess->SetPixel(y, x, aColor);
- }
- else
- {
- pWriteAccess->SetPixel(y, x,
- pReadAccess->GetPixel(y - nExtendSize, x - nExtendSize));
- }
- }
- }
- }
- rBitmap = aNewBitmap;
-}
-
} // end anonymous namespace
/**
@@ -614,9 +581,8 @@ void centerExtendBitmap(Bitmap& rBitmap, sal_Int32 nExtendSize, Color aColor)
* (https://code.google.com/p/fog/)
*
*/
-BitmapFilterStackBlur::BitmapFilterStackBlur(sal_Int32 nRadius, bool bExtend)
+BitmapFilterStackBlur::BitmapFilterStackBlur(sal_Int32 nRadius)
: mnRadius(nRadius)
- , mbExtend(bExtend)
{
}
@@ -648,22 +614,12 @@ Bitmap BitmapFilterStackBlur::filter(Bitmap const& rBitmap) const
? 4
: 3;
- if (mbExtend)
- {
- centerExtendBitmap(bitmapCopy, mnRadius, COL_WHITE);
- }
-
stackBlur24(bitmapCopy, mnRadius, nComponentWidth);
}
else if (nScanlineFormat == ScanlineFormat::N8BitPal)
{
int nComponentWidth = 1;
- if (mbExtend)
- {
- centerExtendBitmap(bitmapCopy, mnRadius, COL_WHITE);
- }
-
stackBlur8(bitmapCopy, mnRadius, nComponentWidth);
}