systems easy color graphics colors rgb mixing

graphics - easy - Cálculo de un color mezclado en RGB



rgb color (11)

Quiero poder tomar dos vectores RGB-256 y calcular el resultado de su mezcla. También quiero poder dar a cada vector un peso diferente. Experimenté con él usando la placa de color de Word, y he visto que mientras algunos colores se mezclan de acuerdo con un promedio ponderado:

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

otros no:

0.5*yellow(255,255,0) + 0.5*blue(0,0,255) = gray (127,127,127) y no green (0,255,0)

¿Existe un algoritmo para el cálculo preciso de todos los colores o me veo obligado a hacerlo utilizando una tabla de consulta?


Basándome en esta respuesta documentada y esta respuesta consciente de algoritmos , he intentado una interfaz simple para mezclar colores utilizando un enfoque aditivo y sustractivo.

Debe confirmar que los colores primarios de RGB y CMYK le dan los colores secundarios en los primeros diagramas de respuesta:

  • Rojo + Azul = Magenta (en aditivo)
  • Amarillo + Cian = Verde (en sustractivo)
  • y así ...

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

Básicamente, estas operaciones son como lógica Y y lógica OR. (Bueno no exactamente)

  • En aditivo alghoritm, los colores se superponen, pero para cada primario solo puede ser 255 (Operación lógica OR)
  • En alghoritm sustractivo, si algún primario no está presente, el resultado no tendrá eso (CYAN no tiene ROJO, AMARILLO no tiene AZUL: obtienes VERDE) (Lógica Y operación)

En base a this , puede obtener colores terciarios a partir de una mezcla de colores primarios y secundarios, por lo que hago una pequeña implementación que funciona bastante bien:

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

También hay una alusión a la dilución / sustractiva mencionada en la segunda respuesta citada, pero no puedo decir en qué se basa, simplemente se agregó para la prueba.


La respuesta REAL es cambiar el espacio vectorial de color RGB en uno que sea aditivo, luego cámbielo a RGB. En este nuevo espacio vectorial, cuando agrega dos vectores de luz, toma en cuenta las propiedades aditivas de la luz y nuestra percepción del color para producir un color aditivo.

Resulta que el espacio vectorial CIE XYZ funciona bien para ese propósito.

Los vectores XYZ son aditivos en este espacio y se mezclan como lo hacen las fuentes de luz.

Vea este documento sobre la mezcla de colores por Cree:

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

Luego puede cambiar la base a RGB. Hay muchas bibliotecas disponibles para cambiar el color entre los espacios de vectores y CIEXYZ está estandarizado y es ampliamente compatible.

Este método produce resultados realistas que se adaptan a la mayoría de mis propósitos.

Más información sobre el espacio de color CIE 1931 .


Mirando la respuesta de Cody Gray, creo que puedo sugerir cómo combinar colores. Convirtiendo la rueda de color a 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)

Sin complicaciones adicionales, los colores se pueden combinar así: invierta ambos colores, agréguelos e invierta el resultado (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; }

Salida:

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

Vea si eso le queda bien.

Editar: No pretendo que esto sea físicamente correcto, es solo un intento de aproximación. La idea de la tabla de búsqueda me parece una locura por dos razones: depende de dos argumentos, por lo que su tamaño será muy grande; y las leyes de la naturaleza suelen ser continuas sin casos excepcionales o sin casos excepcionales. Si puede completar la tabla de búsqueda, debe conocer el algoritmo, por lo que solo debe escribir una función para ello.


No creo que las respuestas anteriores den resultados de mezcla adecuados.

He estado trabajando en este problema con RGB y RYB (después de convertir desde RGB). Aquí la conversión de RGB a RYB es buena: http://www.insanit.net/tag/rgb-to-ryb/ (compartiré mi código cuando lo solicite).

Si se mezcla como la luz, no es tan malo (ver abajo). Si desea mezclar materiales físicos como pintura, es un poco más complicado: estoy trabajando en una aplicación para explorarlo.

Volver a la pregunta original: aquí está mi código para mezclar RGB. RgbColor es una clase personalizada, pero creo que tiene sentido por sí mismo:

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


La mejor explicación es que el modelo de color RGB es algo poco intuitivo para nosotros los humanos.
Es perfectamente lógico que un dispositivo de visualización de video (como un monitor o un televisor) solo sepa cómo mostrar colores mezclando cantidades variables de 3 colores predefinidos: rojo, verde y azul. Pero no es así como aprendimos a mezclar colores en la escuela primaria.

En RGB, el color blanco se representa como (255, 255, 255), lo que equivale a "todo encendido". Se muestra el valor completo para cada uno de los componentes de color rojo, verde y azul, lo que crea una intensidad de luz tan alta que percibimos el color como blanco. Por el contrario, el color negro (0, 0, 0) es el estado "predeterminado" del dispositivo de visualización: cuando no se muestra luz de color ("0"), el resultado es negro o la ausencia de color.

Cuando mezcla completamente amarillo (255, 255, 0) y azul (0, 0, 255), obtiene el color representado por (255, 255, 255), o blanco . Cuando multiplicas el blanco por 0.5, obtienes un color gris, porque 255 * 0.5 = 127.

Probablemente sea más una anomalía que cualquier cosa que obtenga el resultado esperado al mezclar rojo y amarillo. Rojo + amarillo es (510, 255, 0), así que cuando multiplicas eso por 0.5, obtienes naranja (255, 127, 0).

Resulta que lo que usted y yo aprendimos en la escuela primaria se conoce con más precisión como un modelo de color sustractivo , en comparación con el modelo de color aditivo utilizado por RGB. Al observar los dos diagramas en la parte inferior, verá el modelo de color RGB (aditivo) a la izquierda, en comparación con el modelo de color CMYK (sustractivo) a la derecha. Debes poder ver el problema inmediatamente. En cambio, usar un modelo de color sustractivo producirá los resultados que desee.

EDITAR: Por supuesto, eso es más fácil decirlo que hacerlo. Es decir, incluso si adopta el modelo de color CMYK en lugar del RGB (que ya es difícil, debido a que las conversiones de RGB a CMYK dependen en gran medida del dispositivo y están lejos de ser sencillas), esto probablemente no satisfaga la necesidad de mezclar el azul puro 0, 0, 255) con amarillo puro (255, 255, 0) y obtener verde. CMYK usa cian, magenta y amarillo como los 3 colores primarios, en lugar de rojo, amarillo y azul. Y tiene mucho trabajo por delante si desea implementar el modelo de color RYB en el idioma que elija.

No conozco ninguno de estos algoritmos para combinar colores RGB de forma realista. Intenté en mi respuesta explicar por qué sería imposible, o extremadamente difícil al menos. Podrías dejar esta pregunta abierta unos días más y ver si alguien más tiene alguna idea, pero seguiría adelante y comenzaría en la tabla de búsqueda si necesitas seguir con el modelo RGB. ;-)


El "Amarillo" en el modelo RGB no es el mismo que el Amarillo en el modelo RYB, que cuando se mezcla con el Azul se supone que da verde.

Como ejemplo: (255, 255, 0) es (aproximadamente) el doble de "intenso" que (0, 0, 255) en el modelo RGB, mientras que en el modelo RYB, se supone que las cantidades IGUALES de Amarillo y Azul dan Verde. Del mismo modo, Rojo y Azul en los dos modelos son diferentes.

Piense en ellos como espacios vectoriales RGB y R''Y''B ''.

Si algún tipo de relación como:

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

sostiene, puede hacer su álgebra convirtiendo primero los colores individuales (operandos) del espacio RGB al espacio R''Y''B ''.

Hay 9 incógnitas (i, j, k variables), por lo que necesita 9 ecuaciones (3 ecualidades de color en estos 2 espacios).

Desafortunadamente, creo que los modelos no se escalan linealmente y, por lo tanto, para la precisión, es posible que tenga que usar tablas de búsqueda.

Otra buena idea puede ser convertir al espacio HSV o YCbCr, porque la información de color se abstrae más claramente en ese espacio. (Si existe una conversión RGB a RYB, una ruta RGB-> YCbCr-> RYB podría ser más fácil de encontrar).


Teniendo el mismo problema con la mezcla de colores en un tema oscuro o ligero en mi aplicación, estaba buscando una solución rápida y fácil.

En el tema oscuro, simplemente coloqué los colores RGB y el resultado fue bastante bueno, sin embargo, en el tema claro, los colores muy claros se volvieron invisibles.

Simplemente probé colores y eso funcionó bastante bien. azul + amarillo me dio verde, magenta + cian me dio azul al menos.

Entonces, en el tema oscuro (fondo) hago:

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

En el tema de la luz:

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

Es poco probable que exista realismo en la mezcla, pero para mi necesidad (muy lejos del software de fotografía) fue muy satisfactorio.


Ya se ha dicho mucho al respecto, pero solo quería compartir una forma de mezclar colores (considerando trabajar con luz: esquema de adición).

Intenté el código de ejemplo de Damien Del Russo, que parecía un buen enfoque a mi gusto utilizando el promedio blanco para calcular la mezcla de rgb. Quería comparar los resultados con mi propio código (básico y lineal).

Desafortunadamente, el código anterior puede devolver valores que superan los 255 en algunos casos ... Sin embargo, en estos casos, el resultado es el mismo para mí si se aplica una proporción para volver al rango de 0-255.

Para otros casos (principalmente con un componente blanco), puedo ver algunas diferencias en los resultados. La diferencia es más acerca de la luminosidad que la cromaticidad. Si trato de escalar los valores que obtengo, me acerco mucho a los resultados del código anterior ...

Todavía no estoy seguro de qué manera de calcularlo ofrece los resultados más cercanos en términos de luminosidad, pero si obtengo una respuesta, actualizaré esta publicación para compartir los resultados.

Sabiendo eso, aquí está mi código inacabado (en python, ya que es mi banco de pruebas de principios) para mezclar n tuplas de colores 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))

mixing colors adding light rgb python


Aquí hay una implementación en Java de la Teoría de la reflectancia de Kubelka-Munk para mezclar colores RGB. Esta implementación utiliza una versión simplificada del modelo Kubelka-Munk que asume que todos los colores tienen la misma concentración cuando se mezclan y que todos los colores son opacos.

https://github.com/benjholla/ColorMixer



Solo quería señalar por qué te estás poniendo gris cuando agregas azul . Es porque estás agregando azul y no cian :

  • Si agrega Cyan a Amarillo, obtiene Verde
  • Si agrega Azul (es decir, magenta + cian) a Amarillo, obtendrá Gris.

O, más matemáticamente:

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

Estás agregando azul , cuando quisiste agregar Cyan .

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