it-swarm.com.de

Berechnung einer Mischfarbe in RGB

Ich möchte in der Lage sein, zwei RGB-256-Vektoren zu nehmen und das Ergebnis ihrer Mischung zu berechnen. Außerdem möchte ich jedem Vektor ein anderes Gewicht geben können. Ich habe mit der Word-Farbtafel experimentiert und festgestellt, dass sich einige Farben nach einem gewichteten Durchschnitt mischen:

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

andere nicht:

0.5*yellow(255,255,0) + 0.5*blue(0,0,255) = gray (127,127,127) und nicht green (0,255,0)

Gibt es einen Algorithmus für die genaue Berechnung aller Farben oder muss ich ihn mithilfe einer Nachschlagetabelle ausführen?

30
SIMEL

Die beste Erklärung ist, dass das RGB-Farbmodell für uns Menschen etwas Unintuitive ist.
Es ist absolut logisch für ein Videoanzeigegerät (z. B. einen Monitor oder ein Fernsehgerät), das nur weiß, wie Farben angezeigt werden, indem es verschiedene Mengen von 3 vordefinierten Farben mischt: Rot, Grün und Blau. Aber so haben Sie und ich nicht gelernt, Farben in der Grundschule zu mischen.

In RGB wird die Farbe Weiß als (255, 255, 255) dargestellt, was "all on" entspricht. Der volle Wert für jede der roten, grünen und blauen Farbkomponenten wird angezeigt, wodurch eine so hohe Lichtintensität entsteht, dass wir die Farbe als weiß wahrnehmen. Umgekehrt ist die Farbe Schwarz (0, 0, 0) der "Standard" -Zustand des Anzeigegeräts. Wenn kein Farblicht ("0") angezeigt wird, ist das Ergebnis Schwarz oder das Fehlen von Farbe.

Wenn Sie Gelb (255, 255, 0) und Blau (0, 0, 255) vollständig mischen, erhalten Sie die Farbe (255, 255, 255) oder Weiß. Wenn Sie Weiß mit 0,5 multiplizieren, erhalten Sie eine graue Farbe, denn 255 * 0.5 = 127.

Es ist wahrscheinlich eher eine Anomalie als alles andere, dass Sie beim Mischen von Rot und Gelb das erwartete Ergebnis erzielen. Rot + Gelb ist (510, 255, 0). Wenn Sie das also mit 0,5 multiplizieren, erhalten Sie Orange (255, 127, 0).

Es stellt sich heraus, dass das, was Sie und ich in der Grundschule gelernt haben, eigentlich genauer als subtraktiv Farbmodell , im Vergleich zu dem Additiv Farbmodell von RGB. Wenn Sie die beiden Diagramme unten betrachten, sehen Sie links das RGB-Farbmodell (Additiv) und rechts das CMYK-Farbmodell (subtraktiv). Sie sollten das Problem sofort sehen können. Wenn Sie stattdessen ein subtraktives Farbmodell verwenden, werden die gewünschten Ergebnisse erzielt.

RGB Color ModelCMYK Color Model

EDIT: Natürlich ist das leichter gesagt als getan. Das heißt, selbst wenn Sie das CMYK-Farbmodell anstelle von RGB verwenden (was bereits schwierig ist, da Konvertierungen von RGB in CMYK stark geräteabhängig und alles andere als einfach sind), wird dies wahrscheinlich immer noch nicht zufriedenstellen fordern Sie auf, reines Blau (0, 0, 255) mit reinem Gelb (255, 255, 0) zu mischen und grün zu werden. CMYK verwendet Cyan, Magenta und Gelb als die 3 Primärfarben anstelle von Rot, Gelb und Blau. Und Sie haben ein Los Arbeit vor Ihnen, wenn Sie das RYB-Farbmodell in der Sprache Ihrer Wahl implementieren möchten.

Ich kenne keinen solchen Algorithmus, um RGB-Farben realistisch zu kombinieren. In meiner Antwort versuchte ich zu erklären, warum es unmöglich oder zumindest äußerst schwierig sein würde. Sie könnten diese Frage noch ein paar Tage offen lassen und nachsehen, ob noch jemand andere Ideen hat, aber ich würde weitermachen und an diesem Nachschlagetisch anfangen, wenn Sie beim RGB-Modell bleiben müssen. ;-)

30
Cody Gray

Basierend auf dieser dokumentierten Antwort und dieser Alghoritm-bewussten Antwort habe ich eine einfache Schnittstelle zum Mischen von Farben mit additivem und subtraktivem Ansatz ausprobiert.

Sie müssen bestätigen, dass die Primärfarben von RGB und CMYK die Sekundärfarben in den ersten Antwortdiagrammen enthalten:

  • Rot + Blau = Magenta (auf Zusatzstoff)
  • Gelb + Cyan = Grün (subtraktiv)
  • und so weiter ...
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

Grundsätzlich sind diese Operationen wie logisches UND und logisches ODER. (Na ja nicht genau) 

  • Bei additivem Algorithmus überlappen sich die Farben, aber für jede Primärfarbe kann es nur 255 sein (Operation OR).
  • Wenn bei einem substraktiven Alghoritm keine Primärdaten vorhanden sind, wird das Ergebnis nicht das Ergebnis haben.

Basierend auf this können Sie Tertiärfarben aus einer Mischung von Primär- und Sekundärfarben erhalten, daher mache ich eine kleine Implementierung, die ziemlich gut funktioniert:

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

Es gibt auch einen verwässernden/substraktiven Algorithmus, der in der zweiten zitierten Antwort erwähnt wird, aber ich kann nicht sagen, worauf er basiert, nur zum Test hinzugefügt.

3
albfan

Die ECHTE Antwort ist, den RGB-Farbvektorraum in einen additiven zu ändern und ihn dann wieder in RGB zu ändern. Wenn Sie in diesem neuen Vektorraum zwei Lichtvektoren hinzufügen, werden die additiven Eigenschaften von Licht und unsere Farbwahrnehmung berücksichtigt, um eine additive Farbe zu erzeugen.

Es stellt sich heraus, dass der CIE XYZ-Vektorraum für diesen Zweck gut funktioniert.

Die XYZ-Vektoren sind in diesem Raum additiv und mischen sich wie Lichtquellen.

dieses Papier zum Farbmischen von Cree:

X_mix = X1 + X2 + ...

Y_mix = Y1 + Y2 + ...

Z_mix = Z1 + Z2 + ...

Sie können dann die Basis wieder auf RGB umstellen. Es gibt viele Bibliotheken, um die Farbe zwischen Vektorräumen zu ändern. CIEXYZ ist standardisiert und wird weitgehend unterstützt.

Diese Methode liefert realistische Ergebnisse, die den meisten meiner Zwecke entsprechen.

Weitere Informationen zum CIE 1931 Farbraum .

3
nh43de

Wenn ich mir Cody Greys Antwort anschaue, denke ich, dass ich vorschlagen kann, wie man Farben kombiniert. Farbrad nach RGB konvertieren:

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

Ohne zusätzliche Komplikationen können Farben wie folgt kombiniert werden: Invertieren Sie beide Farben, addieren Sie sie und invertieren Sie das Ergebnis (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;
}

Ausgabe:

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

Sehen Sie, ob das zu Ihnen passt.

Edit: Ich behaupte nicht, dass dies physisch korrekt ist, es ist nur ein Annäherungsversuch. Die Idee der Nachschlagetabelle klingt für mich aus zwei Gründen verrückt: Sie hängt von zwei Argumenten ab, daher ist ihre Größe sehr groß; und Naturgesetze sind in der Regel ohne oder mit seltenen Eckfällen. Wenn Sie eine Lookup-Tabelle füllen können, sollten Sie den Algorithmus kennen - schreiben Sie einfach eine Funktion dafür.

2
alxx

Ich wollte nur darauf hinweisen, warum Sie grau werden, wenn Sie Blue hinzufügen. Es liegt daran, dass Sie Blue und nicht Cyan hinzufügen:

enter image description here

  • Wenn Sie Cyan zu Yellow hinzufügen, erhalten Sie Green
  • Wenn Sie Blue (d. H. Cyan + Magents) zu Yellow hinzufügen, erhalten Sie Gray.

Oder mathematischer:

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

Sie fügen Blue hinzu, wenn Sie Cyan hinzufügen wollten.

0.5*Yellow(255,255,0) + 0.5*Cyan(0,255,255) = VeryLightLimeGreen(128,255,128)
1
Ian Boyd

Hier ist eine Java-Implementierung der Kubelka-Munk-Theorie der Reflexion zum Mischen von RGB-Farben. Diese Implementierung verwendet eine vereinfachte Version des Kubelka-Munk-Modells, bei der alle Farben beim Mischen die gleiche Konzentration haben und alle Farben undurchsichtig sind.

https://github.com/benjholla/ColorMixer

1
Ben Holland

Ich denke nicht, dass die obigen Antworten angemessene Mischungsergebnisse ergeben.

Ich habe an diesem Problem sowohl mit RGB als auch mit RYB gearbeitet (nach dem Konvertieren von RGB). Die Konvertierung für RGB in RYB ist hier gut: http://www.insanit.net/tag/rgb-to-ryb/ (Ich werde meinen Code auf Anfrage freigeben).

Beim Mischen als Licht ist es nicht so schlimm (siehe unten). Wenn Sie physikalische Materialien wie Paint mischen möchten, ist dies ein wenig -Trickler - ich arbeite an einer App, um sie zu erkunden. 

Zurück zur ursprünglichen Frage - hier ist mein Code für das RGB-Mischen. RgbColor ist eine benutzerdefinierte Klasse, aber ich denke, das macht aus sich heraus Sinn:

-(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;
}
1

Mit dem gleichen Problem beim Mischen von Farben in einem dunklen oder hellen Thema in meiner App suchte ich nach einer schnellen und einfachen Lösung.

Bei dunklen Motiven habe ich einfach oder nur die RGB-Farben verwendet und das Ergebnis war ziemlich in Ordnung, aber bei hellen Motiven führte dies dazu, dass sehr helle Farben unsichtbar wurden.

Ich habe einfach Farben ausprobiert und das hat gut funktioniert. Blau + Gelb gab mir Grün, Magenta + Cyan gab mir mindestens Blau.

Also, im dunklen Thema (Hintergrund) mache ich:

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

Im Lichtthema:

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

Es ist unwahrscheinlich, dass der Mix realistisch ist, aber für meinen Bedarf (weit weg von der Fotografie-Software) war das sehr zufriedenstellend.

0
3c71

Das "Gelb" im RGB-Modell ist nicht das Gleiche wie das Gelb im RYB-Modell, das beim Mischen mit Blau Grün ergeben soll.

Ein Beispiel: (255, 255, 0) ist (ungefähr) doppelt so "intensiv" wie (0, 0, 255) im RGB-Modell, während im RYB-Modell EQUAL-Mengen von Gelb und Blau Grün ergeben sollen. Ebenso unterscheiden sich Rot und Blau in den beiden Modellen. 

Stellen Sie sich sie als Vektorräume RGB und R'Y'B 'vor.

Wenn eine Art Beziehung wie:

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

sie können Ihre Algebra verwenden, indem Sie zunächst die einzelnen Farben (Operanden) von RGB in den R'Y'B'-Raum konvertieren.

Es gibt 9 Unbekannte (i, j, k-Variablen). Sie benötigen also 9 Gleichungen (3 Farbgleichungen in diesen beiden Räumen).

Leider - denke ich , dass die Modelle nicht linear skaliert werden, und aus Gründen der Genauigkeit müssen Sie möglicherweise Nachschlagetabellen verwenden.

Eine andere gute Idee ist möglicherweise die Konvertierung in einen HSV- oder YCbCr-Bereich, da die Farbinformationen in diesem Bereich deutlicher abstrahiert werden. (Wenn eine RGB-zu-RYB-Konvertierung vorhanden ist, kann eine RGB-> YCbCr-> RYB-Route möglicherweise leichter zu finden sein).

0
JP19

Mischen von gelb (= rot + grün) und blau do ergibt gemäß der Physik eine weiße Farbe, siehe http://en.wikipedia.org/wiki/Additive_color .

0
user502515

Zu diesem Thema wurde bereits viel gesagt, aber ich wollte nur eine Möglichkeit zum Mischen von Farben geben (in Anbetracht der Arbeit mit Licht: Additionsschema).

Ich habe den Beispielcode von Damien Del Russo ausprobiert, der in meinem eigenen Geschmack ein Nizza-Ansatz war und den weißen Mittelwert zur Berechnung des rgb-Mixes verwendete. Ich wollte die Ergebnisse mit meinem eigenen (grundlegenden und linearen) Code vergleichen.

Früherer Code kann leider Werte zurückgeben, die in einigen Fällen über 255 liegen. In diesen Fällen ist das Ergebnis jedoch für mich dasselbe, wenn ein Verhältnis angewendet wird, um zum Bereich 0-255 zurückzukehren.

In anderen Fällen (meistens mit einer weißen Komponente) kann ich einige Unterschiede in den Ergebnissen feststellen. Der Unterschied betrifft mehr die Leuchtkraft als die Farbart. Wenn ich versuche, die Werte, die ich erhalte, herabzusetzen, komme ich den früheren Code-Ergebnissen sehr nahe ...

Ich bin mir noch nicht sicher, welche Berechnungsmethode die näheren Ergebnisse in Bezug auf die Leuchtkraft liefert. Wenn ich jedoch eine Antwort bekomme, werde ich diesen Beitrag aktualisieren, um die Ergebnisse zu teilen.

Zu wissen, hier ist mein unfertiger Code (in Python, da es meine Prinzipienprüfbank ist), um n-Tupel von RGB-Farben zu mischen:

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 __== "__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))

MischenFarbenHinzufügenLichtrgbPython

0
SMFSW