Jump to content

Help with Stripe Plugin


Pratyush
 Share

Recommended Posts

55 minutes ago, toe_head2001 said:

@Pratyush, the Math.Sin() and Math.Cos() trigonometric functions use radians rather than degrees, so don't forget to do conversions if needs be.

 

A little help on this.....

 

Write yourself a couple of helper functions to do the conversions

 

public double DegreeToRadians(double angle)
    {
        return (Math.PI / 180) * angle;
    }

 

private double RadianToDegrees(double angle)
{
   return angle * (180.0 / Math.PI);
}

 

You can call these from your code like this...

double angle = Math.Cos(DegreeToRadians(45));

 

 

 

 

Link to comment
Share on other sites

@Pratyush you've written your plugin in a very strange way.  I'm not sure about your looping structure... and basing your calculations on the size of the rectangle sent into the Render function...

 

Anyway, I've written a well behaved version of your plugin.  Use it if you like.

 

<snip>

 

It will render your gradient to any angle and it respects the current selection.  Plus, it is super fast (that is, the UI is very responsive).  It will also repeat the pattern if you pull the nubs [+] in from the edges.

 

Enjoy. :beer: :D 

 

  • Like 2
  • Upvote 1

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

Link to comment
Share on other sites

6 hours ago, Pratyush said:

what's return type of this function?

 

Both Math.Sin and Math.Cos return a double.

 

Edit: I did not see that @toe_head2001 answered the question on the second page.

Edited by null54

PdnSig.png

Plugin Pack | PSFilterPdn | Content Aware Fill | G'MICPaint Shop Pro Filetype | RAW Filetype | WebP Filetype

The small increase in performance you get coding in C++ over C# is hardly enough to offset the headache of coding in the C++ language. ~BoltBait

 

Link to comment
Share on other sites

On 1/24/2018 at 4:32 AM, BoltBait said:

Use it if you like.

Posterize is not giving desired result.

Thanks everyone for suggestion. I will use x^2(3-2x) which gives very good approximation of sin(pi x\2)^2 for the range [0,1]

ZsqzRSP.png

 

Edited by Pratyush

Rl7un0O.png

Link to comment
Share on other sites

22 hours ago, Pratyush said:

Posterize is not giving desired result.

 

I agree... which is why I just rewrote the Posterize part.  Now the colors are correct:

// Name: Gradual Stripes
// Submenu: Render
// Author: BoltBait & Pratyush
// Title: Gradual Stripes
// Version: 2.0
// Desc: Draws stripes with gradual change in shades
// Keywords: Stripes|Grayscale|Lines
#region UICode
PanSliderControl Amount1 = Pair.Create(-1.0,0.0); // Starting Point
ColorWheelControl Amount2 = ColorBgra.FromBgr(0,0,0); // [Black]
PanSliderControl Amount3 = Pair.Create(1.0,0.0); // Ending Point
ColorWheelControl Amount4 = ColorBgra.FromBgr(255,255,255); // [White]
IntSliderControl Amount5=16; // [2,64] Bands
#endregion

Surface wrk = null;
Color[] palette = new Color[64];

protected override void OnDispose(bool disposing)
{
    if (wrk != null) wrk.Dispose();
    wrk = null;
    base.OnDispose(disposing);
}

Color FindNearestColor(Color color, Color[] palette, int palSize)
{
    int minDistanceSquared = 255 * 255 + 255 * 255 + 255 * 255 + 1;
    byte bestIndex = 0;
    for (byte i = 0; i < palSize; i++)
    {
        int Rdiff = color.R - palette[i].R;
        int Gdiff = color.G - palette[i].G;
        int Bdiff = color.B - palette[i].B;
        int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff;
        if (distanceSquared < minDistanceSquared)
        {
            minDistanceSquared = distanceSquared;
            bestIndex = i;
            if (minDistanceSquared < 1) break;
        }
    }
    if (bestIndex == 0) return Amount2;
    if (bestIndex == palSize-1) return Amount4;
    return palette[bestIndex];
}

void PreRender(Surface dst, Surface src)
{
    if (wrk == null) wrk = new Surface(src.Size);
    int sw = (Amount5 + 1) * 2;
    Bitmap swatch = new Bitmap(sw,1);
    using (LinearGradientBrush Brush1 = new LinearGradientBrush(new Point(0,0),new Point(sw-2,0), Amount2, Amount4))
    {
        using (Graphics g = Graphics.FromImage(swatch))
        {
            g.FillRectangle(Brush1,0,0,sw,1);
        }
    }
    for (int i = 0; i < Amount5; i++)
    {
        palette[i] = swatch.GetPixel(i*2+1,0);
    }
    Rectangle selection = EnvironmentParameters.GetSelection(wrk.Bounds).GetBoundsInt();
    int width = selection.Right - selection.Left;
    int height = selection.Bottom - selection.Top;
    int x1 = (int)Math.Round(((Amount1.First + 1) / 2) * width) + selection.Left;
    int y1 = (int)Math.Round(((Amount1.Second + 1) / 2) * height) + selection.Top;
    int x2 = (int)Math.Round(((Amount3.First + 1) / 2) * width) + selection.Left;
    int y2 = (int)Math.Round(((Amount3.Second + 1) / 2) * height) + selection.Top;
    Point p1 = new Point(x1,y1);
    Point p2 = new Point(x2,y2);
    if (!p1.Equals(p2))
    {
        using (LinearGradientBrush Brush1 = new LinearGradientBrush(p1,p2, Amount2, Amount4))
        {
            using (Graphics g = new RenderArgs(wrk).Graphics)
            {
                g.FillRectangle(Brush1,selection.Left,selection.Top,width,height);
            }
        }
    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            if (IsCancelRequested) return;
            ColorBgra CurrentPixel = wrk[x,y];
            CurrentPixel = FindNearestColor(CurrentPixel, palette, Amount5);
            dst[x,y] = CurrentPixel;
        }
    }
}

EDIT: I just rewrote it again.  Now the stripes are the correct number and size.

  • Like 1
  • Upvote 1

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

Link to comment
Share on other sites

1 hour ago, BoltBait said:

int minDistanceSquared = 255 * 255 + 255 * 255 + 255 * 255 + 1;

This makes sense to understand the code, but these calculations are done for each pixels...


Can I suggest this change to save some cpu?

int minDistanceSquared = 999999; // high value greater than 255 * 255 + 255 * 255 + 255 * 255 + 1; 

 

Link to comment
Share on other sites

8 hours ago, MJW said:

the compiler would compute the constant expression

 

Yes, the compiler is smart enough to precompute the results of the constant expression.  Writing it out that way is just easier for us humans to understand what I'm doing.  It is easy to verify by using ILSpy to decompile the resulting DLL:

ILSpyResults.png

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

Link to comment
Share on other sites

10 minutes ago, Pratyush said:

How to typecast double to int?

 

Like this:

 

int MyInt = (int)MyDouble;

You can see examples of this in the code I posted above.  Look at the PreRender function where I'm calling some Math functions.

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

Link to comment
Share on other sites

4 hours ago, BoltBait said:

Writing it out that way is just easier for us humans to understand what I'm doing.

 

That's what comments are for.

 

  int minDistanceSquared = 195076; // i.e. the result of (255 * 255) * 3 + 1;

 

Link to comment
Share on other sites

One way to do that sort of thing is to use a constant variable:

const int MaxDistSqPlusOne = 3 * 255 * 255 + 1;

That way, it will be clearer what's being done when it's assigned:

	minDistanceSquared = MaxDistSqPlusOne;

Since it must evaluate to a single value, if the compiler accepts it, it's guaranteed to be computed in the compilation phase.

  • Upvote 1
Link to comment
Share on other sites

The reason for this is simple.

 

You are trying to store something into a variable defined as an integer.  So, you rightfully tried to cast your calculation to integer using "(int)" in front of it.

 

The problem is that when casting, you're casting only the next item to int.  So, you're casting k to an integer then multiplying it by n which is a double... the result of this multiplication is a double.  And, you can't store a double into an integer variable.

 

The solution, as pointed out by toe_head2001, is to put parens around k * n so that the multiplication happens first resulting in a double and then cast that double to an integer for storing into the variable.

 

You actually did it correctly on line 66.

 

Clear?

  • Like 2

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

Link to comment
Share on other sites

4 minutes ago, Pratyush said:

Hi everyone,

 

Can we do from codelab, that checking one of checkbox will uncheck or disable other UI element?

 

As long as you are using CodeLab v3.0 (or higher), you can.

 

Read this post for more info on how to do it: https://forums.getpaint.net/topic/880-codelab-v32-for-advanced-users-released-january-17-2018/?do=findComment&comment=541005

 

EDIT: ...which toe_head2001 has just quoted above this post. :D 

 

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

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.

 Share

×
×
  • Create New...