Jump to content

My new plagin


black2hack

Recommended Posts

I'm coding my new (and actually first) Paint.NET plugin now and I can't solve a trouble. I've been trying for almost a day but this is a hard nut to crack. I have no idea why it happens. I thought I had eliminated all possible causes but this error is still here. As I'm new with CodeLab and C# I think it's relative to some compiler rule which I don't know.

An idea of my plugin is simple. It splits an image to a few pieces and then move them aside. I use a matrix to keep vertexes of splitting.

8c78b560b486t.jpg

962fc5333ed0t.jpg

b52a950475d6t.jpg

It works perfectly there. But if I add 'fluctuations' to change fragments (from rectangle to arbitrary quadrilaterals) Paint.NET renders a strange thing.

620da44198fft.jpg

I attached a piece of code. It's only a part of my plugin but it shows the error well. I'd really appreciate any ideas why the plugin works incorrectly. [The new code is placed below]

Shatter.zip

Edited by black2hack
Link to comment
Share on other sites

Some extra information. For short I'll call my problem teh BUG.

Function Interpolate seems to be working well. Even if it's bugged it shouldn't relate to teh BUG.

Function PointInQuadrilateral was written by myself so I thought the error is there. But I've tested it a lot and it seems to be working too. But I'm still not sure cause a bug in the function can cause teh BUG.

I use 2 matrices - MatNet and MatFragments - and they could have some errors. But it shouldn't cause such a teh BUG. If vertexes were simply messed my plugin would render messed quadrilaterals. But it renders a total **** (teh BUG), not quadrilaterals at all.

So... I'm stunned. It must be sorta a type conversion or overflow mistake but I can't find it.

Link to comment
Share on other sites

Just from the screenshots, I think you've a problem with the ROI (rectangle of interest).

Read about the ROI and how paint.net uses it here: http://www.boltbait.com/pdn/CodeLab/help/overview.asp

Here's another thread on the subject:

  • Upvote 1
Link to comment
Share on other sites

Just from the screenshots, I think you've a problem with the ROI (rectangle of interest).

Read about the ROI and how paint.net uses it here: http://www.boltbait....lp/overview.asp

Here's another thread on the subject: http://forums.getpai...ing-to-pdn-336/

Thank you for an answer. I'm not really good at ROI. Is an entire program called when a new ROI is rendered or Render function only? In the second case all should work well.

Link to comment
Share on other sites

The way it works is,

1. Your Effect is instantiated (your constructor is called)

2. The user configures stuff (your CreateEffectConfigDialog() is called, or IndirectUI just does it for you)

3. OnSetRenderInfo() is called with the new token.

4. OnRender() is called many times, once for each section of the region of interest. These calls are made in parallel on multiple threads.

5. If the user changes the configuration (the token), then IsCancelRequested is set to true and Paint.NET waits for any pending OnRender() calls to finish. Go back to step 3. (IsCancelRequested is also reset to false)

If you want you can do all your rendering in OnSetRenderInfo() and then OnRender() would be implemented to do nothing. It doesn't provide a great user experience though.

  • Upvote 2

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

  • 2 weeks later...

And after less than a month I've returned to my plugin =)

Ok, I've found out that teh BUG is caused by ROI. So Eer, you was right. Rick, your post seems to be very helpful but there is a problem - no function OnSetRenderInfo() nor OnRender() in my program exist. I use CodeLab, and there is Render function only. Is it possible to create a piece of code called like OnSetRenderInfo() and another called like OnRender() (I think Render function works that way)? If it's impossible to do that in CodeLab please give me a link to a guide 'how to write Paint.NET plugins with C' or something like this.

Link to comment
Share on other sites

You can write plugins in Visual Studio. I use the Express Edition (it's a free download from Microsoft). With Visual Studio you can code in C# - just like Codelab uses.

Here's an effect template should you wish to go down that path: http://forums.getpaint.net/index.php?/topic/2248-visual-studio-2005-effect-plugin-template/ (Note: read the whole thread - especially BoltBait's how-to post!)

I have not heard of Codelab being used with OnSetRender, I'd also be interested if it can be done.

  • Upvote 1
Link to comment
Share on other sites

I've encountered a error during a compilation. (MS Visual Studio 2005)

1. I deleted PdnLib reference and added PaintDotNet.Core. Then I tried to build and

------ Build started: Project: EffectsPluginTemplate2, Configuration: Debug Any CPU ------

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"..\..\..\..\..\..\..\Program Files\Paint.NET\PaintDotNet.Core.dll" /reference:"..\..\..\..\..\..\..\Program Files\Paint.NET\PaintDotNet.Effects.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll /debug+ /debug:full /optimize- /out:obj\Debug\EffectsPluginTemplate2.dll /resource:obj\Debug\EffectsPluginTemplate2.EffectPluginConfigDialog.resources /resource:obj\Debug\EffectsPluginTemplate2.EffectPluginIcon.png /target:library EffectPluginToken.cs EffectPlugin.cs EffectPluginConfigDialog.cs Properties\AssemblyInfo.cs

C:\Users\Yara\Documents\Visual Studio 2005\Projects\EffectsPluginTemplate2\EffectsPluginTemplate2\EffectPluginConfigDialog.cs(12,18): error CS0012: The type 'PaintDotNet.Threading.IDispatcherObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'PaintDotNet.Base, Version=3.58.4081.24574, Culture=neutral, PublicKeyToken=null'.

c:\Program Files\Paint.NET\PaintDotNet.Core.dll: (Related file)

c:\Program Files\Paint.NET\PaintDotNet.Effects.dll: (Related file)

Compile complete -- 1 errors, 0 warnings

========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

2. I added PaintDotNetBase reference and

------ Build started: Project: EffectsPluginTemplate2, Configuration: Debug Any CPU ------

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:"..\..\..\..\..\..\..\Program Files\Paint.NET\PaintDotNet.Base.dll" /reference:"..\..\..\..\..\..\..\Program Files\Paint.NET\PaintDotNet.Core.dll" /reference:"..\..\..\..\..\..\..\Program Files\Paint.NET\PaintDotNet.Effects.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll /debug+ /debug:full /optimize- /out:obj\Debug\EffectsPluginTemplate2.dll /resource:obj\Debug\EffectsPluginTemplate2.EffectPluginConfigDialog.resources /resource:obj\Debug\EffectsPluginTemplate2.EffectPluginIcon.png /target:library EffectPluginToken.cs EffectPlugin.cs EffectPluginConfigDialog.cs Properties\AssemblyInfo.cs

C:\Users\Yara\Documents\Visual Studio 2005\Projects\EffectsPluginTemplate2\EffectsPluginTemplate2\EffectPlugin.cs(37,16): error CS0619: 'PaintDotNet.Effects.Effect.Effect(string, System.Drawing.Image, string, bool)' is obsolete: ''

Compile complete -- 1 errors, 0 warnings

========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========

Blah. I miss Pascal so much.

Link to comment
Share on other sites

Instead of the Output window, you'll probably have an easier time deciphering error messages in the Errors window. It'll even take you to the offending line.

In this case, you are using an obsolete overload of the Effect constructor. The obsolete ones are kept around for compatibility with legacy plugins, but new plugins can't use them.

  • Upvote 1

xZYt6wl.png

ambigram signature by Kemaru

[i write plugins and stuff]

If you like a post, upvote it!

Link to comment
Share on other sites

2 pyrochild. I don't know how to open Error window in Visual Studio. I'd appreciate if you reveal that =)

Ok, I've noticed this in the topic that EER had linked.

public EffectPlugin() //: base(EffectPlugin.StaticName, EffectPlugin.StaticIcon, EffectPlugin.StaticSubMenuName, true) // Obsolete //: base(EffectPlugin.StaticName, EffectPlugin.StaticIcon, EffectPlugin.StaticSubMenuName, EffectFlags.Configurable | EffectFlags.SingleThreaded) : base(EffectPlugin.StaticName, EffectPlugin.StaticIcon, EffectPlugin.StaticSubMenuName, EffectFlags.Configurable) { }

And the template has been built finally. Awesome! Two questions.

Can anybody fix that template? The template seems to be very handy. And I don't think it would take a bunch of time to replace a few strings of code and save poor newbies from their brains crashed =)

Is it possible to work with the template in CodeGear RAD Studio? I tried to check it but I didn't find the way to open the template there.

Link to comment
Share on other sites

2 pyrochild. I don't know how to open Error window in Visual Studio. I'd appreciate if you reveal that =)

View -> Error List

It's open by default, but you may have closed it at some point. It autohides to a tab.

xZYt6wl.png

ambigram signature by Kemaru

[i write plugins and stuff]

If you like a post, upvote it!

Link to comment
Share on other sites

  • 1 month later...

And after less than a month I've returned to my plugin © =)

2pyrochild. Thank you, I've found Error List in View -> Other windows -> Error List.

I've received evidence that The BUG is caused by ROI. When I delete ROI everything works - slowly but correctly. I've attached a piece of code (C# now) just in case someone can find a problem faster than me. I suspect the problem is similar to this one http://forums.getpai...ing-to-pdn-336/ but I haven't understood this topic yet.

public override void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length)
       {
           PdnRegion selectionRegion = EnvironmentParameters.GetSelection(srcArgs.Bounds);
           //Surface src = srcArgs.Surface;
           //Surface dst = dstArgs.Surface;
           Rectangle selection = EnvironmentParameters.GetSelection(srcArgs.Surface.Bounds).GetBoundsInt();
           int CenterX = ((selection.Right - selection.Left) / 2) + selection.Left;
           int CenterY = ((selection.Bottom - selection.Top) / 2) + selection.Top;
           ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor;
           ColorBgra SecondaryColor = (ColorBgra)EnvironmentParameters.SecondaryColor;
           int BrushWidth = (int)EnvironmentParameters.BrushWidth;
           ColorBgra CurrentPixel;

           int Amount1 = 5; //[1,10]CountOfColumns
           int Amount2 = 5; //[1,10]CountOfRows
           int Amount3 = 50;    //[0,50]Shifting(pixels)
           int Amount4 = 10;    //[0,100]Fluctuation(%)
           int Amount5 = 0; //[0,359]MaxAngle(degrees)

           int n = Amount1;
           int m = Amount2;
           int shift = Amount3;
           double a = (selection.Right - selection.Left) / n;
           double b = (selection.Bottom - selection.Top) / m;
           double dFluct = (double)Amount4 / 100.0 * 0.95;
           double dAngle = (double)Amount5 / 360.0 * 3.1415926535897932384626433832795;
           int CenterN = (int)Math.Floor(n / 2.0);
           int CenterM = (int)Math.Floor(m / 2.0);
           double tempX, tempY;
           double tempCenterX, tempCenterY;
           double tempAngle;
           double tempCos, tempSin;
           double tempShiftX, tempShiftY;
           bool bGotcha;
           Random rand = new Random();

           //Creating a matrix splitting the initial picture, [,,0] - x, [,,1] - y
           double[, ,] MatNet = new double[m + 1, n + 1, 2];
           MatNet[0, 0, 0] = selection.Left;
           MatNet[0, 0, 1] = selection.Top;
           MatNet[m, 0, 0] = selection.Left;
           MatNet[m, 0, 1] = selection.Bottom;
           MatNet[0, n, 0] = selection.Right;
           MatNet[0, n, 1] = selection.Top;
           MatNet[m, n, 0] = selection.Right;
           MatNet[m, n, 1] = selection.Bottom;
           for (int j = 1; j < n; j++)
           {
               MatNet[0, j, 0] = selection.Left + a * ((double)j + dFluct * (rand.NextDouble() - 0.5));
               MatNet[0, j, 1] = selection.Top;
               MatNet[m, j, 0] = selection.Left + a * ((double)j + dFluct * (rand.NextDouble() - 0.5));
               MatNet[m, j, 1] = selection.Bottom;
           }
           for (int i = 1; i < m; i++)
           {
               MatNet[i, 0, 0] = selection.Left;
               MatNet[i, 0, 1] = selection.Top + b * ((double)i + dFluct * (rand.NextDouble() - 0.5));
               MatNet[i, n, 0] = selection.Right;
               MatNet[i, n, 1] = selection.Top + b * ((double)i + dFluct * (rand.NextDouble() - 0.5));
               for (int j = 1; j < n; j++)
               {
                   MatNet[i, j, 0] = selection.Left + a * ((double)j + dFluct * (rand.NextDouble() - 0.5));
                   MatNet[i, j, 1] = selection.Top + b * ((double)i + dFluct * (rand.NextDouble() - 0.5));
               }
           }

           //Creating a matrix of fragments of the shattered picture, [,,0,]..[,,3,] - vertexes, [,,4,] - rotating center, [,,,0] - x, [,,,1] - y, [,,5,] - Cos & Sin
           double[, , ,] MatFragments = new double[m, n, 7, 2];  // 01 - vertexes' position
           for (int i = 0; i < m; i++)                      // 23     	
           {
               for (int j = 0; j < n; j++)
               {
                   tempAngle = dAngle * rand.NextDouble();
                   tempCos = Math.Cos(tempAngle);
                   tempSin = Math.Sin(tempAngle);
                   tempShiftX = shift * (j - CenterN); //how much we should move the fragment
                   tempShiftY = shift * (i - CenterM);
                   tempCenterX = (double)selection.Left + a * ((double)j + 0.5); //a (rotating) center of the fragment
                   tempCenterY = (double)selection.Top + b * ((double)i + 0.5);
                   tempX = MatNet[i, j, 0] - tempCenterX;
                   tempY = MatNet[i, j, 1] - tempCenterY;
                   MatFragments[i, j, 0, 0] = tempX * tempCos - tempY * tempSin + tempCenterX + tempShiftX; //rotating and moving
                   MatFragments[i, j, 0, 1] = tempY * tempCos + tempX * tempSin + tempCenterY + tempShiftY;
                   tempX = MatNet[i, j + 1, 0] - tempCenterX;
                   tempY = MatNet[i, j + 1, 1] - tempCenterY;
                   MatFragments[i, j, 1, 0] = tempX * tempCos - tempY * tempSin + tempCenterX + tempShiftX;
                   MatFragments[i, j, 1, 1] = tempY * tempCos + tempX * tempSin + tempCenterY + tempShiftY;
                   tempX = MatNet[i + 1, j, 0] - tempCenterX;
                   tempY = MatNet[i + 1, j, 1] - tempCenterY;
                   MatFragments[i, j, 2, 0] = tempX * tempCos - tempY * tempSin + tempCenterX + tempShiftX;
                   MatFragments[i, j, 2, 1] = tempY * tempCos + tempX * tempSin + tempCenterY + tempShiftY;
                   tempX = MatNet[i + 1, j + 1, 0] - tempCenterX;
                   tempY = MatNet[i + 1, j + 1, 1] - tempCenterY;
                   MatFragments[i, j, 3, 0] = tempX * tempCos - tempY * tempSin + tempCenterX + tempShiftX;
                   MatFragments[i, j, 3, 1] = tempY * tempCos + tempX * tempSin + tempCenterY + tempShiftY;
                   MatFragments[i, j, 4, 0] = tempCenterX;
                   MatFragments[i, j, 4, 1] = tempCenterY;
                   MatFragments[i, j, 5, 0] = tempCos;
                   MatFragments[i, j, 5, 1] = tempSin;
                   MatFragments[i, j, 6, 0] = tempShiftX;
                   MatFragments[i, j, 6, 1] = tempShiftY;
               }
           }

           for (int L = startIndex; L < startIndex + length; ++L)
           {
               Rectangle rect = rois[L];

               for (int y = rect.Top; y < rect.Bottom; ++y)
               {
                   for (int x = rect.Left; x < rect.Right; ++x)
                   {
                       CurrentPixel = srcArgs.Surface[x, y];
                       bGotcha = false;
                       for (int i = 0; i < m; i++)
                       {
                           for (int j = 0; j < n; j++)
                           {
                               //if (x,y) is inside the fragment (i,j) we should restore a colour of the pixel (x,y)
                               if (PointInQuadrilateral((double)x + 0.5, (double)y + 0.5, MatFragments[i, j, 0, 0], MatFragments[i, j, 0, 1], MatFragments[i, j, 1, 0], MatFragments[i, j, 1, 1], MatFragments[i, j, 2, 0], MatFragments[i, j, 2, 1], MatFragments[i, j, 3, 0], MatFragments[i, j, 3, 1]))
                               {
                                   tempX = (double)x - MatFragments[i, j, 6, 0] - MatFragments[i, j, 4, 0];
                                   tempY = (double)y - MatFragments[i, j, 6, 1] - MatFragments[i, j, 4, 1];
                                   tempX = tempX * MatFragments[i, j, 5, 0] + tempY * MatFragments[i, j, 5, 1] + MatFragments[i, j, 4, 0];
                                   tempY = tempY * MatFragments[i, j, 5, 0] - tempX * MatFragments[i, j, 5, 1] + MatFragments[i, j, 4, 1];

                                   CurrentPixel = Interpolate(srcArgs.Surface, selection, tempX - 0.5, tempY - 0.5);
                                   dstArgs.Surface[x, y] = CurrentPixel;

                                   bGotcha = true;
                                   i = m; j = n;
                               }
                           }
                       }
                       //if (x,y) is beyond all fragments we should make the pixel (x,y) transparent
                       if (!bGotcha)
                       {
                           CurrentPixel.R = (byte)PrimaryColor.R;
                           CurrentPixel.G = (byte)PrimaryColor.G;
                           CurrentPixel.B = (byte)PrimaryColor.B;
                           CurrentPixel.A = 10;
                           dstArgs.Surface[x, y] = CurrentPixel;
                       }
                   }
               }
           }
       }

Edited by black2hack
Link to comment
Share on other sites

  • 2 months later...

Hey, thank you pal. I've been occupied by different annoying stuff (like my studies ^_^) so I kinda neglected my work with this plugin. I hope I'll be able to find time to cope with Teh BUG soon.

I also have some ideas for a new plugin. Though there is a high probability I'll never start doing it =)

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