ColorBlend 问题 - 末尾有黑色条纹

ColorBlend issue - black stripe at the end

我想创建一个具有 7 级颜色和自定义大小的线性渐变 - 从黑色、蓝色、青色、绿色、黄色、红色到白色。我的问题是最终位图的右侧有一条黑色条纹。有人知道怎么回事吗?

    public static List<Color> interpolateColorScheme(int size)
    {
        // create result list with for interpolated colors
        List<Color> colorList = new List<Color>();
        // use Bitmap and Graphics from bitmap
        using (Bitmap bmp = new Bitmap(size, 200))
        using (Graphics G = Graphics.FromImage(bmp))
        {
            // create empty rectangle canvas
            Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
            // use LinearGradientBrush class for gradient computation
            LinearGradientBrush brush = new LinearGradientBrush
                                    (rect, Color.Empty, Color.Empty, 0, false);
            // setup ColorBlend object
            ColorBlend colorBlend = new ColorBlend();
            colorBlend.Positions = new float[7];
            colorBlend.Positions[0] = 0;
            colorBlend.Positions[1] = 1 / 6f;
            colorBlend.Positions[2] = 2 / 6f;
            colorBlend.Positions[3] = 3 / 6f;
            colorBlend.Positions[4] = 4 / 6f;
            colorBlend.Positions[5] = 5 / 6f;
            colorBlend.Positions[6] = 1;
            // blend colors and copy them to result color list
            colorBlend.Colors = new Color[7];
            colorBlend.Colors[0] = Color.Black;
            colorBlend.Colors[1] = Color.Blue;
            colorBlend.Colors[2] = Color.Cyan;
            colorBlend.Colors[3] = Color.Green;
            colorBlend.Colors[4] = Color.Yellow;
            colorBlend.Colors[5] = Color.Red;
            colorBlend.Colors[6] = Color.White;
            brush.InterpolationColors = colorBlend;
            G.FillRectangle(brush, rect);
            bmp.Save("gradient_debug_image_sarcus.png", ImageFormat.Png);
            for (int i = 0; i < size; i++) colorList.Add(bmp.GetPixel(i, 0));
            brush.Dispose();
        }

        // return interpolated colors
        return colorList;
    }

这是我的渐变:

我使用了你的代码并尝试了从 2 到 ushort.MaxValue 的每个尺寸,生成渐变并从右边缘扫描以确定有多少黑色像素。

对于许多尺寸,没有黑色像素。然而,对于某些连续的尺寸运行,随着尺寸的增加,黑色像素的数量也会增加。在测试范围内大约有 2140 次这样的运行。这意味着渐变绘图存在舍入误差。

这个bug以前遇到过(http://www.pcreview.co.uk/threads/error-on-lineargradientbrush.2165794/)。 link推荐的两个解决方案是

  1. 绘制比您需要的更大的渐变或
  2. 使用WrapMode.TileFlipX.

link 的错误之处在于,舍入误差始终不只是 1 个像素;在大图像尺寸下,它可以大到 127 像素(在我测试的范围内)。绘制比您需要的更大的渐变需要您知道(或估计)制作渐变需要多大。您可以尝试按 (size + Math.Ceiling(size / 512.0)) / size 缩放,这是我测试过的图像尺寸范围的误差上限。

如果您正在寻找更简单的解决方案,指定 brush.WrapMode = WrapMode.TileFlipX 将导致画笔正常绘制到渐变的(不正确的)边缘,然后反向重复渐变直到实际边缘指定的矩形。由于与矩形的大小相比舍入误差很小,这看起来像是渐变的最终颜色已扩展到矩形的边缘。从视觉上看,它看起来不错,但如果您需要非常精确的结果,它可能不适合。