使用.NET的渐晕图像效果算法

发布于 2024-08-17 11:43:11 字数 157 浏览 1 评论 0 原文

我想知道如何使用 C# 和 .NET 在图片上创建渐晕效果

有谁知道如何做到这一点?或者是否有任何资源可以为我完成算法?

I'd like to know how I create a vignetting effect on a picture using C# and .NET.

Does anyone have any ideas how to do this? Or are there any resources that will have the algorithm already done for me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凉月流沐 2024-08-24 11:43:11

我相信这会满足您的要求:

public void PaintVignette(Graphics g, Rectangle bounds)
{
    Rectangle ellipsebounds = bounds;
    ellipsebounds.Offset(-ellipsebounds.X, -ellipsebounds.Y);
    int x = ellipsebounds.Width - (int)Math.Round(.70712 * ellipsebounds.Width);
    int y = ellipsebounds.Height - (int)Math.Round(.70712 * ellipsebounds.Height);
    ellipsebounds.Inflate(x, y);

    using (GraphicsPath path = new GraphicsPath())
    {
        path.AddEllipse(ellipsebounds);
        using (PathGradientBrush brush = new PathGradientBrush(path))
        {
            brush.WrapMode = WrapMode.Tile;
            brush.CenterColor = Color.FromArgb(0, 0, 0, 0);
            brush.SurroundColors = new Color[] { Color.FromArgb(255, 0, 0, 0) };
            Blend blend = new Blend();
            blend.Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F };
            blend.Factors = new float[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f };
            brush.Blend = blend;
            Region oldClip = g.Clip;
            g.Clip = new Region(bounds);
            g.FillRectangle(brush, ellipsebounds);
            g.Clip = oldClip;
        }
    }
}

public Bitmap Vignette(Bitmap b)
{
    Bitmap final = new Bitmap(b);
    using (Graphics g = Graphics.FromImage(final)) {
        PaintVignette(g, new Rectangle(0, 0, final.Width, final.Height));
        return final;
    }
}

这里发生了什么?首先,我编写了用从白色到黑色的椭圆渐变画笔填充矩形的代码。然后我修改了代码,以便填充区域也包括角点。我通过增加矩形尺寸与 sqrt(2)/2 * 矩形尺寸之间的差值来实现此目的。

为什么要开方(2)/2?因为点(sqrt(2)/2, sqrt(2)/2)是单位圆上的45度角点。按宽度和高度缩放给出了膨胀矩形以确保其被完全覆盖所需的距离。

然后我调整渐变的混合,使其中心更加白色。

然后我将颜色从白色更改为纯透明黑色,从黑色更改为纯不透明黑色。这具有将远角涂成黑色并且在到达中心的过程中阴影较少的效果。

最后,我编写了一个在位图上运行的实用程序方法(我还没有测试这部分 - 我在面板上的图形上测试了代码,但我认为它在这里也可以工作。

I believe this will do what you want:

public void PaintVignette(Graphics g, Rectangle bounds)
{
    Rectangle ellipsebounds = bounds;
    ellipsebounds.Offset(-ellipsebounds.X, -ellipsebounds.Y);
    int x = ellipsebounds.Width - (int)Math.Round(.70712 * ellipsebounds.Width);
    int y = ellipsebounds.Height - (int)Math.Round(.70712 * ellipsebounds.Height);
    ellipsebounds.Inflate(x, y);

    using (GraphicsPath path = new GraphicsPath())
    {
        path.AddEllipse(ellipsebounds);
        using (PathGradientBrush brush = new PathGradientBrush(path))
        {
            brush.WrapMode = WrapMode.Tile;
            brush.CenterColor = Color.FromArgb(0, 0, 0, 0);
            brush.SurroundColors = new Color[] { Color.FromArgb(255, 0, 0, 0) };
            Blend blend = new Blend();
            blend.Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F };
            blend.Factors = new float[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f };
            brush.Blend = blend;
            Region oldClip = g.Clip;
            g.Clip = new Region(bounds);
            g.FillRectangle(brush, ellipsebounds);
            g.Clip = oldClip;
        }
    }
}

public Bitmap Vignette(Bitmap b)
{
    Bitmap final = new Bitmap(b);
    using (Graphics g = Graphics.FromImage(final)) {
        PaintVignette(g, new Rectangle(0, 0, final.Width, final.Height));
        return final;
    }
}

What's going on here? First I wrote code that would fill a rectangle with an elliptical gradient brush that went from white to black. Then I modified the code so that the filled area would also include the corners. I did this by increasing the rectangle size by the difference between the rectangle dimensions and sqrt(2)/2 * the rectangle dimensions.

Why sqrt(2)/2? Because the point (sqrt(2)/2, sqrt(2)/2) is the 45 degree angle point on a unit circle. Scaling by the width and height gives the distance needed to inflate the rect to make sure it's fully covered.

Then I adjusted the Blend of the gradient to be much more white in the center.

Then I changed the color from white to pure transparent black and from black to pure opaque black. This has the effect of painting the far corners black and shade less on the way in to the center.

Finally, I wrote a utility method that runs on a Bitmap (I haven't tested this part - I tested the code on a graphics from a Panel, but I think it will work here too.

枕头说它不想醒 2024-08-24 11:43:11

如果您的图片位于文件中,并且速度足以满足您的要求,则可以使用 convert rel="nofollow noreferrer">ImageMagick,它有一个选项-vignette。要从 C# 程序中调用它,您可以通过 System.Diagnostics.Process.Start 运行它,或者使用 this 。 NET 包装器 ImageMagick。

If your picture is in a file, and if that is fast enough for your requirements, you can use the command line tool convert of ImageMagick, it has an option -vignette. To call this from within a C# program, you can run it via System.Diagnostics.Process.Start, or you use this .NET wrapper for ImageMagick.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文