Sign in to follow this  
Followers 0
pyjo

Basic Antialias version 1.1 - bug fixed (January 14 2008)

24 posts in this topic

-EDIT-

The 1.1 release fixes the reported bug. Or, at least, I hope so. You find this new Basic Antialias in the Effects->Object submenu.

I cannot say if Basic Antialias is better than Antialias. What I can say is that my design goals in writing it were 1) avoid side effects like shrink, grow, blur or outline, and 2) reduce aliasing in a basic way without having to spend time in fine tuning of the settings. Basic Antialias satisfies this goals, and also my personal needs. I hope you will find useful, too.

You find the code below. Now I can understand almost everything of it. My code is far from being perfect, it is redundant and not always does the right thing (it is almost impossible to note this, however). If you want to improve it but you can't understand it, please contact me and I'll try to explain.

I plan to release version 2.0 with support for trasparent objects in the future, but now I want to try developing other plugins.

Thanks,

Pyjo.

________________________

What? After Feather and Antialias, another antialias plugin?

Well... sorry... this is my first plugin, I wanted to start with something simple and not too experimental.

Ok, but why another Antialias plugin? Here is the answer: I noticed that some PdN users, including me, are not totally satisfied with existing antialias tools. I often used motion blur, which is not intended for this purpose, for removing aliasing effectively. So I took CodeLab and wrote this new plugin. Since I'm not a developer (and I don't know C#) it required me a lot of time, but eventually, pushing and kicking, my bare C code worked as expected (I hope that soon or later I'll understand how, too).

I created this plugin for personal use, but maybe that someone else will find it useful. Basic Antialias is basic in that it doesn't ask the user for any setting. It affects the border of "solid" shapes surrounded by trasparent pixels. It is useful when you copy and paste a selection in a new layer or when you fill a selection with something like clouds or gradient, as in this example:

Moons.jpg

(f you see no difference between the four moons, please put your nose close to the screen.)

The original picture is aliased. Feather and Antialias (with default settings) introduce a blur. Basic Antialias reduces aliasing without altering the sharpness of the border.

Here is another example:

Rose.jpg

The rose was selected with the magic wand from a photo, copied two times in a new layer and then Basic Antialias was applied to the second one.

To use this plugin dowload the .zip, put the extracted .dll file in the Effects folder and (re)start PdN. You'll find the tool in Effects>Contour submenu (is this the right menu for an antialias? Please give me a feedback).

If the plugin seems not to work, verify that the shape to be processed doesn't contain any partially trasparent pixel. Basic Antialias works only when it finds a totally trasparent pixel (alpha=0) near a not-trasparent-at-all pixel (alpha=255). If some antialias tool was previously used on the picture (note that paintbrush and other drawing tools have the antialias feature on by default), basic antialias won't do anything on it. Maybe this limitation will be removed in 2.0 version.

Bye,

Pyjo.

 

void Render(Surface dst, Surface src, Rectangle rect)
{
    PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds);
    Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    ColorBgra CurrentPixel;
    for(int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            if (selectionRegion.IsVisible(x, y))
            {
                CurrentPixel = src[x,y];  
                int i,j,p; 
//VERTICAL
                double x1,x2;
		for (p=1;p>=-1;p-=2)
                { 
//Addition
                   if((x>selection.Left) && (x<selection.Right-1) && CurrentPixel.A==0&&src[x-p,y].A==255)
                   {
                    for(i=y;src[x,i].A==0 && src[x-p,i].A==255 && i<selection.Bottom-1;i++);
                    for(j=y;src[x,j].A==0 && src[x-p,j].A==255 && j>selection.Top;j--);
                   
                    if(src[x,j].A==255&&y<=(i+j)/2) //bottom
                     {
                      x1=((double)y+(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                      x2=((double)y-(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                      CurrentPixel=src[x-p,y];
                      CurrentPixel.A=(byte)((x1+x2)*127);
                     }
           
                    if(src[x,i].A==255&&y>(i+j)/2) //top
                     {
                      x1=((double)y+(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                      x2=((double)y-(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);  
                      CurrentPixel=src[x-p,y]; CurrentPixel.A=(byte)(255-(x1+x2)*127);
                     }
                   }
                   
//Subtraction
                   if((x>selection.Left) && (x<selection.Right-1) && src[x,y].A==255&&src[x-p,y].A==0)
                    { 
                     for(i=y;src[x,i].A==255 && src[x-p,i].A==0 && i<selection.Bottom-1;i++);
                     for(j=y; src[x,j].A==255 && src[x-p,j].A==0 && j>selection.Top;j--);
              
                     if(src[x,i].A==0&&y>(i+j)/2) //bottom
                      {
                       x1=((double)y+(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                       x2=((double)y-(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);        
                       CurrentPixel.A+=(byte)((x1+x2)*127);
                      }
                        
                     if(src[x,j].A==0 &&y<(i+j)/2)  //top
                      {
                       x1=((double)y+(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                       x2=((double)y-(0.5))/(j-i+1)+(0.5)*(i+j)/(-j+i-1);
                       CurrentPixel.A-=(byte)((x1+x2)*127);  
                      }
                    }
        
                 }
                
            
//HORIZONTAL
              
                double y1,y2;
                for (p=1;p>=-1;p-=2)
                 { 
//Subtraction
                  if((y>selection.Top) && (y<selection.Bottom-1) && CurrentPixel.A==255&&src[x,y-p].A==0)
                   { 
                    for(i=x;src[i,y].A==255 && src[i,y-p].A<255 && i<selection.Right-1;i++);
                    for(j=x;src[j,y].A==255 && src[j,y-p].A<255 && j>selection.Left;j--);
                        
                    if(src[j,y].A==0&&x<=(i+j)/2) //going up
                    {
                     y1=((double)x+(0.5))/(i-j-1)+(0.5)*(i+j)/(j-i+1);
                     y2=((double)x-(0.5))/(i-j-1)+(0.5)*(i+j)/(j-i+1);
                     if(x==((i+j)/2)) CurrentPixel.A=(byte)(255-((y1/2)*127));
                      else CurrentPixel.A+=(byte)((y1+y2)*127);
                    }
                   if(src[i,y].A==0 &&x>=(i+j)/2)  //going down
                    {
                     y1=((double)x+(0.5))/(j-i+1)+(0.5)*(i+j)/(i-j-1);
                     y2=((double)x-(0.5))/(j-i+1)+(0.5)*(i+j)/(i-j-1);
                     if(x==((i+j)/2)) CurrentPixel.A=(byte)(255-((y2/2)*127));
                       else CurrentPixel.A+=(byte)((y1+y2)*127);
                    }
                  }
            
//Addition
                  if((y>selection.Top) && (y<selection.Bottom-1) && CurrentPixel.A==0&&src[x,y-p].A==255)
                   {   
                    for(i=x;src[i,y].A==0 && src[i,y-p].A==255&& i<selection.Right-1;i++);
                    for(j=x;src[j,y].A==0 && src[j,y-p].A==255&& j>selection.Left;j--);
                   
                    if(src[i,y].A==255&&x>=(i+j)/2) //going up
                    {
                    CurrentPixel=src[x,y-p];
                     y1=((double)x+(0.5))/(i-j-1)+(0.5)*(i+j)/(j-i+1);
                     y2=((double)x-(0.5))/(i-j-1)+(0.5)*(i+j)/(j-i+1);
                     if(x==((i+j)/2)) CurrentPixel.A=(byte)((y1/2)*127);
                       else CurrentPixel.A=(byte)((y1+y2)*127);
                    }
                   if(src[j,y].A==255&&x<=(i+j)/2) //going down
                    {
                     CurrentPixel=src[x,y-p];
                     y1=((double)x+(0.5))/(j-i+1)+(0.5)*(i+j)/(i-j-1);
                     y2=((double)x-(0.5))/(j-i+1)+(0.5)*(i+j)/(i-j-1);
                     if(x==((i+j)/2)) CurrentPixel.A=(byte)((y2/2)*127);else
                      CurrentPixel.A=(byte)((y1+y2)*127);
                    }
                  }
                 }      
                dst[x,y] = CurrentPixel;
            }
        }
    }
}

BasicAntialias11.zip

2

Share this post


Link to post
Share on other sites

Nice plugin!

You'll find the tool in Effects>Contour submenu (is this the right menu for an antialias? Please give me a feedback).

I think the "Effects > Object" menu might be a better choice.

Also, you might want to release the source. We have a lot of great programmers here who might be able to assist you in adding to the greatness of this effect.

0

Share this post


Link to post
Share on other sites

IMO, wee can newer have enough plugins to choose from. So thanks for posting. I am going to try it later.

0

Share this post


Link to post
Share on other sites

Error:

File: C:\Program Files\Paint.NET\Effects\BasicAntialias10.dll
     Effect Name: PaintDotNet.Effects.UserScript
     Full error message: PaintDotNet.WorkerThreadException: Worker thread threw an exception ---> System.ArgumentOutOfRangeException: Coordinates out of range, max={Width=399, Height=299}
Parameter name: (x,y)
Actual value was {X=400,Y=264}.
  at PaintDotNet.Surface.get_Item(Int32 x, Int32 y)
  at PaintDotNet.Effects.UserScript.Render(Surface dst, Surface src, Rectangle rect)
  at PaintDotNet.Effects.UserScript.Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, Int32 startIndex, Int32 length)
  at PaintDotNet.Effects.BackgroundEffectRenderer.RendererContext.RenderImpl()
  --- End of inner exception stack trace ---
  at PaintDotNet.Effects.BackgroundEffectRenderer.Join()
  at PaintDotNet.Menus.EffectMenuBase.DoEffect(Effect effect, EffectConfigToken token, PdnRegion selectedRegion, PdnRegion regionToRender, Surface originalSurface, Exception& exception)

The error was achieved with this image.

test-2.png

This image locks the plugin...

test2.png

0

Share this post


Link to post
Share on other sites

From first inspection, the plugin may be (dare I say after all my preaching) better than Anti-Alias. Madness it is.

And yes, I concur with barkbark00, Effects > Object would be the better location. It pairs quite nicely with pyrochild's Outline Object. Also confirming his bug, too.

Very good overall.

0

Share this post


Link to post
Share on other sites

Considering the fact that you even admit you don't understand your own code, it seems to give better results than Feather or AA plugins.

Good job!

Now... opensource it so we can help you fix those bugs :D

0

Share this post


Link to post
Share on other sites

I get the same error like barkbark00.

aaerrorvi0.png

You should publish the code like pyrochild said, he is the plugin award winner for some good reasons.

And I believe the correct place for this is "Object", too.

0

Share this post


Link to post
Share on other sites

Thanks for comments and bug report.

I'd like to publish the code, but at its current state it is so ugly that an experienced PdN plugin developer could find it obscene, and I don't want to violate again forum rule #12.

Now I'll try to fix the bug by myself, to add features and clean the code, so that I'll release the version 2.0 dll with the source. Then the developer community will possibly improve it.

About the bug: I think the error occurs only whan you antialias the entire picture and the solid shape touches the border of the canvas. The workaround is to apply Basic Antialias to a selection that doesn't touch borders.

Bye,

Pyjo.

0

Share this post


Link to post
Share on other sites

If this is a help, the picture I worked on was 1280x800. This seems to be related to "out of range 1279x799" in the way you said.

0

Share this post


Link to post
Share on other sites

Yeah, open-source it, and we (maybe) can help you solve the bug!

I met the same "coord out of range" bug too while developing my AA plugin. (fixed)

It's because when looping through pixels "around" the corners, some of them will get nasty values like "-1, -1" or "1281, 801."

Good plugin though!

Note: my AA plugin works only in "grow" mode, which means that the shape grow in size.

The more it grows the more smooth it is. 7 is the optimal (if growing doesn't matter).

0

Share this post


Link to post
Share on other sites

-EDIT-

The 1.1 release fixes the reported bug. Or, at least, I hope so. You find this new Basic Antialias in the Effects->Object submenu.

Yeah, now it works. :)

I think this is an excellent plugin, and it gives me better results than e.g. Feather (OK, that depends on the images you work on). However, it's worth a download. :wink:

0

Share this post


Link to post
Share on other sites

Now I'm all ticked off for rendering Eddie the Head before this plugin came out :roll:

Nice plugin, at first I thought the part of the moon that is absolutely diagonal (on the inside, about at the middle of the curve) looked a bit weird (~bit-weird, I can't help but think that :o), but that's the only flaw.

0

Share this post


Link to post
Share on other sites

Thanks for your comments and input for future development.

I was aware that my plugin isn't the ultimate solution against aliasing. This is why it is called "Basic Antialias" and not "Ultimate Antialias". However, I think it isn't true that lines at 45° are not antialiased at all: try to set the zoom at 800% or something and you will see that there is some (little) improvement.

By the way: I just fixed another minor bug that affected angles of about 30°. Stay connected to download the new dll when I'll publish it.

In future releases I'll try also to extend the antialiasing method used for vertical and horizontal lines to 45° lines also.

Bye,

Pyjo.

0

Share this post


Link to post
Share on other sites
vertical and horizontal lines

Should those be affected too? Those are already AA.

If you draw a Square or Rectangle block which only have vertical and horizontal outlines.

Does it / should it be affected by the plugin?

Nice plugin none the less.

0

Share this post


Link to post
Share on other sites

Sorry, it was to be intended as almost vertical and almost horizontal.

Bye

Pyjo.

0

Share this post


Link to post
Share on other sites

What I mean was, your plugin does affect vertical and horizontal lines in Squares or Rectangles.

0

Share this post


Link to post
Share on other sites

Hi Pyjo!

you know who I am...I am the one who first introduced you tu PdN :D

I have seen the plugin during "live" operation...nice results!!!

I am downloading it and testing it in a few minutes...Will let you know!!!

0

Share this post


Link to post
Share on other sites

Pyjo, this is an awesome plugin. Thank you. :-)

I do have a request to make, though. When you release newer versions, could you please just release them as the exact same filename (BasicAntialias.dll) with no version number after it? You can put the version number in the ZIP title, I have no problem with that. But if you replace the version number every time, Windows won't automatically replace the old version with the new, and then I end up having several different Basic Antialias DLL's in there. :-)

Thanks. You've done a great job.

0

Share this post


Link to post
Share on other sites

@Ash: The vertical and horizontal lines are affected by Basic Antialias, which introduces some trasparency, even if they are part of squares and rectangles. There is no need of applying this effect to those types of shape, of course. This picture helps explain how horizontal lines are affected:

AADemo.jpg

@autodafe: mica ti sarai registrato solo per far sapere a tutti che mi conosci? :) Ora pubblica qualche tua opera!

(Sorry for not having written this in english... What he says is true, however. It is due to autodafe if I spent so much time developing a plugin for PdN).

@david.atwell: Every choice has its drawbacks. By adding the version number to the dll you can always know which version you are using, but you have to manually delete old versions every time a new version is released. Starting with version 1.2 however the name of the dll will be simply "BasicAntialias.dll". Thanks for the comment.

Pyjo.

0

Share this post


Link to post
Share on other sites

I can't believe how forgotten this plugin has become. It's sad because I use it almost every day.

Great plugin!

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0