Jump to content

Bug in Gaussian Blur when used on custom surface


Recommended Posts

When you use a custom Surface as the input for the Gaussian Blur effect, and have the radius set to 0, it will mess with the pixels outside of the selection on the left and right.

 

Like so:

gb-example.jpg

 

And of course we all know modifying pixels outside the selection on the Destination canvas will break Undo.

 

This issue can be seen in plugins like my 'Inset Box Shadow' plugin, and BoltBait's 'Inner Shadow (Selection)'. Just set the Blur to 0 in either of these plugins.

 

I do not know if this is a new bug, or if it existed in old version of paint.net.

 

In the mean time, I suppose I can just use an If statement to bypass the Gaussian Blur if the value is 0.

--------- 

 

Here's a reduce code example demonstrating the bug. Run it on a selection. 

protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs)
{
    if (customSurface == null)
        customSurface = new Surface(srcArgs.Surface.Size);

    customSurface.Clear(Color.Purple);

    base.OnSetRenderInfo(newToken, dstArgs, srcArgs);
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    // Setup for calling the Gaussian Blur effect
    GaussianBlurEffect blurEffect = new GaussianBlurEffect();
    PropertyCollection blurProps = blurEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken BlurParameters = new PropertyBasedEffectConfigToken(blurProps);
    BlurParameters.SetPropertyValue(GaussianBlurEffect.PropertyNames.Radius, 0);
    blurEffect.SetRenderInfo(BlurParameters, new RenderArgs(dst), new RenderArgs(customSurface));
    // Call the Gaussian Blur function
    blurEffect.Render(new Rectangle[1] {rect},0,1);
}
Edited by toe_head2001

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

This isn't really a bug. The valid range for the Radius property is [2, 200] as specified by the Property itself.

 

If you want a proper range check then get the Property, cast to ScalarProperty<int>, and inspect its Min/MaxValue.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

The built-in Gaussian Blur has a UI range of 0-200.

 

BlurRange.png

 

As I recall, due to requests from us plugin authors, you added some special code to Gaussian Blur to handle the case of radius 0 where you do a copy surface. Apparently, this is a problem for non-rectangular selections in paint.net 4.0+.

 

If possible, I'd really like you to keep this functionality available to us plugin authors.

Lots of discussion about this "0" issue on pages 2-4 of this thread: http://forums.getpaint.net/index.php?/topic/6697-

post-44727-0-46510800-1455124939_thumb.p

Link to comment
Share on other sites

Yeah there's a bug here. I actually consider there to be 2 bugs. The other bug is that the effect rendering system should not break like that if you render outside of the region of interest.

 

       HRESULT (__stdcall EffectKernel_GaussianBlur)(
            BitmapData* pDstBitmap,
            BitmapData* pSrcBitmap,
            const RectInt32* prcRoi,
            const int nRoisLen,
            const int nBlurRadius)
        {
            if (pDstBitmap == NULL || pSrcBitmap == NULL || prcRoi == NULL)
            {
                return E_POINTER;
            }
 
            if (pDstBitmap->scan0 == NULL || pSrcBitmap->scan0 == NULL)
            {
                return E_POINTER;
            }
 
            if (nBlurRadius == 0)
            {
                for (int i = 0; i < nRoisLen; ++i)
                {
                    RectInt32 rect = prcRoi[i];
                    int cbRow = pDstBitmap->cbPixel * pDstBitmap->width;
 
                    for (int y = rect.y; y < rect.y + rect.height; ++y)
                    {
                        void* pDst = pDstBitmap->GetRowAddress(y);
                        void* pSrc = pSrcBitmap->GetRowAddress(y);
                        CopyMemory(pDst, pSrc, cbRow);
                    }
 
                    return S_OK;
                }
            }
...

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

ummmmmmmmmmmmm

 

that would be bug #3 ! O_O

 

I was referring to the fact that it copies rows from dst into src without respecting the horizontal span of the rectangle.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...