我正在寻找一种简单的算法来生成大量随机的、美观的颜色。所以没有疯狂的霓虹灯颜色,让人联想到粪便的颜色等等。

我已经找到了这个问题的解决方案,但它们依赖于替代调色板而不是RGB。 我宁愿直接使用RGB,而不是来回映射。这些其他解决方案也最多只能生成32种左右令人愉悦的随机颜色。

任何想法都很好。


当前回答

转换到另一个调色板是一种更好的方式。他们这样做是有原因的:其他调色板是“感性的”——也就是说,他们把相似的颜色放在一起,调整一个变量会以可预测的方式改变颜色。对于RGB来说,这些都不是真的,在RGB中,颜色之间没有明显的“搭配良好”的关系。

其他回答

从算法上很难得到你想要的东西——人们研究颜色理论已经很长时间了,他们甚至不知道所有的规则。

然而,有一些规则可以用来剔除糟糕的颜色组合(例如,有冲突的颜色和选择互补的颜色的规则)。

我建议你去图书馆的艺术区看看关于色彩理论的书籍,在你尝试一个好颜色之前更好地理解什么是好颜色——看起来你甚至不知道为什么某些组合有效,而另一些则不行。

亚当

转换到另一个调色板是一种更好的方式。他们这样做是有原因的:其他调色板是“感性的”——也就是说,他们把相似的颜色放在一起,调整一个变量会以可预测的方式改变颜色。对于RGB来说,这些都不是真的,在RGB中,颜色之间没有明显的“搭配良好”的关系。

下面是c#中的一个快速而肮脏的颜色生成器(使用本文中描述的“RYB方法”)。这是JavaScript重写的。

Use:

List<Color> ColorPalette = ColorGenerator.Generate(30).ToList();

前两种颜色往往是白色和暗色的黑色。我经常这样跳过它们(使用Linq):

List<Color> ColorsPalette = ColorGenerator
            .Generate(30)
            .Skip(2) // skip white and black
            .ToList(); 

实现:

public static class ColorGenerator
{

    // RYB color space
    private static class RYB
    {
        private static readonly double[] White = { 1, 1, 1 };
        private static readonly double[] Red = { 1, 0, 0 };
        private static readonly double[] Yellow = { 1, 1, 0 };
        private static readonly double[] Blue = { 0.163, 0.373, 0.6 };
        private static readonly double[] Violet = { 0.5, 0, 0.5 };
        private static readonly double[] Green = { 0, 0.66, 0.2 };
        private static readonly double[] Orange = { 1, 0.5, 0 };
        private static readonly double[] Black = { 0.2, 0.094, 0.0 };

        public static double[] ToRgb(double r, double y, double b)
        {
            var rgb = new double[3];
            for (int i = 0; i < 3; i++)
            {
                rgb[i] = White[i]  * (1.0 - r) * (1.0 - b) * (1.0 - y) +
                         Red[i]    * r         * (1.0 - b) * (1.0 - y) +
                         Blue[i]   * (1.0 - r) * b         * (1.0 - y) +
                         Violet[i] * r         * b         * (1.0 - y) +
                         Yellow[i] * (1.0 - r) * (1.0 - b) *        y +
                         Orange[i] * r         * (1.0 - b) *        y +
                         Green[i]  * (1.0 - r) * b         *        y +
                         Black[i]  * r         * b         *        y;
            }

            return rgb;
        }
    }

    private class Points : IEnumerable<double[]>
    {
        private readonly int pointsCount;
        private double[] picked;
        private int pickedCount;

        private readonly List<double[]> points = new List<double[]>();

        public Points(int count)
        {
            pointsCount = count;
        }

        private void Generate()
        {
            points.Clear();
            var numBase = (int)Math.Ceiling(Math.Pow(pointsCount, 1.0 / 3.0));
            var ceil = (int)Math.Pow(numBase, 3.0);
            for (int i = 0; i < ceil; i++)
            {
                points.Add(new[]
                {
                    Math.Floor(i/(double)(numBase*numBase))/ (numBase - 1.0),
                    Math.Floor((i/(double)numBase) % numBase)/ (numBase - 1.0),
                    Math.Floor((double)(i % numBase))/ (numBase - 1.0),
                });
            }
        }

        private double Distance(double[] p1)
        {
            double distance = 0;
            for (int i = 0; i < 3; i++)
            {
                distance += Math.Pow(p1[i] - picked[i], 2.0);
            }

            return distance;
        }

        private double[] Pick()
        {
            if (picked == null)
            {
                picked = points[0];
                points.RemoveAt(0);
                pickedCount = 1;
                return picked;
            }

            var d1 = Distance(points[0]);
            int i1 = 0, i2 = 0;
            foreach (var point in points)
            {
                var d2 = Distance(point);
                if (d1 < d2)
                {
                    i1 = i2;
                    d1 = d2;
                }

                i2 += 1;
            }

            var pick = points[i1];
            points.RemoveAt(i1);

            for (int i = 0; i < 3; i++)
            {
                picked[i] = (pickedCount * picked[i] + pick[i]) / (pickedCount + 1.0);
            }

            pickedCount += 1;
            return pick;
        }

        public IEnumerator<double[]> GetEnumerator()
        {
            Generate();
            for (int i = 0; i < pointsCount; i++)
            {
                yield return Pick();
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public static IEnumerable<Color> Generate(int numOfColors)
    {
        var points = new Points(numOfColors);

        foreach (var point in points)
        {
            var rgb = RYB.ToRgb(point[0], point[1], point[2]);
            yield return Color.FromArgb(
                (int)Math.Floor(255 * rgb[0]),
                (int)Math.Floor(255 * rgb[1]),
                (int)Math.Floor(255 * rgb[2]));
        }
    }
}

使用色彩分明的颜色。

用javascript编写。

它生成了一个视觉上不同颜色的调色板。

Distinct-colors是高度可配置的:

选择调色板中有多少种颜色 将色调限制在一个特定的范围内 限制色度(饱和度)到一个特定的范围 将亮度限制在一个特定的范围内 配置调色板的一般质量

function fnGetRandomColour(iDarkLuma, iLightLuma) 
{       
  for (var i=0;i<20;i++)
  {
    var sColour = ('ffffff' + Math.floor(Math.random() * 0xFFFFFF).toString(16)).substr(-6);

    var rgb = parseInt(sColour, 16);   // convert rrggbb to decimal
    var r = (rgb >> 16) & 0xff;  // extract red
    var g = (rgb >>  8) & 0xff;  // extract green
    var b = (rgb >>  0) & 0xff;  // extract blue

    var iLuma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709


    if (iLuma > iDarkLuma && iLuma < iLightLuma) return sColour;
  }
  return sColour;
} 

对于粉彩,传入更高亮度的暗/亮整数-即fnGetRandomColour(120,250)

学分:所有学分归 http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black