LinearGradientBrush 导致非平滑渐变位图

LinearGradientBrush results in non-smooth gradient bitmap

我正在使用此函数生成一个简单的渐变位图,使用 LinearGradientBrush 我最后将其另存为文件以用作墙纸。但问题是结果看起来并不“平滑”,它看起来相当“断断续续”,因为你可以看到颜色的线条。

我使用屏幕边界作为位图的尺寸,增加尺寸并不能提高质量(我试过 2 倍甚至 4 倍)。

我尝试设置 InterpolationModeSmoothingMode,但似乎都没有对最终结果产生影响。

有办法解决这个问题吗?

    public static Bitmap GenerateGradient(Color color1, Color color2, int width, int height, LinearGradientMode mode)
    {
        Bitmap bitmap = new(width, height);
        using (Graphics graphics = Graphics.FromImage(bitmap))
        using (LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, width, height), color1, color2, mode))
        {
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.FillRectangle(brush, new Rectangle(0, 0, width, height));
        }

        return bitmap;
    }

编辑: 下面是我调用函数和保存位图的方法,在重新检查代码后我认为问题主要在于我如何生成颜色阴影。使用命名颜色代替生成的阴影后,结果更加平滑。

//Generates a random shade of the specified color 
//by randomly adjusting the alpha value.
public static Color RandomShade(Color color)
{
    var random = new Random(DateTime.Now.Millisecond);
    int alpha = random.Next(0, 255);

    return Color.FromArgb(alpha, color);
}

private void buttonGenerate_Click(object sender, EventArgs e)
{
    int width = Screen.PrimaryScreen.Bounds.Width;
    int height = Screen.PrimaryScreen.Bounds.Height;

    Color color1 = RandomShade(Color.AliceBlue);
    Color color2 = RandomShade(Color.Navy);

    var bitmap = GenerateGradient(color1, color2, width, height, LinearGradientMode.ForwardDiagonal);            

    bitmap.Save("wallpaper.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}

使用生成的阴影

使用命名颜色

问题出在 RandomShade() 方法上。通过使用 alpha 通道生成阴影,渐变也在对该通道进行插值。

我认为产生更好结果的方法是随机使用其他三个(颜色)通道使颜色变暗或变亮,并保持 alpha 不变。换句话说,只改变颜色的亮度。

例如:

public static Color RandomShadeV2(Color color)
{
    const int Range = 1000;
    const int Variance = 700;
    var random = new Random(DateTime.Now.Millisecond);
    int factor = random.Next(Range - Variance, Range + Variance + 1);
    int r = color.R * factor / Range;
    int g = color.G * factor / Range;
    int b = color.B * factor / Range;
    return Color.FromArgb(255, Math.Min(r, 255), Math.Min(g, 255), Math.Min(b, 255));
}

这将生成亮度系数介于原始颜色的 0.3 和 1.7 之间的阴影。

选择这些值作为亮度倍增器没有特别的原因。这些是我正在测试的。例如,如果您选择 0.0 到 2.0,您可能会经常获得非常暗或非常亮的阴影。 RangeVariance 常量是我用来推导亮度因子的:范围始终是整体(如 100%);方差是我允许它从那个点开始变化的,在这种情况下 700 代表 70%,所以最终的因素将在 100% - 70% = 30% = 0.3 和 100% + 70% = 170% = 1.7 之间.