Jump to content

Gaussian Blur (Clamped) v2.0 - (Jan 22, 2016)


Recommended Posts

Gaussian Blur (Clamped)

Effects -> Blurs -> Gaussian Blur (Clamped)

 

Description

This effect is exactly the same as the regular Gaussian Blur effect, except this effect gets clamped to the active selection. This stops colors (and transparency) from bleeding through from outside of the selection.

If you don't have anything selected, there is no need to run this effect (although, it wouldn't hurt anything if you did run it).

ui.png

 

Comparison

Gaussian Blur (Clamped) - Radius of 25:

selection.png -> clamped.png

Gaussian Blur - Radius of 25:

selection.png -> reg.png

 

Change Log

v2.0 (Jan 22, 2016)

  • Changed: Now works on non-rectangular selections. (Thanks MJW)

v1.0 (Jan 11, 2016)

  • Initial release

 

Download

:RightArrowBlue:  ClampedGaussianBlur.zip

 

Donate

PP_logo_h_100x26.png

 

Source Code

https://github.com/toehead2001/pdn-clamped-gaussian-blur

 

 

Icon based on icons from Fugue Icons.

  • Like 1
  • Upvote 6
Link to post
Share on other sites

A useful feature. More than once I've wished the non-selected area could be excluded from the blur. Oddly enough I was thinking about adding the same feature to a (non-Gaussian blur) plugin I'm working on.

 

Oddly enough, this plugin is a side effect (no pun indented) of work I did for my Blur Fill plugin.

Edit: I see most (all?) the blur effects don't clamp to the selection. I never bothered to notice that before. Then again, I can't remember the last time I used a blur effect other than Gaussian Blur.

 

A step saver effect. Before I had to duplicate the blurred selection four or more times in order to bring back full opacity to the edges.

 

Before, I would copy the selection to a new image, since the canvas edge works as a clamp. Then I'd run Gaussian Blur.

Edited by toe_head2001
Link to post
Share on other sites

Thank you! :)

This will be great for making shiny effects easier.

 

Shiny, like what I did in this picture

http://m.artician.com/pu/4DBTZC3EM25CZMTXBFPP536M4CJTFVZS.original.png

 

That pic is old, but making new pics like it will hopefully be better now.

Edited by Cc4FuzzyHuggles
Link to post
Share on other sites

Maybe not, but you could clamp to the bounding rectangle and clip to the entire selection.

 

That's what I'm doing already, unless I misunderstand you.

 

It creates a Rectangle based on the selection, and clamps the pixels outside the selection to the edges of the Rectangle edges. It then calls Gaussian Blur on the selection, and renders it to the dst surface.

Edited by toe_head2001
Link to post
Share on other sites
On 1/12/2016 at 1:46 PM, toe_head2001 said:

Why do I always forget to test non-rectangular selections?  :/ Can a non-rectangle even be clamped?  I'll see if I can a solution.

toe_head2001,

This code should solve your problem:

 

Spoiler

using System;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using PaintDotNet;
using PaintDotNet.Effects;
using PaintDotNet.AppModel;
using PaintDotNet.IndirectUI;
using PaintDotNet.Collections;
using PaintDotNet.PropertySystem;
using IntSliderControl = System.Int32;

[assembly: AssemblyTitle("GaussianBlurClamped Plugin for Paint.NET")]
[assembly: AssemblyDescription("Blur only selected pixels")]
[assembly: AssemblyConfiguration("blur|clamped|gaussian")]
[assembly: AssemblyCompany("toe_head2001")]
[assembly: AssemblyProduct("GaussianBlurClamped")]
[assembly: AssemblyCopyright("Copyright ©2016 toe_head2001")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("2.0.*")]

namespace GaussianBlurClampedEffect
{
    public class PluginSupportInfo : IPluginSupportInfo
    {
        public string Author
        {
            get
            {
                return ((AssemblyCopyrightAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)[0]).Copyright;
            }
        }
        public string Copyright
        {
            get
            {
                return ((AssemblyDescriptionAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)[0]).Description;
            }
        }

        public string DisplayName
        {
            get
            {
                return ((AssemblyProductAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false)[0]).Product;
            }
        }

        public Version Version
        {
            get
            {
                return base.GetType().Assembly.GetName().Version;
            }
        }

        public Uri WebsiteUri
        {
            get
            {
                return new Uri("http://www.getpaint.net/redirect/plugins.html");
            }
        }
    }

    [PluginSupportInfo(typeof(PluginSupportInfo), DisplayName = "Gaussian Blur Clamped")]
    public class GaussianBlurClampedEffectPlugin : PropertyBasedEffect
    {
        public static string StaticName
        {
            get
            {
                return "Gaussian Blur Clamped";
            }
        }

        public static Image StaticIcon
        {
            get
            {
                return new Bitmap(typeof(GaussianBlurClampedEffectPlugin), "Clamped.png");
            }
        }

        public static string SubmenuName
        {
            get
            {
                return SubmenuNames.Blurs;
            }
        }

        public GaussianBlurClampedEffectPlugin()
            : base(StaticName, StaticIcon, SubmenuName, EffectFlags.Configurable)
        {
        }

        public enum PropertyNames
        {
            Amount1
        }

        protected override PropertyCollection OnCreatePropertyCollection()
        {
            List<Property> props = new List<Property>();

            props.Add(new Int32Property(PropertyNames.Amount1, 2,0,200));

            return new PropertyCollection(props);
        }

        protected override ControlInfo OnCreateConfigUI(PropertyCollection props)
        {
            ControlInfo configUI = CreateDefaultConfigUI(props);

            configUI.SetPropertyControlValue(PropertyNames.Amount1, ControlInfoPropertyNames.DisplayName, "Radius");

            return configUI;
        }

        protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs)
        {
            Amount1 = newToken.GetProperty<Int32Property>(PropertyNames.Amount1).Value;

            if (scratch == null)
            {
                scratch = new Surface(dstArgs.Size);
                scratch.Clear(ColorBgra.TransparentBlack);

                PdnRegion selectionRegion = EnvironmentParameters.GetSelection(srcArgs.Bounds);
                foreach (Rectangle r in selectionRegion.GetRegionScansInt())
                {
                    scratch.CopySurface(src,r.Location,r);
                }
            }

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

        protected override unsafe void OnRender(Rectangle[] rois, int startIndex, int length)
        {
            if (length == 0) return;
            for (int i = startIndex; i < startIndex + length; ++i)
            {
                Render(DstArgs.Surface,SrcArgs.Surface,rois[i]);
            }
        }

        #region User Entered Code
        #region UICode
        IntSliderControl Amount1=2; // [0,200] Radius
        #endregion

        Surface scratch = null;

        void Render(Surface dst, Surface src, Rectangle rect)
        {
            GaussianBlurEffect blurEffect = new GaussianBlurEffect();
            PropertyCollection blurProps = blurEffect.CreatePropertyCollection();
            PropertyBasedEffectConfigToken BlurParameters = new PropertyBasedEffectConfigToken(blurProps);
            BlurParameters.SetPropertyValue(GaussianBlurEffect.PropertyNames.Radius, Amount1);
            blurEffect.SetRenderInfo(BlurParameters, new RenderArgs(dst), new RenderArgs(scratch));
            blurEffect.Render(new Rectangle[1] {rect},0,1);
        }
        
        #endregion
    }
}

 

 

Sorry if it doesn't work. I just wrote it off the top of my head and haven't tested it.

Magic is in OnSetRenderInfo.

Edited by toe_head2001
Fixed broken Hidden box
  • Upvote 3

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites

This code should solve your problem...

 

Yes, it may, in part. When I said non-rectangular, I was specifically thinking of elliptical selections. The clamping would need to be radial.

 

Like so:

radial1.png---> radial2.png

 

 

 

Which of course can be done in code, but I have yet to try anything yet and measure the performance.

Edited by toe_head2001
Link to post
Share on other sites

toe_head2001, I'm not sure how you produced the second image in your most-recent comment, but it it wasn't through a program, and you intend to write such a program, I may be able to help.

 

Nothing fancy; Many layers and zooming.

 

Help is always welcome and appreciated.

Link to post
Share on other sites

I said it was odd that I was thinking of adding the feature of looking at the only the selected region in a plugin I'm working on. What's odder is that the plugin does pretty much what you're interested in doing. It takes an "object" (a region surrounded by transparency) and extends it by setting each transparent pixel to the color of the nearest non-transparent pixel. It uses a separate surface, but the algorithm is O(n), where n in the number of pixels in the window. I describe the algorithm in my "Fast algorithm for finding the minimum distances to a set" comment.

 

(The idea of clamping the edge in this way would work for blurring convex selections, but wouldn't work for some non-convex selections, since the color from one edge could bleed over into another if the blur radius exceeded half the distance between the edges.)

 

Here is the flower image processed with the algorithm.

 

FlowersExtended_zps2xxyffmq.png

Edited by MJW
  • Upvote 1
Link to post
Share on other sites

The code I wrote for you won't extrude a picture. It only blurs the selected pixels of an irregular selection without the influence of the non-selected pixels.

After looking at the code, the only problem will be calculating a proper alpha value for the blurred pixels. Perhaps it would use the source alpha or the most opaque alpha between the result pixel and the source pixel.

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites

A plugin that would 'trail' objects towards a vanishing point would be very useful! ;)

I normally duplicate the object, make the background object smaller, use zoom blur, then change the opacity.
The plugin named Trail 3d doesn't do that and Pyro's trail is great but doesn't converge for perspective.

 

I guess that's slightly off topic, sorry Toe_Head.

 

Red ochre Plugin pack............................................................... Diabolical Drawings

 

PdnForumSig2.jpg

Link to post
Share on other sites

I said it was odd that I was thinking of adding the feature of looking at the only the selected region in a plugin I'm working on. What's odder is that the plugin does pretty much what you're interested in doing. It takes an "object" (a region surrounded by transparency) and extends it by setting each transparent pixel to the color of the nearest non-transparent pixel. It uses a separate surface, but the algorithm is O(n), where n in the number of pixels in the window. I describe the algorithm in my "Fast algorithm for finding the minimum distances to a set" comment.

 

(The idea of clamping the edge in this way would work for blurring convex selections, but wouldn't work for some non-convex selections, since the color from one edge could bleed over into another if the blur radius exceeded half the distance between the edges.)

 

Thank you. I'll take a close look at this during the weekend when I have plenty of time.

 

Concave selections are pretty rare (or maybe it's just me that never makes them), so I don't think that's a big deal.

 

 

... It only blurs the selected pixels of an irregular selection without the influence of the non-selected pixels...

 

Just because the non-selected pixels are transparent, doesn't mean they aren't influencing the selected ones. That's why transparency is bleeding into the blur when your code is run. This is why the clamping is so important.

 

The code you posted in regards to the PdnRegion will be helpful though. Much appreciated.

I'd seen PdnRegion in other people's code before, but I never bothered to see what it did or what it was used for.

Link to post
Share on other sites
  • 2 weeks later...
  • 4 years later...

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...