Jump to content

Applying Blur to a Specific Part of an Image Automatically Using a Plugin


Recommended Posts

Hi there! I'm new to plugin coding and I would like to create a plugin that can blur a specific part of an image (not selected) just with a click of a button.

 

Example:

https://imgur.com/a/9LPCstX

Here is a random image of a car. (file size too big so I had to resort to this)

The selected area is exactly where I want to blur.

 

What I want to do is that this specific area (it's ok if the selected area looks weird, I know how to break it up) is applied with Gaussian blur of 70 every time I press the button, regardless of whether or not that area is selected.

 

It should look like this after pressing the button:

https://imgur.com/a/899z9C2

 

Any help is much appreciated since I am just starting out. Thanks!

-Keanny

 

(P.S.: first post here)

Link to comment
Share on other sites

Why not use Copy Selection and Paste Selection?

 

Also, if you're asking about implementing a plugin then your question goes into the Plugin Developer's Central. I'm moving your post.

  • Like 1

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

14 hours ago, Rick Brewster said:

Why not use Copy Selection and Paste Selection?

 

Also, if you're asking about implementing a plugin then your question goes into the Plugin Developer's Central. I'm moving your post.

Yes, that's what I meant. Sorry about that. First time posting here so I don't know which goes where.

Link to comment
Share on other sites

UPDATE: I figured out how to apply Gaussian blur of 70 to the entire image. Now I just have to narrow it down to that selected area.

 

I'm thinking about trying to get the coordinates of every single pixel during pixel processing, how should I do that?

 

(mock up) Example:

 

if (CurrentPixel.Coordinates.X >= 1064 || CurrentPixel.Coordinates.Y <= 96) { // idk what im doing here 
	// apply gaussian blur here
}

Is there such property for CurrentPixel? Thanks in advance.

-Keanny

Link to comment
Share on other sites

For some reason i got this error message:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at PaintDotNet.SystemLayer.PdnNativeMethods.x64.EffectKernel_GaussianBlur(PdnBitmapData& dstBitmap, PdnBitmapData& srcBitmap, Rectangle* pRois, Int32 roisLength, Int32 blurRadius)
   at PaintDotNet.SystemLayer.RenderingKernels.GaussianBlur(BitmapData dstBitmap, BitmapData srcBitmap, Rectangle[] rois, Int32 startIndex, Int32 length, Int32 blurRadius) in D:\src\pdn\src\SystemLayer\RenderingKernels.cs:line 521
   at PaintDotNet.Effects.GaussianBlurEffect.OnRender(Rectangle[] rois, Int32 startIndex, Int32 length) in D:\src\pdn\src\Effects\GaussianBlurEffect.cs:line 141
   at TDCEffect.TDCEffectPlugin.Render(Surface dst, Surface src, Rectangle rect)
   at TDCEffect.TDCEffectPlugin.OnRender(Rectangle[] rois, Int32 startIndex, Int32 length)
   at PaintDotNet.Effects.Effect`1.Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, Int32 startIndex, Int32 length) in D:\src\pdn\src\Effects\Effect`1.cs:line 99
   at PaintDotNet.Effects.BackgroundEffectRenderer.RenderWithClipMask(Effect effect, EffectConfigToken token, RenderArgs dstArgs, RenderArgs srcArgs, RectInt32[] rois, Result`1 lazyClipMaskRenderer) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 193
   at PaintDotNet.Effects.BackgroundEffectRenderer.RendererContext.RenderTile(EffectConfigToken token, Int32 tileIndex) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 173
   at PaintDotNet.Effects.BackgroundEffectRenderer.RendererContext.RenderNextTile(EffectConfigToken token) in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 165
   at PaintDotNet.Effects.BackgroundEffectRenderer.ThreadFunction() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 283
   --- End of inner exception stack trace ---
   at PaintDotNet.Effects.BackgroundEffectRenderer.DrainExceptions() in D:\src\pdn\src\PaintDotNet\Effects\BackgroundEffectRenderer.cs:line 458
   at PaintDotNet.Menus.EffectMenuBase.DoEffect(Effect effect, EffectConfigToken token, Result`1 lazySelectionScans, Result`1 lazyRegionToRenderScans, Result`1 lazyClipMaskRenderer, Surface originalSurface, Exception& exception) in D:\src\pdn\src\PaintDotNet\Menus\EffectMenuBase.cs:line 0

This is causing the plugin to not work at all.

 

Here is my modified script:

// Setup for calling the Gaussian Blur effect
GaussianBlurEffect gaussianblurEffect = new GaussianBlurEffect();
PropertyCollection gaussianblurProps;

protected override void OnDispose(bool disposing)
{
    if (disposing)
    {
        // Release any surfaces or effects you've created
        if (gaussianblurEffect != null) gaussianblurEffect.Dispose();
        gaussianblurEffect = null;
    }

    base.OnDispose(disposing);
}

void PreRender(Surface dst, Surface src)
{
    // Gaussian Blur
    gaussianblurEffect.EnvironmentParameters = EnvironmentParameters;
    gaussianblurProps = gaussianblurEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken gaussianblurParameters = new PropertyBasedEffectConfigToken(gaussianblurProps);
    gaussianblurParameters.SetPropertyValue(GaussianBlurEffect.PropertyNames.Radius, 70);
    gaussianblurEffect.SetRenderInfo(gaussianblurParameters, new RenderArgs(dst), new RenderArgs(src));
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    dst.CopySurface(src, rect.Location, rect);
    Rectangle sel = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();

    int sT = sel.Top;
    int sB = sel.Bottom;
    int sL = sel.Left;
    int sR = sel.Right;

    int x = 1064;
    int y = 96;

    Point left = new Point(sL, sT + x);
    Point rite = new Point(sR, sT + x);
    Point top = new Point(y + sL, sT);
    Point bot = new Point(y + sL, sB);

    int w = sR - sL;
    int h = left.Y - sT;
    Rectangle r1 = new Rectangle(0, 0, w, h);

    w = sR - top.X;
    h = sB - sT;
    Rectangle r2 = new Rectangle(top.X, 0, w, h);;

    // Now call the Gaussian Blur function from src surface to dst surface
    gaussianblurEffect.Render(new Rectangle[1] {r1},0,1);
    gaussianblurEffect.Render(new Rectangle[1] {r2},0,1);
}

Other than that, thanks for the code that you provided me!

Link to comment
Share on other sites

The error is given by the fact that the maximum value of the sliders does not correspond to the length / width of the canvas.
Using CodeLab it is not possible to load these maximum values at runtime with the values of the canvas.
 

Edited by NSD
typo
Link to comment
Share on other sites

2 hours ago, NSD said:

The error is given by the fact that the maximum value of the sliders does not correspond to the length / width of the canvas.
Using CodeLab it is not possible to load these maximum values at runtime with the values of the canvas.
 

Could it be possible to add a conditional to bypass that error?

Edited by Reptillian

G'MIC Filter Developer

 

I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me.

Link to comment
Share on other sites

OP, try this CodeLab script:

 

// Name: Blur Corner
// Author: BoltBait
// Version: 1.0
#region UICode
IntSliderControl Amount1 = 70; // [0,100] Gaussian Blur Radius
IntSliderControl TopPercent = 20; // [0,100] Blur Top Percent
IntSliderControl RightPercent = 20; // [0,100] Blur Right Percent
#endregion

// Setup for calling the Gaussian Blur effect
GaussianBlurEffect gaussianblurEffect = new GaussianBlurEffect();
PropertyCollection gaussianblurProps;

protected override void OnDispose(bool disposing)
{
    if (disposing)
    {
        // Release any surfaces or effects you've created
        if (gaussianblurEffect != null) gaussianblurEffect.Dispose();
        gaussianblurEffect = null;
    }

    base.OnDispose(disposing);
}

// This single-threaded function is called after the UI changes and before the Render function is called
// The purpose is to prepare anything you'll need in the Render function
void PreRender(Surface dst, Surface src)
{
    // Gaussian Blur
    gaussianblurEffect.EnvironmentParameters = EnvironmentParameters;
    gaussianblurProps = gaussianblurEffect.CreatePropertyCollection();
    PropertyBasedEffectConfigToken gaussianblurParameters = new PropertyBasedEffectConfigToken(gaussianblurProps);
    gaussianblurParameters.SetPropertyValue(GaussianBlurEffect.PropertyNames.Radius, Amount1);
    gaussianblurEffect.SetRenderInfo(gaussianblurParameters, new RenderArgs(dst), new RenderArgs(src));
}

// Here is the main multi-threaded render function
// The dst canvas is broken up into rectangles and
// your job is to write to each pixel of that rectangle
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Now call the Gaussian Blur function from src surface to dst surface
    gaussianblurEffect.Render(new Rectangle[1] {rect},0,1);


    // Step through each row of the current rectangle
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        // Step through each pixel on the current row of the rectangle
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];
            ColorBgra SourcePixel = src[x,y];

            if ((x < src.Width * (100-RightPercent) / 100) && 
                (y > src.Height * TopPercent / 100))
            {
                CurrentPixel = SourcePixel;
            }

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

 

Link to comment
Share on other sites

It also looks like you're switching x and y ?

    int x = 1064;
    int y = 96;

    Point left = new Point(sL, sT + x); // uhh, the second parameter is Y, why're you doing +x ?
    Point rite = new Point(sR, sT + x); // same here
    Point top = new Point(y + sL, sT);  // and the opposite here
    Point bot = new Point(y + sL, sB);  // same here

 

  • Like 1

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

No, I delete the UI stuff and basically it would automatically set the Gaussian blur to 70, and apply it to a fixed place. All in a press of a button. There are no constraints at all.

Edited by Keanny Ooi
Additional info that might be useful
Link to comment
Share on other sites

UPDATE: After some improvising using BoltBait's code, I finally did it! Thank you everyone for your help!

 

Also quick question: Are paint.net plugins capable of inserting pictures into the canvas?

Example: https://imgur.com/a/Y3AhvhK

 

Here is a picture. Let's say i want to insert another picture into said picture, all within a press of a button.

It should look like this after pressing the button: https://imgur.com/a/raFmwdY

 

Is this possible?

 

EDIT: @BoltBait, is it possible to print out bold text using the DrawString function?

 

-Keanny

Edited by Keanny Ooi
asking something real quick
Link to comment
Share on other sites

On 5/3/2020 at 12:12 AM, Keanny Ooi said:

EDIT: @BoltBait, is it possible to print out bold text using the DrawString function?

 

Here is some source code showing how to do it:

 

https://forums.getpaint.net/topic/111330-unfinished-plugins/?do=findComment&comment=543199

 

Link to comment
Share on other sites

4 hours ago, BoltBait said:

Thanks a lot! I feel like there should be a code reference for CodeLab, that way it can be easier for beginners.

btw one more question, is it possible to change the alignment of the text while printing it?

 

Example:

you set the alignment to the right, text goes to the right as more text is added.

you set the alignment to the left, text goes to the left as more text is added.

you set the alignment to the middle, text goes to the middle as more text is added.

-Keanny

Link to comment
Share on other sites

There are dozens of tutorials like this one: Dragan Effect - codelab first steps

 

Then there are a set of awesome tuts by @BoltBait here BoltBait.com

 

For more, try using the forum search tool

 

 

 

Link to comment
Share on other sites

11 hours ago, Keanny Ooi said:

Thanks a lot! I feel like there should be a code reference for CodeLab, that way it can be easier for beginners.

btw one more question, is it possible to change the alignment of the text while printing it?

 

While in CodeLab, click on the DrawString method, and press F12 on your keyboard. That will take you to the appropriate page on docs.microsoft.com, where you can read the relevant documentation.

 

To answer your question: Yes.

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

4 hours ago, toe_head2001 said:

 

While in CodeLab, click on the DrawString method, and press F12 on your keyboard. That will take you to the appropriate page on docs.microsoft.com, where you can read the relevant documentation.

 

To answer your question: Yes.

Thanks a lot!

 

Here are more questions:

1. (was asked before but no one answered)

On 5/3/2020 at 3:12 PM, Keanny Ooi said:

Are paint.net plugins capable of inserting pictures into the canvas?

Example: https://imgur.com/a/Y3AhvhK

 

Here is a picture. Let's say i want to insert another picture into said picture, all within a press of a button.

It should look like this after pressing the button: https://imgur.com/a/raFmwdY

 

Is this possible?

444427738_Screenshot(94).thumb.png.a3ae4d2aa14cfc0646fd3bdc2862b061.png

2. Here is a string of words. I would like it so that the unbolded text's location depends on how long the bolded text is.817796118_Screenshot(95).png.9972d8912849ebb71c48c36a9c901ada.png

Let's say I changed the bolded text to this random meme. The word "there" should move to the right side a little bit because the meme word is longer than the word "Hello". If the bolded word is shorter, the unbolded text should move to the left a little bit.

TL, DR: The spacing between the bolded word and the unbolded one remains the same.

 

Is this possible? If so, how?

-Keanny

Link to comment
Share on other sites

On 5/3/2020 at 7:12 AM, Keanny Ooi said:

Also quick question: Are paint.net plugins capable of inserting pictures into the canvas?

Example: https://imgur.com/a/Y3AhvhK

 

Here is a picture. Let's say i want to insert another picture into said picture, all within a press of a button.

It should look like this after pressing the button: https://imgur.com/a/raFmwdY

 

Is this possible?

 

Yes, there are a methods.  If you tell how you want it to work, and we can give you details how to do it.

 

7 minutes ago, Keanny Ooi said:

TL, DR: The spacing between the bolded word and the unbolded one remains the same.

 

Is this possible? If so, how?

 

Take a look at MeasureString. For the non-paint.net-specific stuff, please look on the Microsoft Docs site or stackoverflow.

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

On 5/5/2020 at 1:45 PM, toe_head2001 said:

Yes, there are a methods.  If you tell how you want it to work, and we can give you details how to do it.

I would like it to work like a stamp tool that stamps the picture in place, with the anchor set in the middle. I would like the pic to be stored inside the plugin. It should also allow the picture to be exchanged with another one.

Not sure if it is feasible or not?

 

As for the MeasureString thing, thanks a lot! I sure will do my searching in the Microsoft docs before asking here!

Link to comment
Share on other sites

Start with creating a Surface from your image.

Surface mySurface = Surface.CopyFromBitmap(myBitmap);

 

If you're looking for sample code, there's tons of it inside of CodeLab.  Inside CodeLab, go to File -> New.

 

 

Also look here:

https://forums.getpaint.net/tags/source code/

(There are many more, they just haven't been tagged yet)

 

 

4 minutes ago, Keanny Ooi said:

I would like the pic to be stored inside the plugin.

 

It's possible to have an image file embedded into your plugin, but not with CodeLab.  You'd have to switch to Visual Studio.

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

So why not use some of the tools already created?

 

image.png

 

I know @Reptillian has something similar to this in the G'Mic plugin.

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.

×
×
  • Create New...