Possible to have anti-aliasing when drawing a clip

2019-02-17 11:45发布

问题:

Currently, I'm successfully using the Graphics class to draw a non-rectangular clipped image (the turtle inside):

My code looks something like:

using (var g = Graphics.FromImage(image))
{
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;

    using (var gfxPath = new GraphicsPath())
    {
        gfxPath.AddEllipse(r);

        using (var region = new Region(r))
        {
            region.Exclude(gfxPath);

            g.ExcludeClip(region);

            g.DrawImage(turtleImage, r, r2, GraphicsUnit.Pixel);
        }
    }
}

This all works just as expected. What I do not know how to solve is to make the image border anti-aliased.

The image zoomed looks like:

I.e. the border where the image ends and the transparent "background" of the image starts is a rough cut, not a smooth alpha blending.

My question is:

Is it possible to clip a drawn image and having anti-aliasing active?

回答1:

If you want to go for full blown feathering you should consider taking a look at this article:

http://danbystrom.se/2008/08/24/soft-edged-images-in-gdi/

If you want a quick and easy solution you could probably draw the image first then draw a GraphicsPath on top of it using a solid white brush with antialiasing. You would do something like this:

Rectangle outerRect = ClientRectangle;
Rectangle rect = Rectangle.Inflate(outerRect, -20, -20);

using (Image img = new Bitmap("test.jpg"))
{
    g.DrawImage(img, outerRect);

    using (SolidBrush brush = new SolidBrush(Color.White))
    using (GraphicsPath path = new GraphicsPath())
    {
        g.SmoothingMode = SmoothingMode.AntiAlias;

        path.AddEllipse(rect);
        path.AddRectangle(outerRect);

        g.FillPath(brush, path);
    }
}


回答2:

I had the same issue with constructing a circular profile picture with a transparent background. The tactic I finally settled on was to resize the image to an arbitrary multiple (in my case 5x), do the clipping operation, then shrink it back to the original size while using SmoothingMode.AntiAlias. I get a nicely feathered edge on the picture.

Is it a hack? Yes. Is it performant? Mmm, probably not. Does it work? Perfectly!