The most common type of extension is an effect or an adjustment. Although the difference between the two is quite arbitrary, the general rule is that an adjustment is designed to tweak an image (like colors or contrast), while an effect commonly provides a more dramatic change (like blurs or embossing). It is recommended that most extensions be an effect unless there is a compelling reason to make it an adjustment. For the rest of this guide, we'll use the word effect, but the same applies if you are writing an adjustment.
Like extensions in general, the design of Pinta endeavors to make writing an effect as simple as possible.
Step 1 - The Basics
This guide assumes you have created a skeleton extension as described in
Getting Started Writing an Extension, and will simply add to that.
All effects inherit from Pinta.Core.BaseEffect, so let's create a new class that inherits from BaseEffect, and have our IDE implement the required methods for us.
class MyEffect : Pinta.Core.BaseEffect
{
public override string Name
{
get { throw new NotImplementedException (); }
}
}As you can see, there is only one required method to implement, you must provide the Name of your extension. Let's add that.
public override string Name
{
get { return "My First Effect"; }
}Step 2 - Doing Something Interesting
Even though we've written all the
required code for an effect, we haven't written any
interesting code yet, so our effect doesn't do anything interesting. For this simple sample, we are going to write an effect that removes the color blue from the image. The interesting work takes place in one of the Render methods.
Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle roi)
Render (ColorBgra* src, ColorBgra* dst, int length)
Render (ColorBgra color)
These allow you to work at different levels depending on your needs. In order, you can work on all rectangles of interest ("roi"), individual rectangles of interest, a single line, or a single pixel. Note that you only want to override one of these, and you do not want to call the base method, or else it will chain down to the more granular levels.
For our sample, we are simply going to remove the blue component from each pixel. Therefore, we only need to work at the pixel level. Here is the code we need:
protected override ColorBgra Render (ColorBgra color)
{
color.B = 0;
return color;
}With this method, we are given the color of the source pixel and we need to return the color that we want the destination pixel to be. In our case, we take the source pixel, set the blue component to zero, and return it as our new color. That's it!
Step 3 - Registering the Effect
We've now written our effect, and we have our extension skeleton code so Pinta loads our extension, but we still need to tell Pinta about our effect. To do this, go back to the IExtension class and inform Pinta about your effect in Initialize using PintaCore.Effects.RegisterEffect. It's also good practice to clean up after yourself in case your extension is uninitialized.
private MyEffect my_effect;
public void Initialize ()
{
my_effect = new MyEffect ();
PintaCore.Effects.RegisterEffect (my_effect);
}
public void Uninitialize ()
{
PintaCore.Effects.UnregisterEffect (my_effect);
}Note: If you are writing an adjustment instead of an effect, you can call PintaCore.Effects.RegisterAdjustment.
Step 4 - Testing it Out
Compile your extension, place it where Pinta can find it, and run Pinta. Your effect should show up in the Effects->General menu.
Run it on your favorite image to see the results!
You will note that all you had to do was specify the algorithm that your effect uses and Pinta handled the rest. It handled all the painting and even added your action to the history pad so the user can undo the effect, without any additional code written by you. If the user had an area selected, only those pixels were passed to your effect.
In fact, if you have multiple CPUs or multiple cores, Pinta even broke the task up in to multiple threads and ran each one on a different core!
Conclusion
With just a few lines of code, we've been able to write a very simple effect. Of course, real effects can be much more complicated. In the following tutorials, we'll expand this effect with more features.