Jump to content

Emulating the curves effect

Recommended Posts

Search the Paint.NET source for "curves" and you'll find the following:

namespace PaintDotNet.Effects
   public sealed class CurvesEffect
       : Effect

I don't know why it isn't visible through intellisense though

Link to post
Share on other sites

OK, I think I understand how to automate non-IndirectUI plugins - but I have another question specifically about Curves. The config token has an array called "ControlPoints" with several collection objects for the points inside - am I right that the items of that array are for each channel?

Link to post
Share on other sites

Simon, I guess you are following Tom Jackson's "How to start a fire" tutorial.

In this case I suggest you to use linear transformation instead of curves. That is just few lines of code, easy to handle and basically same result.

Here is a codelab code that imitates linear "curve" with middle control points located as:

Red: 0, 0

Green: 150, 0

Blue: 215, 0

// Author: Tanel Rüütli
int Amount1=0; //[0,255]Red Control Point
int Amount2=150; //[0,255]Green Control Point
int Amount3=215; //[0,255]Blue Control Point

void Render(Surface dst, Surface src, Rectangle rect)
   Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();

   ColorBgra CurrentPixel;
   for(int y = rect.Top; y < rect.Bottom; y++)
       for (int x = rect.Left; x < rect.Right; x++)
           CurrentPixel = src[x,y];

// initial rgb values that you have after clouds effect
byte r = (byte)CurrentPixel.R;
byte g = (byte)CurrentPixel.G;
byte b = (byte)CurrentPixel.B;
byte a = (byte)CurrentPixel.A;

// Return multipliers from our "Control Point" values
double rx = 255 / (255 - Amount1 + 0.01);  // there is + 0.01 to avoid divide-by-zero exception when Amount is 255
double gx = 255 / (255 - Amount2 + 0.01);  // there is + 0.01 to avoid divide-by-zero exception when Amount is 255
double bx = 255 / (255 - Amount3 + 0.01);  // there is + 0.01 to avoid divide-by-zero exception when Amount is 255

// Calculate new rgb values
double r1 = 255 - rx * (double)(255 - r);
double g1 = 255 - gx * (double)(255 - g);
double b1 = 255 - bx * (double)(255 - ;

// Final RGBA
CurrentPixel.R = Utility.ClampToByte(r1);
CurrentPixel.G = Utility.ClampToByte(g1);
CurrentPixel.B = Utility.ClampToByte(b1);
CurrentPixel.A = a;

           dst[x,y] = CurrentPixel;

You can test it on the gray fire image from Tom's tutorial.

Effectively my code does the same as applying following curves setup (I used Curves+ for this example, because it allows "straight curves"):


If you tie the above Amount1, Amount2 and Amount3 with your plugin controls, or even better, a color wheel control (through opposite RGB values)* then user can easily change color of fire.

* Edit:

by "opposite RGB values" I mean Amount1=255-ColorWheel.R; Amount2=255-ColorWheel.G; Amount3=255-ColorWheel.B;

this way the color of fire turns to same range as the selection in ColorWheel.

Link to post
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.

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