ReMake Posted May 20, 2015 Share Posted May 20, 2015 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. 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). 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: 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: 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. And this is the result of effect's work. 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: Unfortunately simultaneous use of two PaintNet's built-in effects in CodeLab is inaccessible. Вариант этой темы на русском языке смотрите здесь. 4 Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted May 20, 2015 Share Posted May 20, 2015 Excellent tutorial!! 1 Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker Link to comment Share on other sites More sharing options...
ReMake Posted May 20, 2015 Author Share Posted May 20, 2015 Excellent tutorial!! Thank You very much. Quote Link to comment Share on other sites More sharing options...
barbieq25 Posted May 21, 2015 Share Posted May 21, 2015 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 Quote Knowledge is no burden to carry. April Jones, 2012 Gallery My DA Gallery Link to comment Share on other sites More sharing options...
ReMake Posted May 21, 2015 Author Share Posted May 21, 2015 See P.S in the first post. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.