Sign in to follow this  
ReMake

CodeLab - First Steps (Sponge)

Recommended Posts

Among Photoshop filters there is a filter, that named the Sponge. Below is the result of work of this filter and fragment of its interface.

Sponge_PS.png

 

Whether it is possible to create similar effect for Paint.NET? Yes, of course.

So, step by step.

 

Step 1. Open any image. Add a new layer.

 

Step 2. Apply to layer the Cloud's effect with the following parameters: Scale - 24, Roughness - 0,40.

 

Step 3. In the menu Adjustments run effect Curves (Adjustments -> Curves). Drag the left bottom point of a curve to the right to the middle and set its values to (127,0). Drag the right top point of a curve to the left to the middle and set its values to (128,255).

Curves_en.png

 

Step 4. Apply the Eliminate Dark/Light effect for elimination of light areas of the image.

 

Step 5. Select Layer Properties from the menu Layers. Select the Multiply or Darken blend mode in the opened dialog window and set Opacity of a layer to 25...30.

 

Below is the result:

Sponge_PDN.png

 

Compare with the previous picture. It seems to me they are similar. Try to repeat the previous actions with different parameters for Scale and Roughness of the Cloud's effect and Opacity of a layer.

 

Now let's create our effect. Start CodeLab (Effects-> Advanced-> CodeLab). Choose New in the menu File. In a dialogue box Script Editor click a No button. The dialogue window the New Source (Template) will be presented to you. In the drop-down list choose Clouds and in the drop-down list Blend choose Multiply or Darken. Click the Generate Code button. We will receive the following script of effect:

#region UICode
int Amount1 = 250; // [2,1000] Scale
double Amount2 = 0.5; // [0,1] Roughness
BinaryPixelOp Amount3 = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Normal); // Blend Mode
byte Amount4 = 0; // [255] Reseed
#endregion

// Setup for calling the Render Clouds effect
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Setup for using Multiply blend op
private BinaryPixelOp multiplyOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Multiply);

// Here is the main render loop function
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Call the Render Clouds function
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.BlendMode, Amount3);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, (int)Amount4);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Call the Clouds function using Black and White
    cloudsEffect.Render(new Rectangle[1] {rect},0,1);

    // Now in the main render loop, the dst canvas has a render of clouds
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            // TODO: Add additional pixel processing code here

            CurrentPixel = multiplyOp.Apply(src[x,y], CurrentPixel);


            dst[x,y] = CurrentPixel;
        }
    }
}

Open the designer interface (File -> User Interface Designer), select in it the Scale control and rename it to Brush Size. Set the maximum value to 100, set the default value to 25. Click the Update button. Select the second control, set the minimum value to 0, the maximum value to 10 and the default value to 0. Select Integer Slideri in the Contrl type box. Click the Update button. Remove the third and fourth controls - we don't need them. Click button Ok.

 

Comment out or delete the following line:

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.BlendOp, Amount3);

it isn't need to us any more.

In the line

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, (int)Amount4);

write 255 instead of (int) Amount4.

 

Since we changed the type of the variable Amount2, we will have to make a change in the next line:

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2);

replacing Amount2 to Amount2/10.0

 

Save our script with the Sponge_1 name (File -> Save...) and create a DLL file with the same name (File-> Save as DLL...). Check how your effect works. So, we reproduced a Step 2 which is described above.

 

Now let's create an analogue of Step 3. We need the variables R, G, B, and A. Let's add them in our script:

 CurrentPixel = dst[x,y];
 int R = CurrentPixel.R;
 int G = CurrentPixel.G;
 int B = CurrentPixel.B;
 int A = CurrentPixel.A;

The values of all color components that are less than 128, set to 0, the values greater than or equal to 128, set to 255.

// Convert to black and white contrast image
        if (R<128) {R=0;} 
        else R=255; 
        if (G<128) {G=0;} 
        else G=255; 
        if (B<128) {B=0;} 
        else B=255;  

Restore the value of each pixel:

CurrentPixel.R = Int32Util.ClampToByte(R);
CurrentPixel.G = Int32Util.ClampToByte(G);
CurrentPixel.B = Int32Util.ClampToByte(В);

Insert this line into the script to reproduce Step 4:

 A = 255 - Math.Min(Math.Min(R,G),В);

We needs one more control for Step 5. Open the designer interface (File -> User Interface Designer). Select Integer Slider in the drop-down list of  Control type box. In the Control name box write Intensity. Set the maximum value and the default value is 255. Click the Add button, then click Ok. Now let's add to our script one more line:

CurrentPixel.A = Int32Util.ClampToByte(A + Amount3 - 255);

Our script will look as follows:

#region UICode
int Amount1 = 25; // [2,100] Brush Size
int Amount2 = 0; // [0,10] Roughness
int Amount3 = 255; // [0,255] Intensity
#endregion

// Setup for calling the Render Clouds effect
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Setup for using Multiply blend op
private BinaryPixelOp multiplyOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Multiply);

// Here is the main render loop function
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Call the Render Clouds function
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2/10.0);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, 255);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Call the Clouds function using Black and White
    cloudsEffect.Render(new Rectangle[1] {rect},0,1);

    // Now in the main render loop, the dst canvas has a render of clouds
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            // TODO: Add additional pixel processing code here
            CurrentPixel = dst[x,y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
            int A = CurrentPixel.A;
            
            // Convert to black and white contrast image
        	if (R<128) {R=0;} 
        	else R=255; 
        	if (G<128) {G=0;} 
        	else G=255; 
        	if (B<128) {B=0;} 
        	else B=255; 

            CurrentPixel.R = Int32Util.ClampToByte(R);
	    CurrentPixel.G = Int32Util.ClampToByte(G);
	    CurrentPixel.B = Int32Util.ClampToByte(В);

            A = 255 - Math.Min(Math.Min(R,G),;

            CurrentPixel.A = Int32Util.ClampToByte(A + Amount3 - 255);

            CurrentPixel = multiplyOp.Apply(src[x,y], CurrentPixel);

            dst[x,y] = CurrentPixel;
        }
    }
}

Save this script with the Sponge_2 name and create a DLL file with the same name . Check how your effect works. Try to apply different settings for controls.

 

Below are the parameter ranges of our effect, wich very similar to the results of works of the Photoshop's filter Sponge:
- Brush Size - 20...32
- Roughness - 0...10
- Intensity - 10...55

Let's modify our script with the received  results. The code block of the user interface will look like this:

#region UICode
int Amount1 = 2; // [0,10] Brush Size
int Amount2 = 7; // [0,10] Roughness
int Amount3 = 5; // [0,15] Intensity
#endregion

Change the following line in the script:

CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1 + 20);
CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, 1.0 - Amount2/10.0);
CurrentPixel.A = Int32Util.ClampToByte(A + Amount3*3 - 255);

It remains to add some information:

// Author: ReMake
// Submenu: Artistic
// Name: Sponge
// Title: Sponge
// Desc: The Paint.Net effect that simulates Sponge painting
// Keywords: paint.net|effect|sponge
// URL: http://www.getpaint.net/redirect/plugins.html

and our final script will look like this:

// Author: ReMake
// Submenu: Artistic
// Name: Sponge
// Title: Sponge
// Desc: The Paint.Net effect that simulates Sponge painting
// Keywords: paint.net|effect|sponge
// URL: http://www.getpaint.net/redirect/plugins.html

#region UICode
int Amount1 = 2; // [0,10] Brush Size
int Amount2 = 7; // [0,10] Roughness
int Amount3 = 5; // [1,15] Intensity
#endregion

// Setup for calling the Render Clouds effect
private CloudsEffect cloudsEffect = new CloudsEffect();
private PropertyCollection cloudsProps;

// Setup for using Multiply blend op
private BinaryPixelOp multiplyOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Multiply);

// Here is the main render loop function
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Call the Render Clouds function
    cloudsProps = cloudsEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken CloudsParameters = new PropertyBasedEffectConfigToken(cloudsProps);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Scale, Amount1+22);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Power, Amount2/10.0);
    CloudsParameters.SetPropertyValue(CloudsEffect.PropertyNames.Seed, 255);
    cloudsEffect.SetRenderInfo(CloudsParameters, new RenderArgs(dst), new RenderArgs(src));
    // Call the Clouds function using Black and White
    cloudsEffect.Render(new Rectangle[1] {rect},0,1);

    // Now in the main render loop, the dst canvas has a render of clouds
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            // TODO: Add additional pixel processing code here
            CurrentPixel = dst[x,y];
            int R = CurrentPixel.R;
            int G = CurrentPixel.G;
            int B = CurrentPixel.B;
            int A = CurrentPixel.A;
            
            // Convert to black and white contrast image
        	if (R<128) {R=0;} 
        	else R=255; 
        	if (G<128) {G=0;} 
        	else G=255; 
        	if (B<128) {B=0;} 
        	else B=255; 

            CurrentPixel.R = Int32Util.ClampToByte(R);
	    CurrentPixel.G = Int32Util.ClampToByte(G);
	    CurrentPixel.B = Int32Util.ClampToByte(В);

            // Eliminate light areas
            A = 255 - Math.Min(Math.Min(R,G),;

            CurrentPixel.A = Int32Util.ClampToByte(A + Amount3*3 - 245);

            CurrentPixel = multiplyOp.Apply(src[x,y], CurrentPixel);

            dst[x,y] = CurrentPixel;
        }
    }
}

Save the script with the Sponge name. Create an icon for the interface of our effect from the PNG file, which have the size of 16x16 pixels. I have created this icon: Sponge_1.png

 

Now let's save our effect as a DLL file: File-> Save as DLL... Almost all information is in the dialog box, which presented to you. Click the Select icon link and select the icon. Click the Build button - your new effect is ready!

 

The user interface of our new effect looks like this.

Sponge_EN.png

And this is the result of effect's work.

Sponge_effect.png

 

I think, it was easy to create this effect.

 

P.S. In order that the result of work of this effect was most similar to work of the Photoshop's Sponge filter, at first apply to the image Oil Painting effect with parameters: Brush size - 2... 3 and Coarseness - 3... 20.

The result of the work of both the filter looks like this:

Oil_Sponge.jpg

 

Unfortunately simultaneous use of two PaintNet's built-in effects in CodeLab is inaccessible.

 

Вариант этой темы на русском языке смотрите здесь.

  • Upvote 4

Share this post


Link to post
Share on other sites

Oh ReMake, you mean I have to write this MYSELF?? Oh dear. Now I will have to get my toes wet with CodeLab. 

 

Thanks so much. I hope over the next few days I can get to this :D

Share this post


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.

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.

Sign in to follow this