Search code examples
c#dropshadowskiasharpskia

How can I tell the amount of space needed for a Skia dropshadow


Note: Since I am using SkiaSharp I will be posting code in C#; however, I suspect that conceptually this applies to Skia in any language/environment.

Summary

I am rendering a Skia object to a canvas of a given size. I would like the canvas to be sized such that it contains the rendered object and its drop shadow. How can I determine the extra padding needed for the dropshadow given a sigmaX and sigmaY

Code Example

I am drawing a rounded rectangle to a canvas using the following code:

var paint = SKPaint 
{ 
    Color = SKColors.Red, 
    Style = SKPaintStyle.Fill
};

float sigmaX = 5;
float sigmaY = 5;

paint.ImageFilter = SKImageFilter.CreateDropShadow(
            0,
            0,
            sigmaX,
            sigmaY,
            SKColors.Black,
            SKDropShadowImageFilterShadowMode.DrawShadowAndForeground);

surface.Canvas.DrawRoundRect(
    sigmaX,
    sigmaY, 
    Width - sigmaX * 2, 
    Height - sigmaY * 2, 
    5, 5, // corner radius
    paint);

In this code I have the canvas equal to Width and Height, but I am adding a padding of sigmaX and sigmaY, because I assumed that would provide enough room for the dropshadow.

However, this does not provide enough room for the dropshadow as shown in the following screenshot (zoomed to show the sharp boundaries more clearly):

enter image description here

If I want to make the canvas contain the dropshadow I have to increase the padding for the dropshadow to about 3 times the sigma value:


...

surface.Canvas.DrawRoundRect(
    sigmaX * 3,
    sigmaY * 3, 
    Width - (sigmaX * 2 * 3), 
    Height - (sigmaY * 2 * 3), 
    5, 5, // corner radius
    paint);

This seems to provide room for the dropshadow, as shown in the following screenshot:

enter image description here

Questions

What does sigma mean, and what should my padding be given a set sigma? Is sigma referring to standard deviation, so 3 would effectively capture 99% of the shadow, the way 3 standard deviations capture 99% of samples in a normal distribution? Or is there some other correlation between width and size that I'm missing?


Solution

  • It could be a late answer, but in Skia there's ConvertRadiusToSigma and ConvertSigmaToRadius functions which do exactly what you need.

    According to learn.microsoft.com:

    The sigma parameter specifies the extent of the blur. In older versions of Skia, the extent of the blur was indicated with a radius value. If a radius value is preferable for your application, there is a static SKMaskFilter.ConvertRadiusToSigma method that can convert from one to the other. The method multiplies the radius by 0.57735 and adds 0.5.