7

目前,我正在成功地使用Graphics该类来绘制一个非矩形的裁剪图像(里面的乌龟):

在此处输入图像描述

我的代码看起来像:

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

这一切都按预期工作。我不知道如何解决是使图像边框抗锯齿。

放大后的图像如下:

在此处输入图像描述

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

我的问题是:

是否可以剪切绘制的图像并激活抗锯齿功能?

4

4 回答 4

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);
    }
}
于 2013-09-27T14:39:31.073 回答
2

如果您想要透明背景,则此处的其他答案将不起作用,因为您无法使用透明画笔进行绘制 - 它没有任何作用。

我找到了可以做到这一点的其他答案(例如,使用SetClip),但它没有出现抗锯齿边缘。

我发现这个答案是可行的,但它的设计只是为了圆角,而不是让它成为一个圆圈。所以我修改了它。

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

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

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

于 2019-07-26T16:18:45.440 回答
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;
    }
于 2019-03-28T20:28:31.257 回答
0

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

是黑客吗?是的。它是高性能的吗?嗯,应该不会吧。它有效吗?完美!

于 2018-03-22T22:08:25.660 回答