简体   繁体   English

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

[英]Antialiasing when clipping an image using GDI+ in ASP.NET/C#?

I'm working on some image transformations using ASP.NET/C#/GDI+. 我正在使用ASP.NET/C#/GDI+进行一些图像转换。 I have a method that looks like this to make a rectangular image round: 我有一个看起来像这样的方法来使矩形图像变圆:

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

It takes a square image and then an ellipse is added that is as big as the image. 它拍摄一个正方形图像,然后添加一个与该图像一样大的椭圆。 I then use SetClip to remove everything that lies outside the path and return a round image. 然后,我使用SetClip删除路径外的所有内容并返回圆形图像。 This works as intended. 这按预期工作。

The returned image is then drawn onto another (larger) image at a certain position and the resulting composite image is saved as a file. 然后将返回的图像在某个位置绘制到另一个(较大)图像上,并将生成的合成图像保存为文件。 A real world example of how to use this could be adding a logo or a watermark to an existing image. 如何使用此功能的真实示例可能是在现有图像上添加徽标或水印。 Here is some code from this operation: 这是此操作的一些代码:

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

The only problem is that the edges of the superimposed/round/returned image are a bit rough. 唯一的问题是,叠加/倒圆/返回图像的边缘有些粗糙。 I'd like to make its edges smoother so it blends in better with the larger background image it's superimposed upon. 我想使其边缘更平滑,使其与叠加的较大背景图像更好地融合。

Are there any anti-aliasing parameters that I could use? 我可以使用任何抗锯齿参数吗? Do you think that this smoothing should be done in the method above or is it applied when the round image is superimposed on the bigger backdrop? 您是否认为应该使用上述方法进行这种平滑处理,还是将圆形图像叠加在较大的背景上时应用?

All pointers and tips are most welcome! 欢迎所有指针和技巧!

The technique you're looking for is called Feathering, ie: feathered edges is a form of anti-aliasing applied at the edge of a drawn image. 您正在寻找的技术称为“羽化”,即:羽化边缘是一种抗锯齿的形式,应用于绘制图像的边缘。

Take a look at this post on soft edges in GDI+ . 看看GDI +中有关软边的文章。 It may be applicable to your scenario. 它可能适用于您的方案。

Most examples you'll find for this either: 您可以找到以下大多数示例:

  1. Use a brush to draw the background, or 使用画笔绘制背景,或
  2. Use SetClip to remove the part of the image you don't want 使用SetClip删除不需要的图像部分

But there are problems with both if you want a transparent background: 但是,如果您想要透明的背景,则两者都有问题:

  1. You can't draw with a transparent brush. 您不能使用透明笔刷绘制。 It just does nothing. 它什么也没做。
  2. SetClip won't give you an anti-aliased edge, as you've noticed. 正如您所注意到的, SetClip不会给您带来抗锯齿的优势。

I found this answer that works well, but that one is designed to just round the corners, not make it a circle. 我发现这个答案很好用,但是这个答案只是为了解决问题而已,而不是圆成一个圆。 So I modified it. 所以我修改了它。

Here's how you can crop an image to a circle with a transparent background and anti-aliased edges: 这是将图像裁剪为具有透明背景和抗锯齿边缘的圆的方法:

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

Instead of trying to crop the image, this creates a new, transparent image first, then draws a cut-out of the image on top. 无需尝试裁剪图像,而是先创建一个新的透明图像,然后在顶部绘制图像的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM