如何在特定范围内生成随机颜色?

enxuqcxy  于 2021-06-29  发布在  Java
关注(0)|答案(3)|浏览(384)

我查看了不同的来源:
在java中创建随机颜色?
如何在java中创建随机颜色
如何在java中随机化颜色?
“随机颜色生成器javascript堆栈溢出”代码答案
然而,这些答案都不是我要寻找的。
我想做的是得到一个随机的颜色范围内的2种颜色,例如紫色和粉红色。紫色的存在 #6A0DAD 粉红色的存在 #FFC0CB ,我想在这两种颜色的范围内获取一种颜色,但是随机获取一种。所以我举个例子 #D982B5 ,是洋红色。
到目前为止,除了做一个随机发生器,我还不知道从哪里开始。

bf1o4zei

bf1o4zei1#

正如我所评论的,“中间”在颜色方面并没有很好的定义。
然而,一种可能但可能无用的方法是取每个分量(r、g和b)并在两种颜色的值之间生成一个随机值。
请注意,除非颜色在hsv色轮上相对接近,否则结果很有可能不是您认为的“介于”之间的东西。什么是“中间人” 0xff0000 以及 0x00ffff ? 如果你能提供任何3个人都认为介于红色和青色之间的东西,我会非常惊讶。
以你为例


# 6A0DAD

# FFC0CB

生成一个新的颜色,其中r分量介于 0x6A 以及 0xFF (106..255)之间的绿色分量 0x0D 以及 0xC0 (13..192),以及 0xAD 以及 0xCB (173..203).

hsgswve4

hsgswve42#

热释光;博士:
没那么简单。颜色是你看到可见光时所感知到的东西。形成一种颜色的是不同波长的光。为了用数字表示颜色,我们使用了不同的颜色空间,例如rgb、cmyk、ycbcr等。所有这些颜色空间都进行了简化,以表示物理(或生物)属性。
当你说“颜色介于两者之间”时,它可能意味着很多事情:一个波长介于两个波长之间。在一个特定的颜色空间中,介于两种其他色调之间的色调。根据你的经验和感知,你“期望”介于两种颜色之间的颜色。由两种颜色混合而成的颜色。要混合颜色,一个好的方法是使用加法混合,但在一个颜色空间。然而,在“颜色之间”,这可能是有缺陷的,这取决于你想要什么。
以下是一些值得一读的相关帖子:
有没有一种混合颜色的算法可以像混合真颜色一样工作?
rgb混合色的计算
rgb值的加性混色算法
颜色梯度算法
较长版本:
首先想到的是简单地在rgb中获取两种颜色的每个通道,并在相应通道的值之间生成一个随机值:例如,您获取颜色 #6A0DAD 以及 #FFC0CB . 红色通道的值为 106 以及 255 . 所以新颜色的红色通道的值应该是介于 106 以及 255 . 这种幼稚的方法有一个问题:结果之间的数字 #6A0DAD 、紫色和 #FFC0CB ,粉色,可能是 #6AC0AD ,是汽油色。汽油绝对不是一种你会认为是“介于紫色和粉色之间”的颜色。
其原因是rgb颜色空间具有由所有三个通道表示的颜色的色调:正是通道的平衡构成了色调。当我们为新颜色的每个通道在相应的范围内生成一个随机数时,结果颜色的色调可能会完全不同,因为它可能来自通道的完全不同的平衡。
另一种方法是将我们正在处理的颜色空间更改为通过单个通道表示色调的颜色空间。一个这样的颜色空间是hsl/hsv。我们要做的是:将这两个数字转换成等价的hsb。然后为每个通道生成随机数,就像我们在rgb中所做的那样。请注意,通道的平衡并不重要,因为色调由单个通道表示。然后将结果转换回rgb。
下面是一个简单的java演示:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;

class Main {

    static int[] purple = {106, 13, 173};
    static int[] pink = {255, 192, 203};

    static float randomBetween(float a, float b) {
        float min = Math.min(a, b);
        float max = Math.max(a, b);
        return min + (max - min) * (float) Math.random();
    }

    static Color colorBetween(int[] a, int[] b) {
        float[] a_hsb = Color.RGBtoHSB(a[0], a[1], a[2], null);
        float[] b_hsb = Color.RGBtoHSB(b[0], b[1], b[2], null);
        float[] between_hsb = {
                randomBetween(a_hsb[0], b_hsb[0]),
                randomBetween(a_hsb[1], b_hsb[1]),
                randomBetween(a_hsb[2], b_hsb[2])
        };
        return new Color(
                Color.HSBtoRGB(
                        between_hsb[0],
                        between_hsb[1],
                        between_hsb[2]));
    }

    public static void main(String args[]) {
        Color purple_color = new Color(purple[0], purple[1], purple[2]);
        Color pink_color = new Color(pink[0], pink[1], pink[2]);
        Color between_color = colorBetween(purple, pink);

        JFrame frame = new JFrame();
        GridLayout layout = new GridLayout(2, 2);
        frame.setLayout(layout);

        JLabel purple_label = new JLabel();
        purple_label.setBackground(purple_color);
        purple_label.setOpaque(true);
        frame.add(purple_label);

        JLabel pink_label = new JLabel();
        pink_label.setBackground(pink_color);
        pink_label.setOpaque(true);
        frame.add(pink_label);

        JLabel between_label = new JLabel();
        between_label.setBackground(between_color);
        between_label.setOpaque(true);
        frame.add(between_label);

        frame.addMouseListener(new MouseAdapter() {  
            public void mouseClicked(MouseEvent e) {  
               between_label.setBackground(colorBetween(purple, pink));
            }  
        }); 

        frame.setSize(1000, 1000);
        frame.setVisible(true);
    }
}

单击框架以重新创建新颜色。左上角是紫色,右上角是粉色,结果是左下角。


正如你应该看到的,结果肯定是一种颜色,你会称之为至少“在同一调色板”。但这仍然有一个问题:我们也在调整hsb的亮度和饱和度。我们最初的粉色饱和度很低,而紫色饱和度很高。问题是,结果可能是相同的粉红色,但高度饱和,这看起来非常红。这“似乎”不对。
另一种方法是回到rgb并尊重通道的平衡。实际上,这并不是什么新鲜事。它被称为混合,这是渲染中显示透明度的常用技术。
这里有同样的示范,但有一个调整 colorBetween 方法:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;

class Main {

    static int[] purple = {106, 13, 173};
    static int[] pink = {255, 192, 203};

    static Color colorBetween(int[] a, int[] b) {
        double c_a = Math.random();
        double c_b = 1.0 - c_a;

        int[] blend = {
                (int) (c_a * a[0] + c_b * b[0]),
                (int) (c_a * a[1] + c_b * b[1]),
                (int) (c_a * a[2] + c_b * b[2]),
        };

        return new Color(blend[0], blend[1], blend[2]);
    }

    public static void main(String args[]) {
        Color purple_color = new Color(purple[0], purple[1], purple[2]);
        Color pink_color = new Color(pink[0], pink[1], pink[2]);
        Color between_color = colorBetween(purple, pink);

        JFrame frame = new JFrame();
        GridLayout layout = new GridLayout(2, 2);
        frame.setLayout(layout);

        JLabel purple_label = new JLabel();
        purple_label.setBackground(purple_color);
        purple_label.setOpaque(true);
        frame.add(purple_label);

        JLabel pink_label = new JLabel();
        pink_label.setBackground(pink_color);
        pink_label.setOpaque(true);
        frame.add(pink_label);

        JLabel between_label = new JLabel();
        between_label.setBackground(between_color);
        between_label.setOpaque(true);
        frame.add(between_label);

        frame.addMouseListener(new MouseAdapter() {  
            public void mouseClicked(MouseEvent e) {  
               between_label.setBackground(colorBetween(purple, pink));
            }  
        }); 

        frame.setSize(1000, 1000);
        frame.setVisible(true);
    }
}


请注意,结果不再是一个高度饱和的粉红色“似乎是错误的”。你所做的只是使用一个随机因子 c_a 那是介于 0.0 以及 1.0 还有一个因素 c_b 就是这样 1.0 - c_a . 你把每个通道的颜色都放大 ac_a ,对 b 以及 c_b 并添加结果。这是一个简单的缩放一个恒定的因素,这有一个渠道的平衡不变的效果颜色。添加结果后,您将拥有一个新的颜色平衡,它是 a 以及 b .
另一种方法是减法:把每一个通道的颜色叠加起来 a 通过相应的颜色通道 b 除以 255 .
或者另一种附加方法:将通道添加到一起,如果是,则将其作为结果 <= 255 ,否则采取 255 .
... 等等等等。。。
请注意,当最初的两种颜色接近另一种颜色时,所有这些方法都能相对较好地工作。在其他一些情况下会变得很困难:红色, (255, 0, 0) ,和青色, (0, 255, 255) ,是互补色。加法方法将产生白色。减法将导致黑色。对于“中间”的颜色,让我们看看色调(来自维基百科的hsb/hsl图像):

你可以看到红色在左边和右边。当我们想要在颜色空间之间选择一种色调时,颜色空间所做的简化现在很麻烦。我们选择0之间的颜色吗° 和180° 或者我们选一个180度之间的颜色° 和360°? 我展示的第一个示例将从下半部分选择一种颜色。你可以很好地理解为什么两种颜色接近另一种会产生一个好的结果和颜色远离将产生一个坏的结果。
一个完美的例子: (255, 0, 0) 以及 (255, 0, 50) ,红色和粉色,会产生任何颜色:绿色、蓝色、黄色等等。你能做什么来解决它是看距离和增加360度° 如果需要的话。e、 g.颜色 a 色调为10° 和颜色 b 色调350° 会变成颜色 a 与370° 以及 b 还有350°. 此范围内随机选取的色调(模360)是新颜色的色调。
我的建议是使用混合方法,因为它产生的结果来自一个加法方法,它更接近可见光的工作原理,不会像其他一些方法那样不适当地增加亮度。

hsvhsicv

hsvhsicv3#

它需要一个十六进制颜色如何排序的主观定义。
请参阅本页的十六进制颜色分类为他们。
基本上,您不能根据十六进制的数值对其进行分类,因为数字接近的十六进制数字在颜色上可能有很大的不同。
又是一个人类思维方式与计算机不同的插曲。
我创建了一个功能齐全的java程序来满足您的请求。你想把它附在这里吗?我不想用未经请求的代码压倒你。
它可以输入十六进制代码或颜色名称,并且可以返回伪随机十六进制代码、颜色名称或我们所感知的颜色之间的可渲染颜色(不像akuzminykh恰当地说的“紫色和粉色之间的汽油”)。

相关问题