如何在C#/ Winforms中将图像裁剪为圆形?

7

编辑:在“重复”问题中给出的代码对我没有解决问题。

我遇到的主要问题是我不能简单地使用CSS和border-radius属性,这本来很容易。这是一个在WinForms页面/项目中加载的图像。我必须试图将一个正方形/矩形图像变成圆形。我尝试了以下两种方法(每种方法的结果将发布在下面):

public Image RoundCorners(Image StartImage, int CornerRadius, Color BackgroundColor)
{
    CornerRadius *= 2;
    Bitmap RoundedImage = new Bitmap(StartImage.Width, StartImage.Height);

    using (Graphics g = Graphics.FromImage(RoundedImage))
    {
        g.Clear(BackgroundColor);
        g.SmoothingMode = SmoothingMode.AntiAlias;

        Brush brush = new TextureBrush(StartImage);

        GraphicsPath gp = new GraphicsPath();
        gp.AddArc(0, 0, CornerRadius, CornerRadius, 180, 90);
        gp.AddArc(0 + RoundedImage.Width - CornerRadius, 0, CornerRadius, CornerRadius, 270, 90);
        gp.AddArc(0 + RoundedImage.Width - CornerRadius, 0 + RoundedImage.Height - CornerRadius, CornerRadius, CornerRadius, 0, 90);
        gp.AddArc(0, 0 + RoundedImage.Height - CornerRadius, CornerRadius, CornerRadius, 90, 90);
        g.FillPath(brush, gp);

        return RoundedImage;
    }
}

被调用的代码:

Image StartImage = Image.FromFile(medwImg);
Image RoundedImage = btn.RoundCorners(StartImage, 100, Color.Transparent);
btn.NormalImage = RoundedImage;

结果: RoundCorners 如果将半径值更改为145,您可以看到以下结果: RoundCorners145 正如您所见,这种方法也不好。
这是我的第二种方法:
public Image CropToCircle(Image srcImage, Color backGround)
{
    Image dstImage = new Bitmap(srcImage.Width, srcImage.Height, srcImage.PixelFormat);
    Graphics g = Graphics.FromImage(dstImage);

    using (Brush br = new SolidBrush(backGround))
    {
        g.FillRectangle(br, 0, 0, dstImage.Width, dstImage.Height);
    }

    GraphicsPath path = new GraphicsPath();
    path.AddEllipse(0, 0, dstImage.Width, dstImage.Height);
    g.SetClip(path);
    g.DrawImage(srcImage, 0, 0);        

    return dstImage;
}

被调用的代码:

Image StartImage = Image.FromFile(medwImg);
Image RoundedImage = btn.CropToCircle(StartImage, Color.FromArgb(0, 101, 167));
btn.NormalImage = RoundedImage;

这里的结果如下: CropToCircle
看起来更好了,但仍不是一个漂亮的完整圆。 我最好的猜测是第二种方法最接近一个好的解决方案,但我不知道接下来该怎么做才能从源图像创建一个完整的圆形。

最简单的方法是遍历所有像素,并检查每个像素是否满足 x^2 + y^2 < distance^2。如果是,则该像素在内。 - JBeurer
https://learn.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-use-clipping-with-a-region - Hans Passant
1个回答

16

我已经找到了解决我的问题的答案,使用以下方法:

// makes nice round ellipse/circle images from rectangle images
public Image ClipToCircle(Image srcImage, PointF center, float radius, Color backGround)
{
    Image dstImage = new Bitmap(srcImage.Width, srcImage.Height, srcImage.PixelFormat);

    using (Graphics g = Graphics.FromImage(dstImage))
    {
        RectangleF r = new RectangleF(center.X - radius, center.Y - radius,
                                                 radius * 2, radius * 2);

        // enables smoothing of the edge of the circle (less pixelated)
        g.SmoothingMode = SmoothingMode.AntiAlias;

        // fills background color
        using (Brush br = new SolidBrush(backGround))
        {
            g.FillRectangle(br, 0, 0, dstImage.Width, dstImage.Height);
        }

        // adds the new ellipse & draws the image again 
        GraphicsPath path = new GraphicsPath();
        path.AddEllipse(r);
        g.SetClip(path);
        g.DrawImage(srcImage, 0, 0);

        return dstImage;
    }
}

调用该方法的代码:

Image StartImage = Image.FromFile(medwImg);
Image RoundedImage = btn.ClipToCircle(StartImage, new PointF(StartImage.Width/2, StartImage.Height/2), StartImage.Width/2, Color.FromArgb(0, 101, 167));
btn.NormalImage = RoundedImage;

现在我获得了漂亮的圆形图片(结果):

圆形图片成功


7
由于 GraphicsPath 包含未托管的 GDI 资源,因此你应该调用 pathDispose 方法(或使用 using 语句)。GraphicsPath 实现了 IDisposable 接口。 - Bradley Uffner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接