颜色表算法

3

我已经搜索了一个多星期,想知道怎样创建类似于这样的东西。

enter image description here

我已经有了代码和for循环,通过X坐标和Y坐标来创建每个面板。每个面板都是数组的一部分,从左上角开始为0,到右上角结束为90。但是我不关心它是如何完成的,只要完成了并且可以使用就行。颜色不需要完全相同,但应该接近,以便我可以拥有全屏幕的颜色选择器。如果有人知道一些代码,可以将一种特定的颜色变亮十倍,并使用Color.FromARGB或只是Color类来设置面板的背景颜色,请帮助我。谢谢。

(这是我正在为Windows平板电脑制作的应用程序,支持触摸屏。该应用程序的目的是全屏幕使用,而不暴露出它是Windows平板电脑,因此我必须自己制作颜色选择器,不能使用内置的颜色对话框。)


1
你目前尝试了什么?另外,我不确定你所说的让颜色变亮10倍是什么意思。也许你应该看一下HSL颜色模型(https://en.wikipedia.org/wiki/Color_model#HSV_and_HSL_representations)? - Ruben Steins
1
一种替代颜色转换的方法是使用多彩的LinearGradientBrush,并将其与角落颜色配合使用。 - TaW
2个回答

8

为了更好的控制,我建议使用颜色计算函数。

enter image description here

有很多选择;这是我使用的其中之一:

Color HsvToRgb(double h, double S, double V)
{
    /// Convert HSV to RGB
    /// h is from 0d - 360d
    /// s,v values are 0d - 1d
    /// r,g,b values are 0 - 255

    int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
    double f = hue / 60 - Math.Floor(hue / 60);

    value = value * 255;
    int v = Convert.ToInt32(value);
    int p = Convert.ToInt32(value * (1 - saturation));
    int q = Convert.ToInt32(value * (1 - f * saturation));
    int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));

    if      (hi == 0)  return Color.FromArgb(255, v, t, p);
    else if (hi == 1)  return Color.FromArgb(255, q, v, p);
    else if (hi == 2)  return Color.FromArgb(255, p, v, t);
    else if (hi == 3)  return Color.FromArgb(255, p, q, v);
    else if (hi == 4)  return Color.FromArgb(255, t, p, v);
    else               return Color.FromArgb(255, v, p, q);
}

请注意输入范围!!
现在可以轻松设置一个类级别的Color数组:
int width = 10;
int height = 9;
Color[,] colors;

并填充它:

void loadColors()
{
    colors = new Color[width, height];

    // load greys
    for (int i = 0; i < width; i++ ) colors[i, 0] = HsvToRgb(0f, 0f, 1f * i / width);
    // load bright stripe:
    for (int i = 0; i < width; i++) colors[i, 1] = HsvToRgb(i* 360f / width, 0.33f, 1f);
    // load matrix:
    for (int j = 2; j < height; j++)
        for (int i = 0; i < width; i++) 
             colors[i, j] = HsvToRgb(i * 360f / width, 1f, 1f * (height - j + 2) / height);
}

从这里开始,设置您的面板的BackColors就轻而易举了。
以下是我用于创建上面截图的Form.Paint函数:
private void Form1_Paint(object sender, PaintEventArgs e)
{
    int w = ClientSize.Width / width;
    int h = ClientSize.Height / height;

    for (int j = 0; j < height; j++) 
        for (int i = 0; i < width; i++)
        {
            using (SolidBrush brush = new SolidBrush(colors[i,j]))
            e.Graphics.FillRectangle(brush, i * w, j * h, w, h);
        }
}

当然,只需更改两个数字即可使网格更细,这里是20x20:

enter image description here

此外,还要注意到色调的均匀间距并不起作用,因为无论是人眼还是我们常见的显示系统对光谱中色调的变化都不是同样敏感的。
事实上,眼睛对绿色色调非常敏感

在蓝绿和黄色波长中,可察觉的波长差异约为1纳米,而在较长的红色和较短的蓝色波长中则达到10纳米甚至更多

但是我们的监视器在创建不同的绿色色调方面表现得相当糟糕。
使用一个经过适应的感知均匀间距色调列表可能会有所帮助,具体取决于您想要什么。

enter image description here

使用这个一行代码:
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
    int hue = (int) ((Bitmap)pictureBox1.Image).GetPixel(e.X, e.Y).GetHue();
}

在上面的图片中,我们可以看到这样一个颜色列表:
20 32 41 50 58 72 133 163 170 177 183 190 197 206 269 288 307 324 334 346 

我稍微修改了一下,可能让它在我的显示器上更好地运行:

List<int> hues = new List<int> 
{ 20, 32, 41, 50, 58, 72, 133, 162,  180, 188, 195,  205, 215, 223, 246, 267, 288, 300, 320, 346 };

我希望你能帮忙翻译以下内容:将上述代码更改(保持宽度为20)为

HsvToRgb(hues[i],..

结果为:

enter image description here

更新:我已经用一个简化了的函数替换了HsvToRgb函数。


不是人眼,而是显示设备。需要进行伽马校正。 - Hans Passant
嗯,两者都是。但关于绿色,你是正确的;我改变了答案。 - TaW
谢谢,这个完美地运作了。我不得不修改绘制图形的那一部分(e.Graphics.FillRectangle(brush, i * w, j * h, w, h);),但是让它正常工作并不难。非常感谢你。 - user4950184
请考虑将色调循环改为使用我答案末尾的数字! - TaW
你的第一篇帖子完美地起到了作用,非常符合我的需求。不过,我在另一个程序中尝试了你最后的建议,它很有趣。我从没想到眼睛对绿色色调相当敏感。无论如何,还是谢谢你。 - user4950184
好吧,考虑到我们在丛林和大草原上生存了这么长时间,这应该是可以的。 - TaW

2
使用这个答案,您可以使用颜色的HSB表示法(也可以在这里看一下)。通过使用此方法,您可以为第一行使用随机色调、零饱和度和亮度从1.0到0.0逐步减少的数量所需的步骤。对于其他行,您必须将饱和度设为1.0,并在相同数量的步骤中从0增加到360的色调,并且每行的饱和度也要从0.0增加到1.0。我只是提供了一个示例:
private void OnResize(object sender, EventArgs e)
{
    Invalidate();
}

protected override void OnPaint(PaintEventArgs e)
{
    UpdateImage(e.Graphics);
}

private void UpdateImage(Graphics graphics)
{
    var columns = 10;
    var rows = 8;

    var hueSteps = 360 / columns;
    var columnSteps = 1.0F / columns;

    var width = Width / columns;
    var height = Height / (rows + 1);

    for (int i = 0; i < columns; i++)
    {
        var gray = ColorExtensions.FromAhsb(255, 0, 0, columnSteps * i);

        using (var brush = new SolidBrush(gray))
        {
            graphics.FillRectangle(brush, width * i, 0, width, height);
        }
    }

    for (int i = 0; i < columns; i++)
    {
        for (int j = 1; j <= rows; j++)
        {
            var color = ColorExtensions.FromAhsb(255, hueSteps * i, 1, columnSteps * j);

            using (var brush = new SolidBrush(color))
            {
                graphics.FillRectangle(brush, width * i, height * j, width, height);
            }
        }
    }
}

结果并不完全相同,但只需要重新排列循环即可:color table

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