Jump to content

toe_head2001

Administrator
  • Posts

    5,029
  • Joined

  • Last visited

  • Days Won

    155

Posts posted by toe_head2001

  1. Spoked Wheel

    Effects -> Render -> Spoked Wheel

     

    ui.pngex1.png

     

    Change Log

    v1.1 (March 5, 2016)

    • Changed: The range for Line Thicknesses now maxes out at 100

    v1.0 (Feb 20, 2016)

    • Initial release

     

    Download

    SpokedWheel.zip

     

    Spoiler

    SpokedWheel.png <---- Icon

    GPL v3

    
    // Name: Spoked Wheel
    // Submenu: Render
    // Author: toe_head2001
    // Title:
    // Version: 1.1
    // Desc: Generates a Spoked Wheel
    // Keywords:
    // URL:
    // Help:
    #region UICode
    IntSliderControl Amount1 = 5; // [3,20] Spokes
    DoubleSliderControl Amount2 = 1; // [0.1,1] Wheel Size
    DoubleSliderControl Amount3 = 0.333; // [0.1,0.9] Axle Size
    IntSliderControl Amount4 = 2; // [1,100] Rim Thickness
    ListBoxControl Amount5 = 0; // Rim Style|Solid|Dashed|Dotted
    IntSliderControl Amount6 = 2; // [1,100] Spoke Thickness
    ListBoxControl Amount7 = 0; // Spoke Style|Solid|Dashed|Dotted
    IntSliderControl Amount8 = 2; // [1,100] Axle Thickness
    ListBoxControl Amount9 = 0; // Axle Style|Solid|Dashed|Dotted
    AngleControl Amount10 = 0; // [-180,180] Rotation
    ColorWheelControl Amount11 = ColorBgra.FromBgr(0,0,0); // Color
    #endregion
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
        Rectangle selection = EnvironmentParameters.SelectionBounds;
        float centerX = ((selection.Right - selection.Left) / 2f) + selection.Left;
        float centerY = ((selection.Bottom - selection.Top) / 2f) + selection.Top;
        float diameter = (float)Amount2 * Math.Min(selection.Width - 4, selection.Height - 4) - Amount4;
        float radius = diameter / 2f;
        float offsetX = centerX - radius;
        float offsetY = centerY - radius;
        float axleDiameter = (float)Amount3 * diameter;
        float axleOffsetX = centerX - axleDiameter / 2f;
        float axleOffsetY = centerY - axleDiameter / 2f;
        float start = (float)Amount10;
        float sweep = 360f / Amount1;
    
        dst.CopySurface(src, rect.Location, rect);
    
        using (Graphics wheel = new RenderArgs(dst).Graphics)
        {
            wheel.SmoothingMode = SmoothingMode.AntiAlias;
            wheel.Clip = new Region(rect);
            
            using (Pen wheelPen = new Pen(Amount11))
            {
                // Draw Rim
                wheelPen.Width = Amount4;
                wheelPen.DashStyle = getDashStyle(Amount5);
                wheel.DrawEllipse(wheelPen, offsetX, offsetY, diameter, diameter);
                
                // Draw Spokes
                wheelPen.Width = Amount6;
                wheelPen.DashStyle = getDashStyle(Amount7);
                for (int spoke = 0; spoke < Amount1; spoke++)
                {
                    float degrees = start + sweep * spoke;
                    double radians = Math.PI / 180 * degrees;
    
                    float startX = (float)(radius * Amount3 * Math.Sin(radians));
                    float startY = (float)(radius * Amount3 * Math.Cos(radians));
                    
                    float endX = (float)(radius * Math.Sin(radians));
                    float endY = (float)(radius * Math.Cos(radians));
    
                    wheel.DrawLine(wheelPen, centerX - startX, centerY - startY, centerX - endX, centerY - endY);
                }
                
                // Draw Axle
                wheelPen.Width = Amount8;
                wheelPen.DashStyle = getDashStyle(Amount9);
                wheel.DrawEllipse(wheelPen, axleOffsetX, axleOffsetY, axleDiameter, axleDiameter);
            }
        }
    }
    
    static DashStyle getDashStyle(byte style)
    {
        DashStyle dashStyle;
        switch (style)
        {
            case 0: // Solid
                dashStyle = DashStyle.Solid;
                break;
            case 1: // Dashed
                dashStyle = DashStyle.Dash;
                break;
            case 2: // Dotted
                dashStyle = DashStyle.Dot;
                break;
            default:
                dashStyle = DashStyle.Solid;
                break;
        }
        return dashStyle;
    }

     

     

    • Upvote 7
  2. Try installing gdi+ and see if that helps. Interestingly enough, I can open your image in my PDN installed in Linux under Wine. I did install gdi+ on that virtual drive.

     

    GDI+ is a component that is built into Windows; it isn't something you'd install (on Windows).

     

    I'm pretty sure the Wine implementation of GDI+ is either using Cairo or simply the X server. So you can't compare apples to oranges.

  3. Your idea would mean there wouldn't be any cut-off edges as the box wouldn't be able to go off of the canvas. For the most part, that actually sounds like a good idea, but then again, there are times where I would want some sides of the box to be purposely cut-off. Perhaps the margins can have the ability to go off of the canvas? (sorry, I don't know what's possible in coding).

    Not necessarily. There's no reason why the Margin sliders couldn't have a negative value.

     

    Also, what would give a smaller UI, panning controls, or four margin controls, or would UI size be the same either way? Maybe UI size doesn't matter too much? (I personally am fine with UIs that get a bit long, such as the curly lines UI.)

     

    UI size doesn't matter too much, but I do like to keep them short if I can. I'm more concerned with making UI as intuitive as possible.

     

    - To use a Offset/Pan control, it doesn't make sense to set a margin(s). It makes more sense to simply to set the Width and Height. It would automatically rendered to the exact center of the canvas/selection, and then you could move it around with the Offset/Pan control.  I imagine this is what most people would want.

     

    - The other way is to set the four Margins individually to an exact amount. Personally, I like this method, because I'm a nerd that that.

     

     

    I will most likely go with the Offset/Pan route, but I need to think about the ramifications of each a little more before I decide.

     

    I can offer a suggestion on how to do non-rectangular selections, though it would make the plugin considerably more complex. You could use the distance-transform idea, very similar to the way the Edge Expander works when restricted to the selection. The amount of color would depend on the distance to the edge of the selection, with values less than some distance being uncolored, then a jump to fully colored, which would then fade away. I think panning could be accomplished by adding a distance offset which depends on the XY position. One possible difficulty might be aliasing problems making boundary formed by the transition from uncolored to fully colored look ugly. Perhaps that could be reduced by adding a small transition region, so the coloring would increase rapidly but not instantly.

     

    Considering we are only with one color at a time here, I think there are easier & less complicated ways to do it.

     

    While I'm at it, I'll mention an idea I had, even though it may be a little far from the plugin's original concept. What would be useful is if the plugin could allow embossed shading, so the frame looked like it was lighted by an angled light.

     

    Can you post an image of what that might look like?

  4. Non-rectangular selections would require a rewrite of the plugin. That's not a big deal though; this plugin (or rather the actual algorithm of the plugin) is just a few lines of code. When I figure out a good way of doing non-rectangular selections, I'll release a version 2.0.

     

     

    As for the Offset, your bullet points do have merit.

    However it makes more sense, to me at least, to allow for each of the four margins to be set independently. (plus the code is already written in a way in which this can be done)  Otherwise the whole concept of the Margin breaks down.

    For example, the Margin is set to 10px, but it's offset by 30px.... so that margin is 40px and that other one is....????

     

    Would that work for you? Independent sliders of each margin?

    It could also have a checkbox that allows all four to be linked, like it is now.

  5. 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);
    }
    
  6. Is it would be neat if the plugin had the ability to move or shift the shadow around, like what the "off set" controls do in the drop shadow plugin or like the pan controls in other plugins.

     

    You can already do this by making a selection before running the plugin. I know it's not the same, but it should work none-the-less.

     

    If you still think you need Offset controls, feel free to convince me.

  7. Version 1.1 posted.

    - Added a Opacity slider for @Cc4FuzzyHuggles.

    - The maximum value Margin slider is no longer hard coded to 100. (100 was to high for small images, and too low for large images). It is now set dynamically based on canvas/selection size.

     

    Thank you, toe head. This is a nice compliment to MadJik's Frames.

    IMO, it fits better under Effects -> Render (like Madjik's).

    Would you consider combining the two into one?

    If Vignette can be in the Photos menu, why not this? That was my thinking anyways.

    Technically speaking, this is not frame. It's literally an inset box shadow (as seen in CSS), with an optional margin.

    I'm not interesting in combining the functionality of the two plugins. However, my source code is under a Free Software license, so anyone that wants to use it, has the freedom to do so.

    • Upvote 3
×
×
  • Create New...