绘制剪裁图像时可能会出现抗锯齿效果吗?

时间:2013-09-27 14:18:45

标签: c# .net graphics system.drawing clipping

目前,我已成功使用Graphics class绘制非矩形剪裁图像(里面的乌龟):

enter image description here

我的代码类似于:

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);
        }
    }
}

这一切都与预期一样有效。我不知道如何解决的问题是使图像边框消除锯齿。

缩放的图像看起来像:

enter image description here

即。图像结束的边界和图像的透明“背景”开始是粗剪,而不是平滑的alpha混合。

我的问题是:

是否可以剪切绘制的图像并使抗锯齿处于活动状态?

4 个答案:

答案 0 :(得分:6)

如果你想要完整的羽毛,你应该考虑看一下这篇文章:

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

如果您想要一个快速简便的解决方案,您可以先绘制图像,然后使用带有抗锯齿的纯白色画笔在其上绘制一个GraphicsPath。你会做这样的事情:

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);
    }
}

答案 1 :(得分:1)

我想分享我的解决方案,该解决方案基于所选答案。 此代码将抗锯齿功能应用于边缘,将图像调整大小并将其裁剪为圆形。它还可以防止鼠标悬停或窗口调整大小时图像丢失。裁剪的图像可以轻松保存。

    /// <summary>Redimensiona y recorta la imagen en forma de Circulo (con Antialias).</summary>
    /// <param name="srcImage">Imagen Original a Recortar</param>
    /// <param name="size">Tamaño deseado (en pixeles)</param>
    /// <param name="BackColor">Color de fondo</param>
    public static Image CropToCircle(System.Drawing.Image srcImage, Size size, System.Drawing.Color BackColor)
    {
        System.Drawing.Image Canvas = new System.Drawing.Bitmap(size.Width, size.Height, srcImage.PixelFormat);
        System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(Canvas);

        System.Drawing.Rectangle outerRect = new System.Drawing.Rectangle(-1, -1, Canvas.Width + 1, Canvas.Height + 1);
        System.Drawing.Rectangle rect = System.Drawing.Rectangle.Inflate(outerRect, -2, -2);

        g.DrawImage(srcImage, outerRect);

        using (System.Drawing.SolidBrush brush = new System.Drawing.SolidBrush(BackColor))
        using (System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath())
        {
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

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

            g.FillPath(brush, path);
        }

        return Canvas;
    }

用法:(所需大小为64x64像素,白色背景)

    System.Drawing.Image img = System.Drawing.Image.FromFile(@"E:\Mis Documentos\Mis imágenes\ergo-proxy-fullon-fight.jpg");
    System.Drawing.Image circle = Util.CropToCircle(img, new System.Drawing.Size(64,64), System.Drawing.Color.White);
    if (circle != null)
    {
        this.picUser.Image = circle;
    }

答案 2 :(得分:1)

如果您想要透明的背景,那么这里的其他答案将不起作用,因为您无法使用透明的笔刷进行绘制-它什么也没做。

我找到了其他可以做到的答案(例如,使用SetClip),但是它没有消除锯齿的边缘。

我发现this answer可以用,但是那只不过是在拐角处而不是变成一个圆而设计。所以我修改了它。

以下是将图像裁剪为具有透明背景和抗锯齿边缘的圆的方法:

/// <summary>
/// Crop the given image into a circle (or ellipse, if the image isn't square)
/// </summary>
/// <param name="img">The image to modify</param>
/// <returns>The new, round image</returns>
private static Bitmap CropCircle(Image img) {
    var roundedImage = new Bitmap(img.Width, img.Height, img.PixelFormat);

    using (var g = Graphics.FromImage(roundedImage))
    using (var gp = new GraphicsPath()) {
        g.Clear(Color.Transparent);

        g.SmoothingMode = SmoothingMode.AntiAlias;

        Brush brush = new TextureBrush(img);
        gp.AddEllipse(0, 0, img.Width, img.Height);
        g.FillPath(brush, gp);
    }

    return roundedImage;
}

其他答案在图像顶部绘制背景色。相反,这将首先创建一个新的透明图像,然后在顶部绘制图像的一部分。

答案 3 :(得分:0)

我在构建具有透明背景的圆形轮廓图时遇到了同样的问题。我最终确定的策略是将图像调整为任意倍数(在我的情况下为5x),执行剪切操作,然后在使用SmoothingMode.AntiAlias时将其缩小回原始大小。我在画面上得到了很好的羽毛边缘。

是黑客吗?是。它表现得好吗?嗯,可能不是。它有用吗?完美!