Sign in to follow this  
Tanel

Plugins return distorted images after updating to PdN 3.36

Recommended Posts

Can you pease explain what are the changes in 3.36 effect render system?

Almost all my previously designed plugins (Sharpen+, Shadow/Highlight, Color Mixer, Color to Alpha, Local Contrast) return distorted images now, like this:

pdn_336_pluginerror.jpg

Maybe you can point out what I need to change, for example below is simplified presentation of Sharpen+ :

using System;
using System.Drawing;
using PaintDotNet;
using PaintDotNet.Effects;
using PaintDotNet.PropertySystem;
using System.Collections.Generic;

namespace Sharpen_
{
   public class EffectPlugin
       : PaintDotNet.Effects.Effect
   {
       public static string StaticName { get { return "Sharpen+"; } }
       public static Bitmap StaticImage { get { return new Bitmap(typeof(EffectPlugin), "EffectPluginIcon.png"); } }
       public static string StaticSubMenuName { get { return SubmenuNames.Photo; } }

       public EffectPlugin()
           : base(StaticName, StaticImage, StaticSubMenuName, EffectFlags.Configurable)
       {
           this.blurEffect = new GaussianBlurEffect();
           this.blurProps = this.blurEffect.CreatePropertyCollection();
       }

       public override EffectConfigDialog CreateConfigDialog()
       {
           return new EffectPluginConfigDialog();
       }

       private GaussianBlurEffect blurEffect;
       private PropertyCollection blurProps;

       public override unsafe void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length)
       {
           EffectPluginConfigToken token = (EffectPluginConfigToken)parameters;
           PdnRegion selectionRegion = EnvironmentParameters.GetSelection(srcArgs.Bounds);
           Rectangle selection = EnvironmentParameters.GetSelection(srcArgs.Bounds).GetBoundsInt();

           int rad = token.Radius;
           int amt = token.Amount;

               this.blurEffect.Render(rois, startIndex, length);
               for (int i = startIndex; i < startIndex + length; ++i)
               {
                   Rectangle roi = rois[i];

                   for (int y = roi.Top; y < roi.Bottom; ++y)
                   {
                       ColorBgra* srcPtr = srcArgs.Surface.GetPointAddress(roi.X, roi.Y);
                       ColorBgra* dstPtr = dstArgs.Surface.GetPointAddress(roi.X, roi.Y);
                       ColorBgra CurrentPixel;
                       ColorBgra OrigPixel;
                       byte r, g, b, ro, go, bo, ao, ry, by, gy;

                       for (int x = roi.Left; x < roi.Right; ++x)
                       {
                           CurrentPixel = dstArgs.Surface[x, y];
                           r = CurrentPixel.R;
                           g = CurrentPixel.G;
                           b = CurrentPixel.B;
                           vf = (float)CurrentPixel.GetIntensityByte();

                           if (selectionRegion.IsVisible(x, y))
                           {
                               OrigPixel = srcArgs.Surface[x, y];
                               ro = OrigPixel.R;
                               go = OrigPixel.G;
                               bo = OrigPixel.B;
                               ao = OrigPixel.A;

                               // .....
                               // pixel level calculations here
                               // .....

                               OrigPixel = ColorBgra.FromBgra(by, gy, ry, ao);

                               *dstPtr = OrigPixel;

                               ++srcPtr;
                               ++dstPtr;
                           }
                       }
                   }
               }
       }
   }
}

Share this post


Link to post
Share on other sites

Fixed:

using System;
using System.Drawing;
using PaintDotNet;
using PaintDotNet.Effects;
using PaintDotNet.PropertySystem;
using System.Collections.Generic;

namespace Sharpen_
{
   public class EffectPlugin
       : PaintDotNet.Effects.Effect
   {
       public static string StaticName { get { return "Sharpen+"; } }
       public static Bitmap StaticImage { get { return new Bitmap(typeof(EffectPlugin), "EffectPluginIcon.png"); } }
       public static string StaticSubMenuName { get { return SubmenuNames.Photo; } }

       public EffectPlugin()
           : base(StaticName, StaticImage, StaticSubMenuName, EffectFlags.Configurable)
       {
           this.blurEffect = new GaussianBlurEffect();
           this.blurProps = this.blurEffect.CreatePropertyCollection();
       }

       public override EffectConfigDialog CreateConfigDialog()
       {
           return new EffectPluginConfigDialog();
       }

       private GaussianBlurEffect blurEffect;
       private PropertyCollection blurProps;

       public override unsafe void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length)
       {
           EffectPluginConfigToken token = (EffectPluginConfigToken)parameters;
           PdnRegion selectionRegion = EnvironmentParameters.GetSelection(srcArgs.Bounds);
           Rectangle selection = EnvironmentParameters.GetSelection(srcArgs.Bounds).GetBoundsInt();

           int rad = token.Radius;
           int amt = token.Amount;

               this.blurEffect.Render(rois, startIndex, length);
               for (int i = startIndex; i                 {
                   Rectangle roi = rois[i];

                   for (int y = roi.Top; y                     {
                       ColorBgra* srcPtr = srcArgs.Surface.GetPointAddressUnchecked(roi.Left, y);
                       ColorBgra* dstPtr = dstArgs.Surface.GetPointAddressUnchecked(roi.Left, y);
                       ColorBgra CurrentPixel;
                       ColorBgra OrigPixel;
                       byte r, g, b, ro, go, bo, ao, ry, by, gy;

                       for (int x = roi.Left; x                         {
                           CurrentPixel = dstArgs.Surface[x, y];
                           r = CurrentPixel.R;
                           g = CurrentPixel.G;
                           b = CurrentPixel.B;
                           vf = (float)CurrentPixel.GetIntensityByte();

                           if (selectionRegion.IsVisible(x, y))
                           {
                               OrigPixel = srcArgs.Surface[x, y];
                               ro = OrigPixel.R;
                               go = OrigPixel.G;
                               bo = OrigPixel.B;
                               ao = OrigPixel.A;

                               // .....
                               // pixel level calculations here
                               // .....

                               OrigPixel = ColorBgra.FromBgra(by, gy, ry, ao);

                               *dstPtr = OrigPixel;

                               ++srcPtr;
                               ++dstPtr;
                           }
                       }
                   }
               }
       }
   }
}

The problem is in the unsafe pointers template. The bug is in these two lines:

    ColorBgra* srcPtr = srcArgs.Surface.GetPointAddress(roi.X, roi.Y);
    ColorBgra* dstPtr = dstArgs.Surface.GetPointAddress(roi.X, roi.Y);

They should read:

    ColorBgra* srcPtr = srcArgs.Surface.GetPointAddressUnchecked(roi.Left, y);
    ColorBgra* dstPtr = dstArgs.Surface.GetPointAddressUnchecked(roi.Left, y);

You see where those new values come from? See, roi.Left is the definition of x from the next line, y is from the previous line. Also, you'll want to use GetPointAddressUnchecked for full speed benefit.

I fell victim to this error as well. I rebuilt all of my plugins last night.

BTW, the reason for this is simple. Prior to 3.36, Paint.NET always called your render loop with ROI's of 1px tall. Now, it calls it with ROI's of 2px tall. So, the error in the template was always getting the address of the first line of the ROI for processing. With the change I show, you now get the address of the proper line to work on.

Share this post


Link to post
Share on other sites

Thank you BoltBait, I appreciate it much.

...

I fell victim to this error as well. I rebuilt all of my plugins last night.

Heh, no wonder then - all my plugin designs are learnt from your examples! :wink:

Share this post


Link to post
Share on other sites
...

I fell victim to this error as well. I rebuilt all of my plugins last night.

Heh, no wonder then - all my plugin designs are learnt from your examples! :wink:

Well, that's what you get for listening to me... :lol:

Share this post


Link to post
Share on other sites

Yes, please update your plugins :)

There may be some plugins that are popular but the author has since "left", so in the next update I may put in some compatibility shims for those.

Share this post


Link to post
Share on other sites

There may be some plugins that are popular but the author has since "left", so in the next update I may put in some compatibility shims for those.

Please do it. I, for example, have some plugins I'm not keeping in my effects folder but they can be installed when I need them. I can imagine other people do this, too, especially for shrinking the effect menus. Without such a compatibility shim, requests and error reportings could show up several times in a month from now on, especially when the issue is not as "popular" as it's right now.

Share this post


Link to post
Share on other sites
I will fix my plugins within few days. Maybe worth to collect them into a single plugin-pack then also?

Yes, please. A sticky is waiting for your pack ;)

Share this post


Link to post
Share on other sites
Can we start a list of plugins that are not working?

If known, can we also list the authors of those plugins?

Such a list would be most helpful. Excellent suggestion, and thank you for thinking of it.

I usually lurk in this forum at least 3 or more times a week. I will definitely be looking out for it. :)

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