在ASP.NET / C#中使用GDI +剪切图像时进行抗锯齿?

时间:2012-01-31 11:11:25

标签: c# asp.net graphics gdi+ antialiasing

我正在使用ASP.NET/C#/GDI+进行一些图像转换。我有一个看起来像这样的方法来制作一个矩形图像:

public static Image MakeRound(Image img)
{
    Bitmap bmp = new Bitmap(img.Width, img.Height);

    GraphicsPath gp = new GraphicsPath();
    Graphics gr = Graphics.FromImage(bmp);

    using (gp)
    {
        gp.AddEllipse(0, 0, img.Width, img.Height);
        using (gr)
        {
            gr.SetClip(gp);
            gr.DrawImage(img, Point.Empty);
        }
    }
    return bmp;
}

它需要一个方形图像,然后添加一个与图像一样大的椭圆。然后我使用SetClip删除路径之外的所有内容并返回一个圆形图像。这按预期工作。

然后将返回的图像绘制到特定位置的另一个(较大的)图像上,并将得到的合成图像保存为文件。如何使用它的真实示例可以是为现有图像添加徽标或水印。以下是此操作的一些代码:

// Get backdrop image from server
string backdropPath = Server.MapPath("/img/backdrop.jpg");
System.Drawing.Image backdrop = Bitmap.FromFile(backdropPath);

// Create a graphics object to work with
Graphics gra = Graphics.FromImage(backdrop);
gra.DrawImage(MakeRound(smallerImage), new Point(50,50));

// Save the new image
backdrop.Save(saveFilePath);

唯一的问题是叠加/圆形/返回图像的边缘有点粗糙。我想让它的边缘更平滑,以便它与叠加的更大的背景图像更好地融合。

我可以使用任何抗锯齿参数吗?你认为这种平滑应该在上面的方法中完成,还是在圆形图像叠加在更大的背景上时应用?

欢迎所有指针和提示!

3 个答案:

答案 0 :(得分:1)

您正在寻找的技术称为羽化,即:羽化边缘是应用于绘制图像边缘的一种抗锯齿形式。

soft edges in GDI+上查看此帖子。它可能适用于您的方案。

答案 1 :(得分:0)

答案 2 :(得分:0)

您可以找到以下大多数示例:

  1. 使用画笔绘制背景,或
  2. 使用SetClip删除不需要的图像部分

但是如果您想要透明的背景,则两者都有问题:

  1. 您不能使用透明笔刷进行绘制。它什么也没做。
  2. 正如您所注意到的,
  3. 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;
}

这不是尝试裁剪图像,而是先创建一个新的透明图像,然后在顶部绘制图像的一部分。