Sign in to follow this  
TechnoRobbo

TR's Str8Edge Tool V1.1

Recommended Posts

TR's Str8Edge Tool V1.1


Smooths out jagged edges on a Cut-Out.


(For those of use who's hands are not that steady)


 


Version 1.1 Updated for Paint.net 4.0


 


 


Menu:


Effects->Object


 


 


Str8Edge.PNG?raw=1


 


Deselect before using.


 


YouTube Example



 


Composite of tiger done with Lasso and Str8Edge tool. No Edge Feathering!!!


(Minimal Cleanup - Hand drawn  whiskers)


 


Hand Selected Tiger


Str8EdgeTiger.png?raw=1


 


The Code


Hidden Content:

// Compiler options:  /unsafe /optimize /debug- /target:library /out:"C:\Program Files\Paint.NET\Effects\TRsStr8Edge.dll"

using System;

using System.Text;

using System.Windows;

using System.Reflection;

using System.Windows.Forms;

using PaintDotNet;

using PaintDotNet.Effects;

using PaintDotNet.IndirectUI;

using PaintDotNet.PropertySystem;

using System.Collections.Generic;

using System.Drawing;

using System.Drawing.Text;

using System.Runtime.CompilerServices;

using System.Runtime.InteropServices;

 

[assembly: AssemblyTitle("TRsStr8EdgePlugin")]

[assembly: AssemblyDescription("TRsStr8Edge Plugin for Paint.NET. (Compiled by Code Lab v1.8)")]

[assembly: AssemblyConfiguration("")]

[assembly: AssemblyCompany("TechnoRobbo")]

[assembly: AssemblyProduct("TRsStr8EdgePlugin")]

[assembly: AssemblyCopyright("Copyright © TechnoRobbo")]

[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]

[assembly: ComVisible(false)]

[assembly: AssemblyVersion("1.1.*")]

 

namespace TRsStr8EdgeEffect

{

    public class PluginSupportInfo : IPluginSupportInfo

    {

        public string Author

        {

            get

            {

                return "TechnoRobbo";

            }

        }

        public string Copyright

        {

            get

            {

                return ((AssemblyCopyrightAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)[0]).Copyright;

            }

        }

 

        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.technorobbo.com");

            }

        }

    }

 

    [PluginSupportInfo(typeof(PluginSupportInfo), DisplayName = "TRsStr8Edge")]

    public class TRsStr8EdgeEffectPlugin : PropertyBasedEffect

    {

        public static string StaticName

        {

            get

            {

                return "TR's Str8 Edge";

            }

        }

 

        public static Image StaticIcon

        {

            get

            {

                return null;

            }

        }

 

        public TRsStr8EdgeEffectPlugin()

            : base(StaticName, StaticIcon, "Object", EffectFlags.Configurable)

        {

        }

 

        public enum PropertyNames

        {

            Amount1

        }

 

 

        protected override PropertyCollection OnCreatePropertyCollection()

        {

            List<Property> props = new List<Property>();

 

            props.Add(new Int32Property(PropertyNames.Amount1, 1, 1, 20));

 

            return new PropertyCollection(props);

        }

 

        protected override ControlInfo OnCreateConfigUI(PropertyCollection props)

        {

            ControlInfo configUI = CreateDefaultConfigUI(props);

 

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

 

            return configUI;

        }

 

        bool noskip = true;

        protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs)

        {

            this.Amount1 = newToken.GetProperty<Int32Property>(PropertyNames.Amount1).Value;

            noskip = true;

            base.OnSetRenderInfo(newToken, dstArgs, srcArgs);

        }

 

 

        protected override void OnCustomizeConfigUIWindowProperties(PropertyCollection props)

        {

            // Change the effect's window title

            props[ControlInfoPropertyNames.WindowTitle].Value = "TR's Str8 Edge - V 1.1";

            base.OnCustomizeConfigUIWindowProperties(props);

        }

 

        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);

            }

        }

 

        #region User Entered Code

        // Submenu: Object

        // Name: TR's Str8 Edge 

        // Title: TR's Str8 Edge - V 1.1 

        // Author: TechnoRobbo

        // URL: http://www.technorobbo.com

        #region UICode

        int Amount1 = 1; // [1,20] Amount

        #endregion

 

        

        void Render(Surface dst, Surface src, Rectangle rect)

        {

            if (noskip)

            {

                Rectangle sel = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();

                dst.CopySurface(src, sel.Location, sel);

                noskip = false;

                try

                {

                    ColorBgra CP = new ColorBgra();

                    int[] offx = { -1, 0, 1, -1, 1, -1, 0, 1 };

                    int[] offy = { -1, -1, -1, 0, 0, 1, 1, 1 };

                    byte[,] agrid = new byte[sel.Width, sel.Height];

                    byte[,] bgrid = new byte[sel.Width, sel.Height];

                    //=================================================

                    for (int oy = sel.Top; oy < sel.Bottom; oy++)

                    {

                        for (int ox = sel.Left; ox < sel.Right; ox++)

                        {

                            CP = src.GetBilinearSampleClamped(ox, oy);

                            bgrid[ox, oy] = (byte)((CP.A == 0) ? 0 : 255);

                        }

                    }

                    //---------------------------------------------------  

                    for (int z = 0; z < Amount1; z++)

                    {

                        Array.Copy(bgrid, agrid, agrid.Length);

                        for (int y = sel.Top; y < sel.Bottom; y++)

                        {

                            for (int x = sel.Left; x < sel.Right; x++)

                            {

 

                                if (agrid[x, y] != 0)

                                {

 

                                    int Threshold = 255;

                                    int Sigma = 0;

                                    for (int i = 0; i < 8; i++)

                                    {

                                        int nx = Int32Util.Clamp(offx + x, 0, sel.Width - 1);

                                        int ny = Int32Util.Clamp(offy + y, 0, sel.Height - 1);

                                        Threshold = Math.Min(agrid[nx, ny], Threshold);

                                        Sigma += agrid[nx, ny];

                                    }

 

                                    if (Threshold == 0)

                                    {

 

                                        CP = src.GetBilinearSample(x, y);

                                        if (Sigma >= 1275)

                                        {

                                            CP.A = 255;

                                        }

                                        else

                                        {

                                            CP.A = 0;

                                            bgrid[x, y] = 0;

                                        }

                                        dst[x, y] = CP;

                                    }

                                } //if

                            } //x

                        } //y

                    }

                }

                catch (Exception e) { }

            }

            else

            {

                ColorBgra CP = dst[0, 0];

                dst[0, 0] = CP;

            }

 

        }

        #endregion

    }

}

 

 



TRsStr8Edge.zip

Edited by TechnoRobbo
  • Upvote 3

Share this post


Link to post
Share on other sites

How it Works


 


The tool examines each pixel twice. First it looks for the tell-tale pattern of an edge.


Then it looks for the tell-tale pattern of a straight edge.


 


An edge is found when an adjacent pixel being transparent.


a straight edge is found when the sum of the adjacent pixels alpha is equal or higher than 1275!


If the pixel is not partof a straight edge - it's removed.


 


Why 1275? a Opaque pixel has a Alpha value of 255. 1275 is 255 times 5.


 


Str8EdgeHow.PNG?raw=1


The tool allows for 20 consecutive passes.


Edited by TechnoRobbo
  • Upvote 1

Share this post


Link to post
Share on other sites

Not only a fab new plugin but a good explanation for how it works. So is this similar to Feather & the Old Feather?

 

I was amazed at your mouse control with the lasso tool :P

 

Thankies once again for another beaut plugin!

Share this post


Link to post
Share on other sites

No it's not a feather. There's no feathering at all. It rejects pixels that don't conform to a straight edge definition.

 

Actually I don't have good lasso control the Str8Edge tool corrected my coffee-fueled mess.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this