Jump to content

Red ochre

Members
  • Posts

    3,025
  • Joined

  • Last visited

  • Days Won

    125

Posts posted by Red ochre

  1. Hi Pixey - nice work on the new sig! B)

    Love the grapes, vine leaves, apple and mouse.
    (- bit confused as to what that is behind the mouses head in front of the apple - tail? tendril?)

    Rest of it looks great though, and your gallery works perfectly and loads quickly too!
     (often a problem on other galleries - with my sluggish broadband).

  2. Why not use the grid maker plugin: http://forums.getpaint.net/index.php?showtopic=4175
    - on a transparent layer with foreground only checked. Then use it as a guide to line up your objects?

    I think a snap to grid plugin could be very decieving as the anti-aliased pixels around an object mean that edges are not always where they seem to be. So for it to look correct you would need a fine adjustment - so you may as well do it the long way I've suggested and decide if it 'looks' correct.

    Have you tried the align object plugin ? : http://forums.getpaint.net/index.php?showtopic=4193

  3. That looks interesting Midora, particularly 'Tabs'.
    'LabelMin' and 'LabelMax' would certainly make it easier to align the words correctly and I like the option to show units too.


    I have a few ideas that may or may not be sensible (I simply don't have the knowledge yet to know how difficult or practical these things are to do using a customU.I.).

    1. I find the 'reset to default' buttons for the trackbars very useful. There doesn't appear to be this function for the checkboxes, drop-down lists or radio buttons - perhaps there could be one 'reset all to default' button for all the controls?
    Aha! - I've just noticed you have included this for checkboxes in your example.

    2. I find the drop-down lists very useful as they save a lot of space on the U.I compared to radio buttons. I wonder if there could be a drop-down list of ckeckboxes too?

    3. Possibly an 'Info' button to show a message box where the plugin author can write basic instuctions?

    Just thought I would suggest these in case they have not already been considered.

    The OptionBased library looks very promising! - thanks for posting the example.
     

  4. Daniels - please do - I find simply 'playing' with plugins the best way to learn and discover new techniques.

    EER - I should nominate that to the Galeria (but there could be copyright issues) - it does make me chuckle!

    YM - stunning! - great use of the plugin and the image itself is a pleasure - great colours & textures!

    Dug - looking forward to seeing what surreal uses you find for it.

    Pixey - That looks great! - original use of Furblur for the icicles. 'Clever' - I wish! (Null54 is the clever one for getting it working).

    Helen - you can hug me anytime! - looking forward to seeing your results - perhaps some candyfloss trees for your candy house?

    Good to see what you're all creating. :)

    • Upvote 1
  5. Hi Null54,

    Imagine a preset called say 'very large curls' created on a standard 800 by 600 canvas.
    The user next uses this preset on a 1600 by 1200 canvas and eventually sees a very small curly texture.
    The effect the user sees is very dependant upon the selection size.

    I think the presets idea would be more relevant for a 'Render' effect where the size, especially line width, can be related to the selection size. If FurBlur had used GDI+ to draw the lines it would have been relatively easy to change the line width based on selection size. But then it would be a different effect.

    Thanks for the example XML - I can see presets being useful for other effects but not really convinced it is needed for this one.

    Do I understand correctly, XML presets could only be used with a Windows Forms based effect (or the 'OptionBasedLibrary' in the future) but are not possible with the current IndirectUI?

    Sorry for my confusing explanations!
     

  6. Aaaah - too many people to thank - you're posting fasting than I can type!

    TR - Thanks for the support on this one and brilliant images too!

    BB - Thanks - it started life in codelab!

    EER - Thanks for all the VS tips and encouragement too.

    doughty - glad you reposted the prevoius 2 and the furryworm is great!

    BBQ - hope you are getting decent results now.

    WB - love the Obama one!

    Drew' - Thanks for reposting Fircraft and hairy target and adding the clipwarped one too.

    Oceana - That's given me vertigo!

    NN - Cheers - you know me too well!

    Should be ok to use on layer after 'Curly Line' - If using Furblur repeatedly on the same object layer you may need to lower the 'Start object transparency' slider a little. That's because it is a blur and mixes the opaque object with the transparent surrounding pixels.

    To all - many thanks all who tested and have reposted or added new examples. Glad you seem to be having fun with it and many thanks to Null54 for getting it to work!

    • Upvote 2
  7. Midora - the OptionBasedLibrary sounds very promising!

    TR - Thanks for the example code and .dll - I can just about get the idea of how it works. It could be a useful technique for future plugins. (Update: Midora has just posted - so, still interesting but looks like the long way is best - many thanks anyway)

    Regarding presets or user saveable settings for FurBlur, I'm not sure it would make the effect any easier to use or understand. Because it is a blur on a pixel size scale, any preset would look very different on different selection sizes. If it was a GDI+ based render effect, then the preset sizes could take selection size into account - and presets would be a better idea.

    I have used a drop-down list and switch block before, to make presets that change the way the control values are used (or ignore them). (e.g. 'Highlight' and 'Object2colour'). - Haven't tried anything saveable though.

    I tend to think some users will want a plugin to work perfectly with the default values and others are happy to explore all the controls to get the effect they want. I'm not sure the first type would be bothered to create and save settings and the second type possibly wouldn't need to?

    For Effects more generally, I tend to either use an effect with different settings each time or consecutively run the same effect with same 'auto-remembered' settings. If I really need to record exact settings for a plugin I write them down - (useful equations for 3D Object plugin for example).

    So, I don't intend to add presets to Furblur but will consider it for future plugins. Many thanks for all the suggestions and info though. Some of it will sink in eventually!
     

  8. TR - love it! B)

    EER - That is a good idea - I must admit I haven't got a clue where to start though and have never used that Shape3D option. If you would like to help me, I/we can either delay publication or add this as an update later?
    I would favour publishing sooner - so people have a proper thread to show all these great images.

    YM - great fun! :lol:

    BBQ - I hope you are getting decent results now - if not, please post back. I am useless at explaining things (not great at understanding sometimes either!).

    WB - I'm hoping this will be useful for textures and chromatography/watercolour type effects as well as photo-manips (which are great fun!).
     

  9. - Just typed a long reply BBQ - then bashed the mouse and I've got to type it all again!

     

    Ok. Best not to use on all of a large canvas to start with.

    The calculations are run single threadedly - so none of the speed advantages of a powerful machine.

    I suspect the little lines are the effect - it operates on a pixel size scale so may be hard to see on a huge canvas.

     

    Suggest to test:

    1. New image 800 * 600 - make background black.

    2. New layer (transparent)

    3. Draw 10 pix wiggly lines. nice bright colours

    4. Possibly select around these lines with the lasso tool (leave plenty of room for the effect!)

    5. Effects/Blurs/Furblur - lower the 'rep' slider and increase the 'length' slider to start.

    6. Try each slider seperately to see what they do.

     

    If still no joy report back please!

     

    I am working on getting some examples together at the moment with screenshots.

    6ifH20t.png

    • Upvote 2
  10. No crashes yet then ? good! - thanks all for testing and positive feedback. I will publish it properly soon.

    doughty - I really like that one. Interesting 'grunge' texture + the 'curve variation' slider way up = looks good! ;)

    Drew - another good result! - that aeroplane needs a shave!   :lol:   - thanks for checking this one out.

    TR - Thanks for the compliment - knowing your programming skills I am very flattered! :)

    Regarding presets: I don't intend to add them - partly due to my laziness and also because I would rather users 'play' with all the controls to get an idea of what this can do. I generally like to give users as many options as practical but I know this can sometimes make the U.I. a bit intimidating. I will include some example settings and results in the publishing thread but hopefully users will experiment and come up with new uses.

    That tiger has walked a long way! :D
     

    • Upvote 1
  11. EchAv10.png

    I am attaching the newest version of Furblur for testing. I've added quite a lot including the circular option for the curve, which gives much better results. However, I like the previous, slightly dotted (spiral) version as it can look like grass seeds, so am keeping that option.

    Now doesn't mix the colour with the transparent white!

    Added a slider to choose the transparency threshold of an 'object'. At around 250 will only put fur on 'objects', at 0 will work on whole selection (only seen if colour turned up).

    Speeded up slightly too.

    Changed radio buttons to checkboxes to save space.

    I would be grateful if you can give it try and report any crashes. There shouldn't be any - but I thought that with the last one! - Many thanks

    Also removing old versions of the .dll to avoid confusion.

    The .dll

    Some more examples:

    RtaIJ3r.pngqMlYKJF.pngRAlFK3T.png

    VS source code:

    Hidden Content:
    // Compiler options:  /unsafe /optimize /res:"C:\Users\john\Code experiments\PLUGIN pack stuff\pdn plugin graphics\plugin pack icons\FurBlurIcon.png","FurBlurEffect.FurBlurIcon.png"  /debug- /target:library /out:"C:\Program Files\Paint.NET\Effects\FurBlur2.dll"
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using PaintDotNet;
    using PaintDotNet.Effects;
    using PaintDotNet.IndirectUI;
    using PaintDotNet.PropertySystem;
    
    [assembly: AssemblyTitle("FurBlurPlugin")]
    [assembly: AssemblyDescription("FurBlur Plugin for Paint.NET")]
    [assembly: AssemblyConfiguration("")]
    [assembly: AssemblyCompany("Red ochre (John Robbins)")]
    [assembly: AssemblyProduct("FurBlurPlugin")]
    [assembly: AssemblyCopyright("Copyright © Red ochre (John Robbins)helped by Null54")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    [assembly: ComVisible(false)]
    [assembly: AssemblyVersion("1.0.1")]
    
    namespace FurBlurEffect
    {
        public class PluginSupportInfo : IPluginSupportInfo
        {
            public string Author
            {
                get
                {
                    return "Red ochre (John Robbins)helped by Null54";
                }
            }
            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.getpaint.net/redirect/plugins.html");
                }
            }
        }
    
        [PluginSupportInfo(typeof(PluginSupportInfo), DisplayName = "FurBlur")]
        public class FurBlurEffectPlugin : PropertyBasedEffect
        {// add another surface in "public class ....Plugin : PropertyBasedEffect"
            private Surface destSurface;
    
            protected override void OnDispose(bool disposing)//added
            {
                if (disposing)
                {
                    if (destSurface != null)
                    {
                        destSurface.Dispose();
                        destSurface = null;
                    }
                }
    
                base.OnDispose(disposing);
            }
            public static string StaticName
            {
                get
                {
                    return "Furblur";
                }
            }
    
            public static Image StaticIcon
            {
                get
                {
                    return FurBlur.Properties.Resources.FurBlurIcon;
                }
            }
    
            public FurBlurEffectPlugin()
                : base(StaticName, StaticIcon, "Blurs", EffectFlags.Configurable)
            {
                instanceSeed = unchecked((int)DateTime.Now.Ticks);
            }
    
            public enum PropertyNames
            {
                StartC,
                Reps,
                MaxL,
                LenV,
                Mang,
                Bid,
                AngV,
                CurT,
                CurA,
                CurV,
                FriV,
                Sooo,
                BTrat,
                ColT,
                ColM,
                Qual,
                JustF,
                ReSeed
    
            }
    
    
    
    
            [ThreadStatic]
            private static Random RandomNumber;
    
            private int instanceSeed;
    
    
    
            protected override PropertyCollection OnCreatePropertyCollection()
            {
                List<Property> props = new List<Property>();
                props.Add(new BooleanProperty(PropertyNames.StartC, false));
                props.Add(new DoubleProperty(PropertyNames.Reps, 10, 0, 100));
                props.Add(new Int32Property(PropertyNames.MaxL, 30, 1, 300));
                props.Add(new DoubleProperty(PropertyNames.LenV, 0.10, 0, 1));
                props.Add(new DoubleProperty(PropertyNames.Mang, 90, -180, +180));
                props.Add(new BooleanProperty(PropertyNames.Bid, false));
                props.Add(new DoubleProperty(PropertyNames.AngV, 0.10, 0, 1));
                props.Add(new BooleanProperty(PropertyNames.CurT, true));
                props.Add(new DoubleProperty(PropertyNames.CurA, 0.10, 0, 1));
                props.Add(new DoubleProperty(PropertyNames.CurV, 0.10, 0, 1));
                props.Add(new DoubleProperty(PropertyNames.FriV, 0.10, 0, 1));
                props.Add(new Int32Property(PropertyNames.Sooo, 250, 0, 255));
                props.Add(new DoubleProperty(PropertyNames.BTrat, 0, 0, 1));
                props.Add(new BooleanProperty(PropertyNames.ColT, true));
                props.Add(new DoubleProperty(PropertyNames.ColM, 0, 0, 1));
                props.Add(new BooleanProperty(PropertyNames.Qual, true));
                props.Add(new BooleanProperty(PropertyNames.JustF, false));
                props.Add(new Int32Property(PropertyNames.ReSeed, 0, 0, 255));
    
                List<PropertyCollectionRule> propRules = new List<PropertyCollectionRule>();
                propRules.Add(new ReadOnlyBoundToBooleanRule("StartC", "JustF", false));
    
                return new PropertyCollection(props, propRules);
            }
    
            protected override ControlInfo OnCreateConfigUI(PropertyCollection props)
            {
                ControlInfo configUI = CreateDefaultConfigUI(props);
    
                configUI.SetPropertyControlValue(PropertyNames.StartC, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.StartC, ControlInfoPropertyNames.Description, "0 = Src(original): tick = Dst(fur on fur)");
                configUI.SetPropertyControlValue(PropertyNames.Reps, ControlInfoPropertyNames.DisplayName, "Repetitions:      big reps & big length = slow!");
                configUI.SetPropertyControlValue(PropertyNames.MaxL, ControlInfoPropertyNames.DisplayName, "Main length");
                configUI.SetPropertyControlValue(PropertyNames.LenV, ControlInfoPropertyNames.DisplayName, "Length variations");
                configUI.SetPropertyControlValue(PropertyNames.LenV, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.LenV, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.LenV, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.Mang, ControlInfoPropertyNames.DisplayName, "Main angle");
                configUI.SetPropertyControlType(PropertyNames.Mang, PropertyControlType.AngleChooser);
                configUI.SetPropertyControlValue(PropertyNames.Bid, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.Bid, ControlInfoPropertyNames.Description, "Both directions");
                configUI.SetPropertyControlValue(PropertyNames.AngV, ControlInfoPropertyNames.DisplayName, "Angle variation");
                configUI.SetPropertyControlValue(PropertyNames.AngV, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.AngV, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.AngV, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.CurT, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.CurT, ControlInfoPropertyNames.Description, "0 = spiral(original - dotty): tick = circular(smooth!)");
                configUI.SetPropertyControlValue(PropertyNames.CurA, ControlInfoPropertyNames.DisplayName, "Curl curvature");
                configUI.SetPropertyControlValue(PropertyNames.CurA, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.CurA, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.CurA, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.CurV, ControlInfoPropertyNames.DisplayName, "Curl variation");
                configUI.SetPropertyControlValue(PropertyNames.CurV, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.CurV, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.CurV, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.FriV, ControlInfoPropertyNames.DisplayName, "Frizz curvature");
                configUI.SetPropertyControlValue(PropertyNames.FriV, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.FriV, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.FriV, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.Sooo, ControlInfoPropertyNames.DisplayName, "Start object transparency");
                configUI.SetPropertyControlValue(PropertyNames.BTrat, ControlInfoPropertyNames.DisplayName, "Blur......................................................................Trail");
                configUI.SetPropertyControlValue(PropertyNames.BTrat, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.BTrat, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.BTrat, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.ColT, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.ColT, ControlInfoPropertyNames.Description, "0 = simple mix: tick = along fur");
                configUI.SetPropertyControlValue(PropertyNames.ColM, ControlInfoPropertyNames.DisplayName, "Src Color............................................... Primary Color");
                configUI.SetPropertyControlValue(PropertyNames.ColM, ControlInfoPropertyNames.SliderLargeChange, 0.25);
                configUI.SetPropertyControlValue(PropertyNames.ColM, ControlInfoPropertyNames.SliderSmallChange, 0.05);
                configUI.SetPropertyControlValue(PropertyNames.ColM, ControlInfoPropertyNames.UpDownIncrement, 0.01);
                configUI.SetPropertyControlValue(PropertyNames.Qual, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.Qual, ControlInfoPropertyNames.Description, "0 = 1pix: tick = 4 pix anti-aliased");
                configUI.SetPropertyControlValue(PropertyNames.JustF, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlValue(PropertyNames.JustF, ControlInfoPropertyNames.Description, "Only keep fur (src Start colour only)");
                configUI.SetPropertyControlValue(PropertyNames.ReSeed, ControlInfoPropertyNames.DisplayName, string.Empty);
                configUI.SetPropertyControlType(PropertyNames.ReSeed, PropertyControlType.IncrementButton);
                configUI.SetPropertyControlValue(PropertyNames.ReSeed, ControlInfoPropertyNames.ButtonText, "Reseed");
    
                return configUI;
            }
            protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs)
            {
    
                this.startColour = newToken.GetProperty<BooleanProperty>(PropertyNames.StartC).Value;
                this.repCount = newToken.GetProperty<DoubleProperty>(PropertyNames.Reps).Value;
                this.maxLength = newToken.GetProperty<Int32Property>(PropertyNames.MaxL).Value;
                this.lengthVariation = newToken.GetProperty<DoubleProperty>(PropertyNames.LenV).Value;
                this.mainAngle = newToken.GetProperty<DoubleProperty>(PropertyNames.Mang).Value;
                this.biDirectional = newToken.GetProperty<BooleanProperty>(PropertyNames.Bid).Value;
                this.angleVariation = newToken.GetProperty<DoubleProperty>(PropertyNames.AngV).Value;
                this.curtype = newToken.GetProperty<BooleanProperty>(PropertyNames.CurT).Value;
                this.curvature = newToken.GetProperty<DoubleProperty>(PropertyNames.CurA).Value;
                this.curvVari = newToken.GetProperty<DoubleProperty>(PropertyNames.CurV).Value;
                this.frizz = newToken.GetProperty<DoubleProperty>(PropertyNames.FriV).Value;
                this.startOnObject = newToken.GetProperty<Int32Property>(PropertyNames.Sooo).Value;
                this.blurAmount = newToken.GetProperty<DoubleProperty>(PropertyNames.BTrat).Value;
                this.coltype = newToken.GetProperty<BooleanProperty>(PropertyNames.ColT).Value;
                this.colmix = newToken.GetProperty<DoubleProperty>(PropertyNames.ColM).Value;
                this.quality = newToken.GetProperty<BooleanProperty>(PropertyNames.Qual).Value;
                this.justF = newToken.GetProperty<BooleanProperty>(PropertyNames.JustF).Value;
                this.randomSeed = (byte)newToken.GetProperty<Int32Property>(PropertyNames.ReSeed).Value;
    
                if (destSurface == null)
                {
                    destSurface = new Surface(dstArgs.Surface.Width, dstArgs.Surface.Height);
                }
    
                Rectangle selection = this.EnvironmentParameters.GetSelection(srcArgs.Surface.Bounds).GetBoundsInt();
    
                this.Render(destSurface, srcArgs.Surface, selection); // clip the rendering to the selection.
    
                base.OnSetRenderInfo(newToken, dstArgs, srcArgs);
            }
    
    
            protected override void OnCustomizeConfigUIWindowProperties(PropertyCollection props)
            {
                // Change the effect's window title
                props[ControlInfoPropertyNames.WindowTitle].Value = "Fur Blur                           Aug 2013   Red Ochre/Null54";
                base.OnCustomizeConfigUIWindowProperties(props);
            }
    
            protected override unsafe void OnRender(Rectangle[] rois, int startIndex, int length)
            {
                if (length == 0) return;
    
                DstArgs.Surface.CopySurface(destSurface, rois, startIndex, length);
            }
    
            #region User Entered Code
            /* =================================================== */
            /* Furblur    */
            /* Name    */
            /* (c) 2013 Red Ochre     */
            /* comment   */
            /* Description:random trail/blur */
            /*     */
            /* ========================================== ======== */
    
            // Name: Furblur
            // Author: Red ochre (John Robbins)
            // Submenu: Blur
            // URL: http://www.getpaint.net/redirect/plugins.html
            // Title:Fur Blur                           Aug 2013 Red Ochre/Null54
    
    
            #region UICode
            bool startColour = false; // [1] Start colour|Src (original)| Dst ( fur on fur )
            double repCount = 10; // [0,100] Repetitions
            int maxLength = 20; // [1,200] Maximum length
            double lengthVariation = 0; // [0,1] Length variations
            double mainAngle = 45; // [-180,180] Main angle
            bool biDirectional = true; // [0,1] Both directions
            double angleVariation = 0; // [0,1] Angle variation
            bool curtype = true; // [0,1] Curve type
            double curvature = 0; // [0,1] Curl curvature
            double curvVari = 0; //[0,1] Curl variation
            double frizz = 0; // [0,1] Frizz curvature
            int startOnObject = 250; // [0,1] Start on object only
            double blurAmount = 0; // [0,1] Blur......................................................................Trail
            bool coltype = true; //[0,1] simple mix|along fur
            double colmix = 0; // [0,1] Src Color............................................... Primary Color
            bool quality = true; // [1] Quality|4 pixel Anti-alias (smoother)| 1 pixel (only slightly faster)
            bool justF = false; // [0,1] Only keep fur (src Start colour only)
            byte randomSeed = 0; // [255] Reseed
            #endregion
            void Render(Surface dest, Surface src, Rectangle rect)
            {
                dest.CopySurface(src, rect.Location, rect);// copy surface quicker than looping through
                if (justF) { ColorBgra klear = ColorBgra.Transparent; dest.Clear(klear); startColour = false; }//keep only blur/trail
    
                int H = rect.Bottom - rect.Top;
                int W = rect.Right - rect.Left;
                int N = (int)((repCount * W * H) / (100));
                int Lmain = maxLength;
                double Lvari = lengthVariation;
                double PI = Math.PI;
                double Amain = (mainAngle + 360) * 17.45329252;// add 360 so that angle can vary less than 0 (360) easier for random min & max
                // now in radians - note (PI * 1000)/180 = 17.453292519943295769236907684886
                bool Bidi = biDirectional;
                double Avar = angleVariation;
                bool Ctype = curtype;
                double Curve = curvature / 5;
                int CVari = (int)(curvVari * 1000);
                double Frizz = frizz / 50;
                int Athresh = startOnObject;
                double BlurV = 1 - blurAmount;
                double PriRat = colmix;
                double invPriRat = 1 - PriRat;
                bool Qual = quality;
    
    
                if (RandomNumber == null)
                {
                    RandomNumber = new Random(instanceSeed ^ (randomSeed << 16) ^ (rect.X << 8) ^ rect.Y);
                }
    
                ColorBgra PrimC = base.EnvironmentParameters.PrimaryColor;
    
    
                ColorBgra LT, RT, LB, RB, stLT, stRT, stLB, stRB;
                int nB = 0; int nG = 0; int nR = 0; int nA = 255;// just to set a value
                int AngMax = (int)(Amain * (1 + Avar));
                int AngMin = (int)(Amain * (1 - Avar));// radians times 1000 for randoms
                double Angle = AngMax;//moved these out of loop
                int Lmax = Lmain + (int)(Lmain * Lvari);
                int Lmin = Lmain - (int)(Lmain * Lvari);
                int L = Lmax;//and these
                int CurMin = (int)(Curve * (1 - curvVari) * 1000);// times 1000 to use randoms
                int CurMax = (int)(Curve * (1 + curvVari) * 1000);
    
                for (int n = 0; n < N; n++)//number of 'stabs' at random locations
                {
                    double Randx = RandomNumber.Next(rect.Left, rect.Right - 1); int Randxi = (int)(Randx);
                    double Randy = RandomNumber.Next(rect.Top, rect.Bottom - 1); int Randyi = (int)(Randy);
                    // note: start position to allow for 4 pixel square, so Randx < Right - 1 , Randy < Top -1
    
                    if (Lmin < Lmax) { L = (int)RandomNumber.Next(Lmin, Lmax); }//Length of line
    
                    //for RANDOMS - protection - Min MUST be less than Max or out of bounds exception
    
                    if (AngMin < AngMax) { Angle = (double)(RandomNumber.Next(AngMin, AngMax)); }//Angle of line (rads * 1000 still)
                    if (Avar == 0) { Angle = AngMax; }//bodge for odd unsolved bug when Avar = 0?????? - works!
                    Angle = Angle / 1000;// back in radians
    
                    int AngDir = RandomNumber.Next(0, 2);//Angle direction random 0 or 1
                    if (Bidi && AngDir >= 1) { Angle += PI; }//randomly reverse angle 
                    int CurDir = (int)RandomNumber.Next(0, 2);//Curve direction random 0 or 1
                    if (CurMin < CurMax) { Curve = (double)(RandomNumber.Next(CurMin, CurMax) / 1000.0); }//divide by 1000 to get back to value range
                    Curve = Curve - (Curve * CurDir * 2);//easier to read - randomly changes curve direction
    
    
                    // need to know start alpha later
                    stLT = src.GetPointUnchecked(Randxi, Randyi);
                    stRT = src.GetPointUnchecked(Randxi + 1, Randyi);
                    stLB = src.GetPointUnchecked(Randxi, Randyi + 1);
                    stRB = src.GetPointUnchecked(Randxi + 1, Randyi + 1);
                    int startA = (stLT.A + stRT.A + stLB.A + stRB.A) / 4;
    
    
                    if (!startColour)
                    {
                        nB = (int)((stLT.B + stRT.B + stLB.B + stRB. / 4);
                        nG = (int)((stLT.G + stRT.G + stLB.G + stRB.G) / 4);
                        nR = (int)((stLT.R + stRT.R + stLB.R + stRB.R) / 4);
                        nA = (int)((stLT.A + stRT.A + stLB.A + stRB.A) / 4);
                    }
    
                    else if (startColour)
                    {
                        stLT = dest.GetPointUnchecked(Randxi, Randyi);
                        stRT = dest.GetPointUnchecked(Randxi + 1, Randyi);
                        stLB = dest.GetPointUnchecked(Randxi, Randyi + 1);
                        stRB = dest.GetPointUnchecked(Randxi + 1, Randyi + 1);
                        nB = (stLT.B + stRT.B + stLB.B + stRB. / 4;
                        nG = (stLT.G + stRT.G + stLB.G + stRB.G) / 4;
                        nR = (stLT.R + stRT.R + stLB.R + stRB.R) / 4;
                        nA = (stLT.A + stRT.A + stLB.A + stRB.A) / 4;
                    }
    
                    if (!coltype)// original Primary color blending see innner loop for along the fur
                    {
                        nB = (int)((nB * invPriRat) + (PrimC.B * PriRat));//mix src or dest colour with Primary Color
                        nG = (int)((nG * invPriRat) + (PrimC.G * PriRat));
                        nR = (int)((nR * invPriRat) + (PrimC.R * PriRat));
                        nA = (int)((nA * invPriRat) + (PrimC.A * PriRat));//potentially transparent fur!
                    }
    
                    double oldx = Randx; double oldy = Randy;
    
                    for (int l = 1; l < L; l++)// distance to loop out from that random location
                    {
                        if (frizz != 0)// don't calculate if not needed - slow as within inner loop
                        {
                            double frangle = Angle;
                            int frizmin = (int)((Angle - (Angle * Frizz)) * 1000); int frizmax = (int)((Angle + (Angle * Frizz)) * 1000);
                            if (frizmin < frizmax) { frangle = (double)(RandomNumber.Next(frizmin, frizmax)) / 1000; }
                            int Lfra = (int)((1 - frizz) * L);
                            int frazz = RandomNumber.Next(0, Lfra);//added to increase frizz
                            if (frazz < l) { Angle = frangle; }
                        }
    
                        double Cang = Math.Cos(Angle); double Sang = -Math.Sin(Angle);
    
                        double Nx = Randx + (l * Cang); int Lxi = (int)(Nx); int Rxi = Lxi + 1;//this is angle from start
                        double Ny = Randy + (l * Sang); int Tyi = (int)(Ny); int Byi = Tyi + 1;
                        if (curtype)
                        {
                            Nx = oldx + (Cang); Lxi = (int)(Nx); Rxi = Lxi + 1;//this is angle from last point
                            Ny = oldy + (Sang); Tyi = (int)(Ny); Byi = Tyi + 1;
                        }// CIRCLES! - no gaps either
    
                        //start position is within bounds, however the loop may take it out of bounds!
                        // therefore protection required or use get sample clamped?
    
                        if (Lxi > rect.Left && Rxi < rect.Right && Tyi > rect.Top && Byi < rect.Bottom)
                        {
    
                            double blur = (double)(L - (l * BlurV)) / (double)(L);//BlurV is less than 1 so blur is too
                            double iblur = 1 - blur;
                            double colblur = (double)(L - l) / (double)(L); double icolblur = 1 - colblur;
                            if (coltype)//colour along the fur
                            {
                                nB = (int)((nB * colblur) + (((PrimC.B * PriRat) + (nB * invPriRat)) * icolblur));//add primary color along fur
                                nG = (int)((nG * colblur) + (((PrimC.G * PriRat) + (nG * invPriRat)) * icolblur));
                                nR = (int)((nR * colblur) + (((PrimC.R * PriRat) + (nR * invPriRat)) * icolblur));
                                nA = (int)((nA * colblur) + (((PrimC.A * PriRat) + (nA * invPriRat)) * icolblur));//potentially transparent fur!
                            }
    
    
                            //4 pixel AA
                            //if (Qual && (!Obtest || startA > Athresh))// assume objects have alpha greater than 250 or object-edge pixels trail transparency across object
                            if (Qual && startA >= Athresh)
                            {
                                LT = dest.GetPointUnchecked(Lxi, Tyi); int Blt = LT.B; int Glt = LT.G; int Rlt = LT.R; int Alt = LT.A;
                                if (LT.A <= Athresh) { Blt = nB; Glt = nG; Rlt = nR; }// to stop it blending colour with clear (white)
                                RT = dest.GetPointUnchecked(Rxi, Tyi); int Brt = RT.B; int Grt = RT.G; int Rrt = RT.R; int Art = RT.A;
                                if (RT.A <= Athresh) { Brt = nB; Grt = nG; Rrt = nR; }
                                LB = dest.GetPointUnchecked(Lxi, Byi); int Blb = LB.B; int Glb = LB.G; int Rlb = LB.R; int Alb = LB.A;
                                if (LB.A <= Athresh) { Blb = nB; Glb = nG; Rlb = nR; }
                                RB = dest.GetPointUnchecked(Rxi, Byi); int Brb = RB.B; int Grb = RB.G; int Rrb = RB.R; int Arb = RB.A;
                                if (RB.A <= Athresh) { Brb = nB; Grb = nG; Rrb = nR; }
    
                                double Nxd = Nx - Lxi; double iNxd = 1 - Nxd;
                                double Nyd = Ny - Tyi; double iNyd = 1 - Nyd;
    
                                // interesting - I think my previous calculations were correct but too complex?
                                // worked for 3 pixels then colours went strange with 4 pixels 
                                // hence the long winded version below
    
                                //left top 
                                double Blt1 = (nB * blur) + (Blt * iblur); double Blt2 = (Blt1 * iNxd) + (Blt * Nxd);
                                double Blt3 = (Blt2 * iNyd) + (Blt * Nyd); int nBlt = (int)(Blt3);
                                double Glt1 = (nG * blur) + (Glt * iblur); double Glt2 = (Glt1 * iNxd) + (Glt * Nxd);
                                double Glt3 = (Glt2 * iNyd) + (Glt * Nyd); int nGlt = (int)(Glt3);
                                double Rlt1 = (nR * blur) + (Rlt * iblur); double Rlt2 = (Rlt1 * iNxd) + (Rlt * Nxd);
                                double Rlt3 = (Rlt2 * iNyd) + (Rlt * Nyd); int nRlt = (int)(Rlt3);
                                double Alt1 = (nA * blur) + (Alt * iblur); double Alt2 = (Alt1 * iNxd) + (Alt * Nxd);
                                double Alt3 = (Alt2 * iNyd) + (Alt * Nyd); int nAlt = (int)(Alt3);
                                LT = ColorBgra.FromBgra(Int32Util.ClampToByte(nBlt), Int32Util.ClampToByte(nGlt), Int32Util.ClampToByte(nRlt), Int32Util.ClampToByte(nAlt));
                                dest[Lxi, Tyi] = LT;
                                //right top 
                                double Brt1 = (nB * blur) + (Brt * iblur); double Brt2 = (Brt1 * Nxd) + (Brt * iNxd);
                                double Brt3 = (Brt2 * iNyd) + (Brt * Nyd); int nBrt = (int)(Brt3);
                                double Grt1 = (nG * blur) + (Grt * iblur); double Grt2 = (Grt1 * Nxd) + (Grt * iNxd);
                                double Grt3 = (Grt2 * iNyd) + (Grt * Nyd); int nGrt = (int)(Grt3);
                                double Rrt1 = (nR * blur) + (Rrt * iblur); double Rrt2 = (Rrt1 * Nxd) + (Rrt * iNxd);
                                double Rrt3 = (Rrt2 * iNyd) + (Rrt * Nyd); int nRrt = (int)(Rrt3);
                                double Art1 = (nA * blur) + (Art * iblur); double Art2 = (Art1 * Nxd) + (Art * iNxd);
                                double Art3 = (Art2 * iNyd) + (Art * Nyd); int nArt = (int)(Art3);
                                RT = ColorBgra.FromBgra(Int32Util.ClampToByte(nBrt), Int32Util.ClampToByte(nGrt), Int32Util.ClampToByte(nRrt), Int32Util.ClampToByte(nArt));
                                dest[Rxi, Tyi] = RT;
                                //left bottom 
                                double Blb1 = (nB * blur) + (Blb * iblur); double Blb2 = (Blb1 * iNxd) + (Blb * Nxd);
                                double Blb3 = (Blb2 * Nyd) + (Blb * iNyd); int nBlb = (int)(Blb3);
                                double Glb1 = (nG * blur) + (Glb * iblur); double Glb2 = (Glb1 * iNxd) + (Glb * Nxd);
                                double Glb3 = (Glb2 * Nyd) + (Glb * iNyd); int nGlb = (int)(Glb3);
                                double Rlb1 = (nR * blur) + (Rlb * iblur); double Rlb2 = (Rlb1 * iNxd) + (Rlb * Nxd);
                                double Rlb3 = (Rlb2 * Nyd) + (Rlb * iNyd); int nRlb = (int)(Rlb3);
                                double Alb1 = (nA * blur) + (Alb * iblur); double Alb2 = (Alb1 * iNxd) + (Alb * Nxd);
                                double Alb3 = (Alb2 * Nyd) + (Alb * iNyd); int nAlb = (int)(Alb3);
                                LB = ColorBgra.FromBgra(Int32Util.ClampToByte(nBlb), Int32Util.ClampToByte(nGlb), Int32Util.ClampToByte(nRlb), Int32Util.ClampToByte(nAlb));
                                dest[Lxi, Byi] = LB;
                                //right bottom 
                                double Brb1 = (nB * blur) + (Brb * iblur); double Brb2 = (Brb1 * Nxd) + (Brb * iNxd);
                                double Brb3 = (Brb2 * Nyd) + (Brb * iNyd); int nBrb = (int)(Brb3);
                                double Grb1 = (nG * blur) + (Grb * iblur); double Grb2 = (Grb1 * Nxd) + (Grb * iNxd);
                                double Grb3 = (Grb2 * Nyd) + (Grb * iNyd); int nGrb = (int)(Grb3);
                                double Rrb1 = (nR * blur) + (Rrb * iblur); double Rrb2 = (Rrb1 * Nxd) + (Rrb * iNxd);
                                double Rrb3 = (Rrb2 * Nyd) + (Rrb * iNyd); int nRrb = (int)(Rrb3);
                                double Arb1 = (nA * blur) + (Arb * iblur); double Arb2 = (Arb1 * Nxd) + (Arb * iNxd);
                                double Arb3 = (Arb2 * Nyd) + (Arb * iNyd); int nArb = (int)(Arb3);
                                RB = ColorBgra.FromBgra(Int32Util.ClampToByte(nBrb), Int32Util.ClampToByte(nGrb), Int32Util.ClampToByte(nRrb), Int32Util.ClampToByte(nArb));
                                dest[Rxi, Byi] = RB;
    
    
                            }
                            //single pixel
                            //if (!Qual && (!Obtest || startA > Athresh))// assume objects have alpha greater than 250 or object-edge pixels trail transparency across object
                            if (!Qual && startA >= Athresh)
                            {
                                LT = dest.GetPointUnchecked(Lxi, Tyi); int Blt = LT.B; int Glt = LT.G; int Rlt = LT.R; int Alt = LT.A;
                                if (LT.A <= Athresh) { Blt = nB; Glt = nG; Rlt = nR; }// to stop it blending colour with clear (white)
                                int nBlt = (int)((nB * blur) + (Blt * iblur));
                                int nGlt = (int)((nG * blur) + (Glt * iblur));
                                int nRlt = (int)((nR * blur) + (Rlt * iblur));
                                int nAlt = (int)((nA * blur) + (Alt * iblur));
                                LT = ColorBgra.FromBgra(Int32Util.ClampToByte(nBlt), Int32Util.ClampToByte(nGlt), Int32Util.ClampToByte(nRlt), Int32Util.ClampToByte(nAlt));
                                dest[Lxi, Tyi] = LT;
                            }
                            oldx = Nx; oldy = Ny;// new point becomes old point for next l
                            Angle = Angle + Curve;
                        }
                    }
                }
            }
    
            #endregion
        }
    }
    
    • Upvote 1
  12. 36RLiyX.png

    I see you are all coming up with good uses for this! Thanks for the encouragement and enthusiasm.

    Cool image Drew.

    Love the ZZtop one Sasha - I think the drummer is called Frank Beard too!

    TR - Grass effects are definitely one of the uses I had in mind for this one.

    I'm still working on this one - the 'beta' above will crash occassionally (sorry) - so, if testing, always save everything before running it. Thanks Welshy and Doughty for testing.

    Hopefully I will get a better (stable) version finished soon.

    Cheers all

    (just seen Doughty's American gothic - subtle but funny! - good work)

    Sorry Mottoman - Only just seen yours too - good work - I think we should have a bearded lady comp once this plugin is finished!

    A few of my tests:

    http://i.imgur.com/CYZtKT3.png">http://i.imgur.com/CYZtKT3.png http://i.imgur.com/nMuAbk5.jpg">http://i.imgur.com/nMuAbk5.jpg

  13. Hi Welshy,

     

    Thanks for reporting that - It happened to me just now - I think I've fixed it (hopefully) - It uses a lot of random numbers between a maximum and minimum, and somewhere the minimum was larger than the max - computer says no!

     

    Also working on varying the amount of curvature randomly and blending in the Primary Color in a more interesting way + some other ideas.

     

    Nice pic!

     

    Have got some good results just running it on a 20pix paintbrush line (on transparent layer) with 'Only keep fur' checked.

     

    @ Null54 - thanks for that tip - I may be changing some of the controls - will bear this in mind.

     

    @ EER - thanks!

     

    @ Pdnnoob - monsters are great!

×
×
  • Create New...