代码之家  ›  专栏  ›  技术社区  ›  SIMEL

RGB中混合颜色的计算

  •  33
  • SIMEL  · 技术社区  · 14 年前

    我想能够采取两个RGB-256矢量,并计算其混合结果。同时,我希望能够给每个向量赋予不同的权重。我用“色板”这个词做了实验,我发现有些颜色确实是按照加权平均值混合的:

    0.5*red(255,0,0) + 0.5*yellow(255,255,0) = orange(255,127,0)

    其他人没有:

    0.5*yellow(255,255,0) + 0.5*blue(0,0,255) = gray (127,127,127) 而不是 green (0,255,0)

    是否有一种算法可以精确计算所有颜色,或者我必须使用查找表来进行计算?

    11 回复  |  直到 14 年前
        1
  •  32
  •   Cody Gray    14 年前

    最好的解释是 RGB color model 有点 直觉性 为了我们人类。
    这是完全合乎逻辑的视频显示设备(如监视器或电视),只知道如何显示颜色混合不同数量的3种预定义颜色:红色,绿色和蓝色。但这不是你和我在小学时学会混合颜色的方法。

    在RGB中,白色表示为(255,255,255),相当于“全部打开”。显示每个红色、绿色和蓝色分量的完整值,这将产生如此高的光强度,以至于我们将颜色视为白色。相反,当不显示彩色灯光(0)、结果为黑色或没有颜色时,黑色(0、0、0)是显示设备的“默认”状态。

    当您完全混合黄色(255,255,0)和蓝色(0,0,255)时,您将得到由(255,255,255)表示的颜色,或者 白色 . 当你把白色乘以0.5,你得到一个灰色,因为255*0.5=127。

    这可能比你在红色和黄色混合时得到预期结果的异常。红色+黄色是(510,255,0),所以当你乘以0.5,你得到橙色(255,127,0)。

    事实证明,你和我在小学学到的东西实际上更准确地说是 subtractive color model ,与 additive color model 由RGB使用。查看底部的两个图表,您将看到左侧的RGB颜色模型(加法),而右侧的CMYK颜色模型(减法)。你应该能立即看出问题所在。相反,使用减色模型将生成所需的结果。

    RGB Color Model CMYK Color Model

    编辑: 当然,说起来容易做起来难。也就是说,即使采用CMYK颜色模型而不是RGB(这已经很困难了,因为从RGB到CMYK的转换是 沉重地 这可能仍然无法满足将纯蓝色(0,0,255)与纯黄色(255,255,0)混合并获得绿色的冲动。CMYK使用青色、洋红和黄色作为3种原色,而不是红色、黄色和蓝色。你有一个 许多 如果你想实施 RYB color model 用你选择的语言。

    我不知道有任何这样的算法结合RGB颜色的现实。我试图在我的回答中解释为什么这是不可能的,或者至少是极其困难的。你可以让这个问题再开放几天,看看其他人是否有任何想法,但如果你需要坚持使用RGB模型,我会先从那个查找表开始。;-)

        2
  •  3
  •   Community pid    7 年前

    基于此 documented response 还有这个 alghoritm aware response ,我尝试了一个简单的界面,使用加法和减法混合颜色。

    您必须确认RGB和CMYK的原色为您提供了第一个响应图中的第二种颜色:

    • 红色+蓝色=品红(添加)
    • 黄色+青色=绿色(减法)
    • 等等。。。
    import javax.swing.*;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.CompoundBorder;
    import javax.swing.border.LineBorder;
    import javax.swing.border.MatteBorder;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Hashtable;
    import java.util.Vector;
    
    /**
     * Color Mixing alghoritms
     * User: alberto
     * Date: 29/01/13
     * Time: 21:28
     */
    public class ColorMix {
    
        Vector<JLabel> firstMixColors;
        Vector<JLabel> secondMixColors;
        JComboBox/*<Mixer>*/ comboBox;
        JLabel firstMixColor;
        JLabel firstSel;
        JLabel secondSel;
        JLabel finalColor;
    
        public ColorMix() {
            firstMixColors = new Vector<JLabel>();
            Vector<Mixer> mixers = new Vector<Mixer>();
            mixers.add(new AdditiveMixer());
            mixers.add(new SustractiveMixer());
            mixers.add(new TertiaryMixer());
            mixers.add(new DilutingSustractiveMixer());
    
            comboBox = new JComboBox(new DefaultComboBoxModel(mixers));
            firstMixColor = buildColorLabel();
            firstSel = buildColorLabel();
            secondSel = buildColorLabel();
            secondMixColors = new Vector<JLabel>();
            secondMixColors.add(firstSel);
            secondMixColors.add(secondSel);
            finalColor = buildColorLabel();
            comboBox.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    calculateMixes();
                }
            });
            buildGUI();
        }
    
        private JLabel buildColorLabel() {
            JLabel label = new JLabel();
            label.setOpaque(true);
            label.setHorizontalAlignment(SwingConstants.CENTER);
            label.setHorizontalTextPosition(SwingConstants.CENTER);
            label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
            label.setPreferredSize(new Dimension(100,25));
            return label;
        }
    
        public void buildGUI() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frame.setTitle("Mixing colors");
    
            frame.setLayout(new GridBagLayout());
            GridBagConstraints cc = new GridBagConstraints();
            cc.fill = GridBagConstraints.BOTH;
            cc.insets = new Insets(5, 5, 5, 5);
            cc.weightx = .2;
            cc.weighty = 1;
            frame.getContentPane().add(buildColorPanel(0), cc);
            frame.getContentPane().add(buildColorPanel(1), cc);
            cc.gridy = 1;
            JPanel firstMix = new JPanel(new GridBagLayout());
            GridBagConstraints ccCol = new GridBagConstraints();
            ccCol.fill = GridBagConstraints.BOTH;
            ccCol.insets = new Insets(5, 5, 5, 5);
            ccCol.weightx = 1;
            ccCol.weighty = 1;
    
            ccCol.gridx = 0;
            ccCol.gridy = 0;
            ccCol.gridheight = 2;
            firstMix.add(firstMixColor, ccCol);
            ccCol.fill = GridBagConstraints.HORIZONTAL;
            ccCol.weightx = 0.2;
            ccCol.weighty = 0.5;
            ccCol.gridx = 1;
            ccCol.gridy = 0;
            ccCol.gridheight = 1;
            ccCol.gridwidth = 1;
            firstMix.add(new JButton(new AbstractAction("Set First") {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setBackgroundToLabel(firstSel, firstMixColor.getBackground());
                    calculateMixes();
                }
            }), ccCol);
            ccCol.gridx = 1;
            ccCol.gridy = 1;
            firstMix.add(new JButton(new AbstractAction("Set Second") {
                @Override
                public void actionPerformed(ActionEvent e) {
                    setBackgroundToLabel(secondSel, firstMixColor.getBackground());
                    calculateMixes();
                }
            }), ccCol);
            firstMix.setBorder(BorderFactory.createTitledBorder("Secondary Colors"));
            frame.getContentPane().add(firstMix, cc);
            cc.weightx = .6;
    
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints ccColor = new GridBagConstraints();
            ccColor.fill = GridBagConstraints.BOTH;
            ccColor.insets = new Insets(5, 5, 5, 5);
            ccColor.weightx = 1;
            ccColor.weighty = 1;
            panel.add(firstSel, ccColor);
            ccColor.gridx = 1;
            panel.add(secondSel, ccColor);
            ccColor.gridx = 0;
            ccColor.gridy = 1;
            ccColor.weighty = 0;
            ccColor.gridwidth = 2;
            panel.add(finalColor, ccColor);
            ccColor.gridy = 2;
            panel.add(comboBox, ccColor);
            panel.setBorder(BorderFactory.createTitledBorder("Tertiary Colors"));
            frame.getContentPane().add(panel, cc);
            frame.pack();
            frame.setVisible(true);
        }
    
    
        public static void main(String[] args) {
            new ColorMix();
        }
    
        private JComponent buildColorPanel(int selectedIndex) {
            final JLabel pColor = buildColorLabel();
            firstMixColors.add(pColor);
            JPanel pSelectColor = new JPanel(new GridBagLayout());
            GridBagConstraints cc = new GridBagConstraints();
            cc.fill = GridBagConstraints.BOTH;
            cc.insets = new Insets(5, 5, 5, 5);
            cc.weightx = 1;
            cc.weighty = 1;
            final JSlider slidRed = buildSlider(pSelectColor, cc);
            final JSlider slidGreen = buildSlider(pSelectColor, cc);
            final JSlider slidBlue = buildSlider(pSelectColor, cc);
            pSelectColor.add(pColor, cc);
            final JComboBox comboColores = buildColorCombo();
            comboColores.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Color color = (Color) comboColores.getSelectedItem();
                    slidRed.setValue(color.getRed());
                    slidGreen.setValue(color.getGreen());
                    slidBlue.setValue(color.getBlue());
                }
            });
            comboColores.setSelectedIndex(selectedIndex);
            cc.gridy = 1;
            cc.gridwidth = 4;
            cc.weighty = 0;
            pSelectColor.add(comboColores, cc);
            ChangeListener changeListener = new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    setBackgroundToLabel(pColor, new Color(slidRed.getValue(), slidGreen.getValue(), slidBlue.getValue()));
                    calculateMixes();
                }
            };
            slidRed.addChangeListener(changeListener);
            slidGreen.addChangeListener(changeListener);
            slidBlue.addChangeListener(changeListener);
            pSelectColor.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
            changeListener.stateChanged(null);
            return pSelectColor;
        }
    
        private JComboBox buildColorCombo() {
            Color TRANSPARENT = new Color(0, 0, 0, 0);
    
            Vector<Color> colors = new Vector<Color>();
    
            colors.add(new NamedColor(Color.RED, "Red"));
            colors.add(new NamedColor(Color.GREEN, "Green"));
            colors.add(new NamedColor(Color.BLUE, "Blue"));
    
            colors.add(new NamedColor(Color.YELLOW, "Yellow"));
            colors.add(new NamedColor(Color.MAGENTA, "Magenta"));
            colors.add(new NamedColor(Color.CYAN, "Cyan"));
    
            colors.add(new NamedColor(Color.WHITE, "White"));
            colors.add(new NamedColor(Color.LIGHT_GRAY, "Light Gray"));
            colors.add(new NamedColor(Color.GRAY, "Gray"));
            colors.add(new NamedColor(Color.DARK_GRAY, "Dark Gray"));
            colors.add(new NamedColor(Color.BLACK, "Black"));
            colors.add(new NamedColor(Color.PINK, "Pink"));
            colors.add(new NamedColor(Color.ORANGE, "Orange"));
    
            colors.add(new NamedColor(TRANSPARENT, "transparent"));
            //http://www.w3schools.com/css/css_colornames.asp
            colors.add(new NamedColor(new Color(0xf0f8ff), "aliceblue"));
            colors.add(new NamedColor(new Color(0xfaebd7), "antiquewhite"));
            colors.add(new NamedColor(new Color(0x00ffff), "aqua"));
            colors.add(new NamedColor(new Color(0x7fffd4), "aquamarine"));
            colors.add(new NamedColor(new Color(0xf0ffff), "azure"));
            colors.add(new NamedColor(new Color(0xf5f5dc), "beige"));
            colors.add(new NamedColor(new Color(0xffe4c4), "bisque"));
            colors.add(new NamedColor(new Color(0x000000), "black"));
            colors.add(new NamedColor(new Color(0xffebcd), "blanchedalmond"));
            colors.add(new NamedColor(new Color(0x0000ff), "blue"));
            colors.add(new NamedColor(new Color(0x8a2be2), "blueviolet"));
            colors.add(new NamedColor(new Color(0xa52a2a), "brown"));
            colors.add(new NamedColor(new Color(0xdeb887), "burlywood"));
            colors.add(new NamedColor(new Color(0x5f9ea0), "cadetblue"));
            colors.add(new NamedColor(new Color(0x7fff00), "chartreuse"));
            colors.add(new NamedColor(new Color(0xd2691e), "chocolate"));
            colors.add(new NamedColor(new Color(0xff7f50), "coral"));
            colors.add(new NamedColor(new Color(0x6495ed), "cornflowerblue"));
            colors.add(new NamedColor(new Color(0xfff8dc), "cornsilk"));
            colors.add(new NamedColor(new Color(0xdc143c), "crimson"));
            colors.add(new NamedColor(new Color(0x00ffff), "cyan"));
            colors.add(new NamedColor(new Color(0x00008b), "darkblue"));
            colors.add(new NamedColor(new Color(0x008b8b), "darkcyan"));
            colors.add(new NamedColor(new Color(0xb8860b), "darkgoldenrod"));
            colors.add(new NamedColor(new Color(0xa9a9a9), "darkgray"));
            colors.add(new NamedColor(new Color(0xa9a9a9), "darkgrey"));
            colors.add(new NamedColor(new Color(0x006400), "darkgreen"));
            colors.add(new NamedColor(new Color(0xbdb76b), "darkkhaki"));
            colors.add(new NamedColor(new Color(0x8b008b), "darkmagenta"));
            colors.add(new NamedColor(new Color(0x556b2f), "darkolivegreen"));
            colors.add(new NamedColor(new Color(0xff8c00), "darkorange"));
            colors.add(new NamedColor(new Color(0x9932cc), "darkorchid"));
            colors.add(new NamedColor(new Color(0x8b0000), "darkred"));
            colors.add(new NamedColor(new Color(0xe9967a), "darksalmon"));
            colors.add(new NamedColor(new Color(0x8fbc8f), "darkseagreen"));
            colors.add(new NamedColor(new Color(0x483d8b), "darkslateblue"));
            colors.add(new NamedColor(new Color(0x2f4f4f), "darkslategray"));
            colors.add(new NamedColor(new Color(0x2f4f4f), "darkslategrey"));
            colors.add(new NamedColor(new Color(0x00ced1), "darkturquoise"));
            colors.add(new NamedColor(new Color(0x9400d3), "darkviolet"));
            colors.add(new NamedColor(new Color(0xff1493), "deeppink"));
            colors.add(new NamedColor(new Color(0x00bfff), "deepskyblue"));
            colors.add(new NamedColor(new Color(0x696969), "dimgray"));
            colors.add(new NamedColor(new Color(0x696969), "dimgrey"));
            colors.add(new NamedColor(new Color(0x1e90ff), "dodgerblue"));
            colors.add(new NamedColor(new Color(0xb22222), "firebrick"));
            colors.add(new NamedColor(new Color(0xfffaf0), "floralwhite"));
            colors.add(new NamedColor(new Color(0x228b22), "forestgreen"));
            colors.add(new NamedColor(new Color(0xff00ff), "fuchsia"));
            colors.add(new NamedColor(new Color(0xdcdcdc), "gainsboro"));
            colors.add(new NamedColor(new Color(0xf8f8ff), "ghostwhite"));
            colors.add(new NamedColor(new Color(0xffd700), "gold"));
            colors.add(new NamedColor(new Color(0xdaa520), "goldenrod"));
            colors.add(new NamedColor(new Color(0x808080), "gray"));
            colors.add(new NamedColor(new Color(0x808080), "grey"));
            colors.add(new NamedColor(new Color(0x008000), "green"));
            colors.add(new NamedColor(new Color(0xadff2f), "greenyellow"));
            colors.add(new NamedColor(new Color(0xf0fff0), "honeydew"));
            colors.add(new NamedColor(new Color(0xff69b4), "hotpink"));
            colors.add(new NamedColor(new Color(0xcd5c5c), "indianred"));
            colors.add(new NamedColor(new Color(0x4b0082), "indigo"));
            colors.add(new NamedColor(new Color(0xfffff0), "ivory"));
            colors.add(new NamedColor(new Color(0xf0e68c), "khaki"));
            colors.add(new NamedColor(new Color(0xe6e6fa), "lavender"));
            colors.add(new NamedColor(new Color(0xfff0f5), "lavenderblush"));
            colors.add(new NamedColor(new Color(0x7cfc00), "lawngreen"));
            colors.add(new NamedColor(new Color(0xfffacd), "lemonchiffon"));
            colors.add(new NamedColor(new Color(0xadd8e6), "lightblue"));
            colors.add(new NamedColor(new Color(0xf08080), "lightcoral"));
            colors.add(new NamedColor(new Color(0xe0ffff), "lightcyan"));
            colors.add(new NamedColor(new Color(0xfafad2), "lightgoldenrodyellow"));
            colors.add(new NamedColor(new Color(0xd3d3d3), "lightgray"));
            colors.add(new NamedColor(new Color(0xd3d3d3), "lightgrey"));
            colors.add(new NamedColor(new Color(0x90ee90), "lightgreen"));
            colors.add(new NamedColor(new Color(0xffb6c1), "lightpink"));
            colors.add(new NamedColor(new Color(0xffa07a), "lightsalmon"));
            colors.add(new NamedColor(new Color(0x20b2aa), "lightseagreen"));
            colors.add(new NamedColor(new Color(0x87cefa), "lightskyblue"));
            colors.add(new NamedColor(new Color(0x778899), "lightslategray"));
            colors.add(new NamedColor(new Color(0x778899), "lightslategrey"));
            colors.add(new NamedColor(new Color(0xb0c4de), "lightsteelblue"));
            colors.add(new NamedColor(new Color(0xffffe0), "lightyellow"));
            colors.add(new NamedColor(new Color(0x00ff00), "lime"));
            colors.add(new NamedColor(new Color(0x32cd32), "limegreen"));
            colors.add(new NamedColor(new Color(0xfaf0e6), "linen"));
            colors.add(new NamedColor(new Color(0xff00ff), "magenta"));
            colors.add(new NamedColor(new Color(0x800000), "maroon"));
            colors.add(new NamedColor(new Color(0x66cdaa), "mediumaquamarine"));
            colors.add(new NamedColor(new Color(0x0000cd), "mediumblue"));
            colors.add(new NamedColor(new Color(0xba55d3), "mediumorchid"));
            colors.add(new NamedColor(new Color(0x9370d8), "mediumpurple"));
            colors.add(new NamedColor(new Color(0x3cb371), "mediumseagreen"));
            colors.add(new NamedColor(new Color(0x7b68ee), "mediumslateblue"));
            colors.add(new NamedColor(new Color(0x00fa9a), "mediumspringgreen"));
            colors.add(new NamedColor(new Color(0x48d1cc), "mediumturquoise"));
            colors.add(new NamedColor(new Color(0xc71585), "mediumvioletred"));
            colors.add(new NamedColor(new Color(0x191970), "midnightblue"));
            colors.add(new NamedColor(new Color(0xf5fffa), "mintcream"));
            colors.add(new NamedColor(new Color(0xffe4e1), "mistyrose"));
            colors.add(new NamedColor(new Color(0xffe4b5), "moccasin"));
            colors.add(new NamedColor(new Color(0xffdead), "navajowhite"));
            colors.add(new NamedColor(new Color(0x000080), "navy"));
            colors.add(new NamedColor(new Color(0xfdf5e6), "oldlace"));
            colors.add(new NamedColor(new Color(0x808000), "olive"));
            colors.add(new NamedColor(new Color(0x6b8e23), "olivedrab"));
            colors.add(new NamedColor(new Color(0xffa500), "orange"));
            colors.add(new NamedColor(new Color(0xff4500), "orangered"));
            colors.add(new NamedColor(new Color(0xda70d6), "orchid"));
            colors.add(new NamedColor(new Color(0xeee8aa), "palegoldenrod"));
            colors.add(new NamedColor(new Color(0x98fb98), "palegreen"));
            colors.add(new NamedColor(new Color(0xafeeee), "paleturquoise"));
            colors.add(new NamedColor(new Color(0xd87093), "palevioletred"));
            colors.add(new NamedColor(new Color(0xffefd5), "papayawhip"));
            colors.add(new NamedColor(new Color(0xffdab9), "peachpuff"));
            colors.add(new NamedColor(new Color(0xcd853f), "peru"));
            colors.add(new NamedColor(new Color(0xffc0cb), "pink"));
            colors.add(new NamedColor(new Color(0xdda0dd), "plum"));
            colors.add(new NamedColor(new Color(0xb0e0e6), "powderblue"));
            colors.add(new NamedColor(new Color(0x800080), "purple"));
            colors.add(new NamedColor(new Color(0xff0000), "red"));
            colors.add(new NamedColor(new Color(0xbc8f8f), "rosybrown"));
            colors.add(new NamedColor(new Color(0x4169e1), "royalblue"));
            colors.add(new NamedColor(new Color(0x8b4513), "saddlebrown"));
            colors.add(new NamedColor(new Color(0xfa8072), "salmon"));
            colors.add(new NamedColor(new Color(0xf4a460), "sandybrown"));
            colors.add(new NamedColor(new Color(0x2e8b57), "seagreen"));
            colors.add(new NamedColor(new Color(0xfff5ee), "seashell"));
            colors.add(new NamedColor(new Color(0xa0522d), "sienna"));
            colors.add(new NamedColor(new Color(0xc0c0c0), "silver"));
            colors.add(new NamedColor(new Color(0x87ceeb), "skyblue"));
            colors.add(new NamedColor(new Color(0x6a5acd), "slateblue"));
            colors.add(new NamedColor(new Color(0x708090), "slategray"));
            colors.add(new NamedColor(new Color(0x708090), "slategrey"));
            colors.add(new NamedColor(new Color(0xfffafa), "snow"));
            colors.add(new NamedColor(new Color(0x00ff7f), "springgreen"));
            colors.add(new NamedColor(new Color(0x4682b4), "steelblue"));
            colors.add(new NamedColor(new Color(0xd2b48c), "tan"));
            colors.add(new NamedColor(new Color(0x008080), "teal"));
            colors.add(new NamedColor(new Color(0xd8bfd8), "thistle"));
            colors.add(new NamedColor(new Color(0xff6347), "tomato"));
            colors.add(new NamedColor(new Color(0x40e0d0), "turquoise"));
            colors.add(new NamedColor(new Color(0xee82ee), "violet"));
            colors.add(new NamedColor(new Color(0xf5deb3), "wheat"));
            colors.add(new NamedColor(new Color(0xffffff), "white"));
            colors.add(new NamedColor(new Color(0xf5f5f5), "whitesmoke"));
            colors.add(new NamedColor(new Color(0xffff00), "yellow"));
            colors.add(new NamedColor(new Color(0x9acd32), "yellowgreen"));
    
            JComboBox comboBox = new JComboBox(new DefaultComboBoxModel(colors));
            comboBox.setRenderer(new DefaultListCellRenderer() {
                protected Color backgroundColor = Color.BLACK;
    
                {
                    setBorder(new CompoundBorder(
                            new MatteBorder(2, 5, 2, 5, Color.white)
                            , new LineBorder(Color.black)));
                }
    
                public Component getListCellRendererComponent(JList list, Object obj,
                                                              int row, boolean sel, boolean hasFocus) {
                    if (obj instanceof Color)
                        backgroundColor = (Color) obj;
                    setText(obj.toString());
                    return this;
                }
    
                public void paint(Graphics g) {
                    setBackground(backgroundColor);
                    super.paint(g);
                }
            });
    
    
            return comboBox;
        }
    
        class NamedColor extends Color {
            private String name;
    
            NamedColor(Color color, String name) {
                super(color.getRed(), color.getGreen(), color.getBlue());
                this.name = name;
            }
    
            @Override
            public String toString() {
                return name;
            }
        }
    
        private void calculateMixes() {
            calculateFirstMix();
            calculateSecondMix();
        }
    
        private void calculateFirstMix() {
            calculateMix(firstMixColors, firstMixColor);
        }
    
        private void calculateSecondMix() {
            calculateMix(secondMixColors, finalColor);
        }
    
        private void calculateMix(Vector<JLabel> mixColors, JLabel finalColor) {
            Color bg = ((Mixer) comboBox.getSelectedItem()).calculateMix(mixColors);
            setBackgroundToLabel(finalColor, bg);
        }
    
        private void setBackgroundToLabel(JLabel label, Color color) {
            label.setBackground(color);
            label.setText(color.getRed() + "," + color.getGreen() + "," + color.getBlue());
        }
    
        interface Mixer {
            Color calculateMix(Vector<JLabel> colores);
        }
    
        /**
         * Implement a additive mix of colors
         */
        static class AdditiveMixer implements Mixer {
            public Color calculateMix(Vector<JLabel> colores) {
                int red = 0;
                int green = 0;
                int blue = 0;
                for (int i = 0; i < colores.size(); i++) {
                    Color background = colores.get(i).getBackground();
                    red += background.getRed();
                    green += background.getGreen();
                    blue += background.getBlue();
                }
                return new Color(Math.min(255, red), Math.min(255, green), Math.min(255, blue));
            }
    
            @Override
            public String toString() {
                return "Additive";
            }
        }
    
        /**
         * Implement a sustractive mix of colors
         */
        static class SustractiveMixer implements Mixer {
            public Color calculateMix(Vector<JLabel> colores) {
                int red = 1;
                int green = 1;
                int blue = 1;
                for (int i = 0; i < colores.size(); i++) {
                    Color background = colores.get(i).getBackground();
                    red *= background.getRed();
                    green *= background.getGreen();
                    blue *= background.getBlue();
                }
                return new Color(Math.min(255, red / 255), Math.min(255, green / 255), Math.min(255, blue / 255));
            }
    
            @Override
            public String toString() {
                return "Sustractive";
            }
        }
    
        /**
         * Implement a diluting/sustractive mix of colors
         */
        static class DilutingSustractiveMixer implements Mixer {
            public Color calculateMix(Vector<JLabel> colores) {
                int red = 0;
                int green = 0;
                int blue = 0;
                for (int i = 0; i < colores.size(); i++) {
                    Color background = colores.get(i).getBackground();
                    red += Math.pow(255 - background.getRed(), 2);
                    green += Math.pow(255 - background.getGreen(), 2);
                    blue += Math.pow(255 - background.getBlue(), 2);
                }
                return new Color(Math.min(255, (int)Math.sqrt(red / colores.size())), Math.min(255, (int)Math.sqrt(green / colores.size())), Math.min(255, (int)Math.sqrt(blue / colores.size())));
            }
    
            @Override
            public String toString() {
                return "Diluting/Sustractive";
            }
        }
    
        /**
         * Implement a diluting/sustractive mix of colors
         */
        static class TertiaryMixer implements Mixer {
            public Color calculateMix(Vector<JLabel> colores) {
                Color background1 = colores.get(0).getBackground();
                int red = background1.getRed();
                int green = background1.getGreen();
                int blue = background1.getBlue();
                Color background2 = colores.get(1).getBackground();
                red -= background2.getRed();
                green -= background2.getGreen();
                blue -= background2.getBlue();
                return new Color(Math.min(255, background1.getRed() - (red/2)), Math.min(255, background1.getGreen() - (green/2)), background1.getBlue() - (blue/2));
            }
    
            @Override
            public String toString() {
                return "Tertiary";
            }
        }
    
        private JSlider buildSlider(JPanel container, GridBagConstraints upperCC) {
            JPanel panel = new JPanel(new GridBagLayout());
            GridBagConstraints cc = new GridBagConstraints();
            cc.fill = GridBagConstraints.BOTH;
            cc.insets = new Insets(5, 5, 5, 5);
            cc.weightx = 1;
            cc.weighty = 0.7;
    
            final JSlider slider = new JSlider(JSlider.VERTICAL, 0, 255, 0);
            slider.setFont(new Font("Serif", Font.PLAIN, 4));
    
            Hashtable<Integer, JLabel> labels = new Hashtable<Integer, JLabel>();
            labels.put(0, new JLabel("0"));
            labels.put(128, new JLabel("128"));
            labels.put(255, new JLabel("255"));
            panel.add(slider, cc);
            final JTextField field = new JTextField();
            field.setEditable(false);
            slider.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    field.setText(String.valueOf(slider.getValue()));
                }
            });
            cc.gridx = 0;
            cc.gridy = 1;
            cc.weighty = 0;
    
            panel.add(field, cc);
            slider.setLabelTable(labels);
            slider.setPaintLabels(true);
    
            container.add(panel, upperCC);
    
            return slider;
        }
    }
    

    Color Mixing Interface

    基本上,这种操作类似于逻辑和和逻辑或。(不完全是)

    • 在additive alghoritm上,颜色重叠,但对于每个primary,它只能是255(逻辑或操作)
    • 在相减的alghoritm上,如果没有某个主元素,结果将不会有那个(青色没有红色,黄色没有蓝色:你得到绿色)(逻辑和操作)

    基于 this 你可以从主色和副色的混合中获得三次色,所以我做了一个很好的小实现:

    NewColor.R = Color1.R - (Color1.R - Color2.R)/2
    NewColor.G = Color1.G - (Color1.G - Color2.G)/2
    NewColor.B = Color1.B - (Color1.B - Color2.B)/2
    

    在第二次引用的回复中也提到了稀释/减量化的alghoritm,但我不能说它是基于什么,只是添加到测试中。

        3
  •  3
  •   nh43de    8 年前

    真正的答案是将RGB颜色向量空间改为一个相加的空间,然后再改回RGB。在这个新的向量空间中,当你添加两个光向量时,它会考虑到光的相加特性和我们对颜色的感知,从而产生相加的颜色。

    结果证明CIE-XYZ向量空间在这方面工作得很好。

    XYZ向量在这个空间中是相加的,并且像光源一样混合。

    this paper on color mixing 克里:

    X_mix = X1 + X2 + ...
    
    Y_mix = Y1 + Y2 + ...
    
    Z_mix = Z1 + Z2 + ...
    

    然后你可以把基础改回RGB。有许多库可用于改变矢量空间之间的颜色,CIEXYZ是标准化的,并得到广泛支持。

    这种方法产生了符合我大多数目的的实际结果。

    有关的详细信息 CIE 1931 color space .

        4
  •  2
  •   alxx    14 年前

    看着科迪·格雷的回答,我想我可以建议如何组合颜色。将色轮转换为RGB:

                    cyan(0, 255, 255)
            blue(0, 0, 255) green(0, 255, 0)
    magenta(255, 0, 255) red(255, 0, 0) yellow(255, 255, 0)
    

    无需额外的复杂操作,颜色可以这样组合:反转两种颜色,将它们相加并反转结果(ActionScript):

    sum(0, 255, 255,   255, 0, 255, "cyan + magenta =");
    sum(255, 0, 0,     0, 255, 0,   "red + green =");
    sum(0, 0, 0,       0, 0, 0,     "black + black =");
    sum(0, 0, 0,       255, 255, 255, "black + white =");
    
    function sum(c1:int, c2:int, c3:int, b1:int, b2:int, b3:int, m:String):void {
        c1 = 255 - c1; c2 = 255 - c2; c3 = 255 - c3;
        b1 = 255 - b1; b2 = 255 - b2; b3 = 255 - b3;
        var d1:int = c1 + b1;
        var d2:int = c2 + b2;
        var d3:int = c3 + b3;
        d1 = 255 - d1; d2 = 255 - d2; d3 = 255 - d3;
        d1 = clamp(d1); d2 = clamp(d2); d3 = clamp(d3);
        trace(m, d1, d2, d3);
    }
    
    function clamp(value:int):int {
        if (value < 0) return 0;
        if (value > 255) return 255;
        return value;
    }
    

    输出:

    cyan + magenta = 0 0 255
    red + green = 0 0 0
    black + black = 0 0 0
    black + white = 0 0 0
    

    看看那是否适合你。

    编辑:我不是假装这是正确的,这只是一个近似的尝试。查找表的想法对我来说听起来很疯狂,原因有两个:它依赖于两个参数,因此它的大小将非常大;自然法则通常是连续的,没有或很少有角的情况。如果你能填充查找表,你应该知道算法-所以只要写一个函数。

        5
  •  2
  •   Ian Boyd    9 年前

    我只是想指出为什么你加上 蓝色 . 因为你在 蓝色 ,而不是 青色 :

    enter image description here

    • 如果你加上 青色 到黄色,你得到 绿色
    • 如果你加上 蓝色 (即青色+红色)到黄色,就变成灰色。

    或者,更精确地说:

    Yellow + (Cyan          ) = Green  
    Yellow + (Cyan + Magenta) = Gray
    Yellow + (Blue)           = Gray
    

    你正在添加 蓝色 ,当您打算添加 青色 .

    0.5*Yellow(255,255,0) + 0.5*Cyan(0,255,255) = VeryLightLimeGreen(128,255,128)
    
        6
  •  1
  •   Damien Del Russo    13 年前

    我认为上面的答案没有给出足够的混合结果。

    我一直在研究这个问题与RGB和RYB(从RGB转换后)。在这里,RGB到RYB的转换是好的: http://www.insanit.net/tag/rgb-to-ryb/ (如有要求,我将分享我的代码)。

    如果混合轻,这并不太坏(见下文)。如果你想混合成物理材料,比如油漆 小的 更棘手的是-我正在开发一个应用程序来探索它。

    回到原来的问题——这是我的RGB混合代码。RgbColor是一个自定义类,但我认为这本身是有意义的:

    -(RgbColor*)mixWith:(RgbColor *)aColor {
        int r1, g1, b1, r2, g2, b2, r3, g3, b3, m1, m2, w1, w2, w3; //colors and maxes, white
        float br; // brightness of resulting color
    
    r1 = self.redVal;
    g1 = self.greenVal;
    b1 = self.blueVal;
    r2 = aColor.redVal;
    g2 = aColor.greenVal;
    b2 = aColor.blueVal;
    
    w1 = MIN(r1, MIN(g1, b1));
    w2 = MIN(r2, MIN(g2, b2));
    
    // remove white before mixing
    r1 -= w1;
    g1 -= w1;
    b1 -= w1;
    r2 -= w2;
    g2 -= w2;
    b2 -= w2;
    
    m1 = MAX(r1, MAX(g1, b1));
    m2 = MAX(r2, MAX(g2, b2));
    
    br = (m1+m2)/(2*255.0);
    
    r3 = (r1+r2)*br;
    g3 = (g1+g2)*br;
    b3 = (b1+b2)*br;
    
    // average whiteness and add into final color
    w3 = (w1+w2)/2;
    
    r3 += w3;
    g3 += w3;
    b3 += w3;
    
    [self setRedVal:[[NSNumber numberWithFloat:r3] intValue]];
    [self setGreenVal:[[NSNumber numberWithFloat:g3] intValue]];
    [self setBlueVal:[[NSNumber numberWithFloat:b3] intValue]];
    return self;
    }
    
        7
  •  1
  •   Ben Holland Hossam Ali    12 年前

    这里是一个Java实现的KuBelka蒙克理论的反射混合RGB颜色。此实现使用Kubelka-Munk模型的简化版本,该模型假设所有颜色在混合时具有相同的浓度,并且所有颜色都是不透明的。

    https://github.com/benjholla/ColorMixer

        8
  •  0
  •   user502515    14 年前

    混合黄色(红色+绿色)和蓝色 根据物理赋予白色,参见 http://en.wikipedia.org/wiki/Additive_color .

        9
  •  0
  •   JP19JP19    14 年前

    RGB模型中的“黄色”与RYB模型中的黄色不同,RYB模型中的黄色与蓝色混合时应该显示绿色。

    例如,(255, 255, 0)在RGB模型中(约)为(0, 0, 255)的两倍,而在RYB模型中,相等量的黄和蓝应该是绿色的。 同样,红色和蓝色在这两款车型上也是不同的。

    把它们看作向量空间RGB和R'Y'B。

    如果某种关系像:

    R = i1*R' + j1*Y' + k1*B';
    G = i2*R' + j2*Y' + k2*B';
    B = i3*R' + j3*Y' + k3*B';
    

    好的,你可以先把各个颜色(操作数)从RGB转换成R'Y'B'空间来完成你的代数。

    有9个未知数(i,j,k变量),所以需要9个方程(这两个空间中有3个颜色等式)。

    不幸的是, 我想 模型不能线性缩放,因此为了精确起见,可能必须使用查找表。

    另一个好主意可能是转换成HSV或YCbCr空间,因为颜色信息在这些空间中被更清晰地提取出来。(如果存在RGB到RYB转换,那么RGB和Gt;YCbCr & Gt;RYB路由可能更容易找到)。

        10
  •  0
  •   3c71    9 年前

    在我的应用程序中,无论是黑色还是LigTH主题混合颜色,我都在寻找一个简单快捷的解决方案。

    在暗色主题中,我只是简单地或者用RGB颜色,结果很好,但是在浅色主题中,这导致非常浅色变得不可见。

    我只是试了试颜色,效果很好。蓝色+黄色给了我绿色,洋红+青色至少给了我蓝色。

    所以,在黑暗的主题(背景)中我会:

    mixed_color = color1 | color2; // Dark theme, like RGB mixing
    

    在灯光主题中:

    mixed_color = color1 & color2; // Light theme, like CMY mixing
    

    这个组合不太可能有任何真实感,但对于我的需要(远离摄影软件),这是非常令人满意的。

        11
  •  0
  •   SMFSW    8 年前

    关于这件事已经说了很多,但我只想分享一种混合颜色的方法(考虑光的工作:加法方案)。

    我尝试了Damien Del Russo的示例代码,这在我个人看来是一个很好的方法,使用白色平均值来计算rgb混合。我想将结果与我自己的(基本和线性)代码进行比较。

    不幸的是,以前的代码返回的值在某些情况下可能超过255。。。但在这些情况下,如果应用比率回到0-255范围,结果对我来说是一样的。

    对于其他情况(主要是白色部分),我可以看到结果中的一些差异。区别更多的是光度而不是色度。 如果我试图缩小我获得的值,我会得到非常接近以前的代码结果。。。

    我还不确定哪种计算方法能给出更接近亮度的结果,但是如果我得到答案,我会更新这篇文章来分享结果。

    知道了这一点,下面是我的未完成代码(在python中,因为它是我的原则测试台)来混合n组rgb颜色:

    def rgb_mix_colors(rgb_scale, *colors):
        """ color mix
        :param rgb_scale: scale of values
        :param colors: list of colors (tuple of rgb values)
        :return: relative mix of rgb colors """
        r = g = b = 0
    
        for item in colors:
            try:
                if not isinstance(item, tuple):
                    raise TypeError
                if item[0] > rgb_scale or item[1] > rgb_scale or item[2] > rgb_scale:
                    raise ValueError
            except (TypeError, ValueError):
                print "WARNING: Value is outside range or unhandled parameter given as function argument!"
            else:
                r += item[0]    # add red value from item
                g += item[1]    # add green value from item
                b += item[2]    # add blue value from item
    
        ratio = max(r, g, b)
        if ratio > rgb_scale:
            ratio = float(rgb_scale) / ratio
            r *= ratio
            g *= ratio
            b *= ratio
    
        return int(r), int(g), int(b)
    
    
    if __name__ == "__main__":
        col_list = [(512, 10, 256),
                    (30, 120, 50),
                    (50, 40, 512),
                    "exception",        # should raise TypeError when mixing
                    (3800, 20, 50),     # should raise ValueError when mixing
                    (512, 10, 512)]
    
        # example with a scale defined at 1024 instead of default, providing list of tuples as params already packed as list
        print "2 warning messages should be displayed on the next line:"
        print rgb_mix_colors(1024, *col_list)
        print rgb_mix_colors(255, (0, 255, 0), (0, 32, 255))