2つのRGB-256ベクトルを取得し、それらの混合の結果を計算できるようにしたいと思います。また、各ベクトルに異なる重みを与えたいと思います。 Wordのカラープレートを使用して実験しましたが、一部の色は加重平均に従って混合することがわかりました。
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)
すべての色を正確に計算するためのアルゴリズムはありますか、ルックアップテーブルを使用して強制的に実行しますか?
最良の説明は、人間にとって RGBカラーモデル はやや直感的ではないであることです
これは、赤、緑、青の3種類の定義済みの色をさまざまな量で混合して色を表示する方法のみを知っているビデオディスプレイデバイス(モニターやテレビなど)にとって完全に論理的です。しかし、それはあなたと私が小学校で色を混ぜることを学んだ方法ではありません。
RGBでは、白色は(255、255、255)として表され、「すべてオン」に相当します。赤、緑、青の各色成分の完全な値が表示されます。これにより、非常に高い光強度が生じ、色が白と認識されます。逆に、黒色(0、0、0)は表示デバイスの「デフォルト」状態です。色のライトが表示されていない(「0」)場合、結果は黒色になり、色がなくなります。
黄色(255、255、0)と青(0、0、255)を完全に混ぜると、(255、255、255)またはwhiteで表される色が得られます。白に0.5を掛けると、255 * 0.5 = 127であるため、灰色になります。
赤と黄色を混ぜると予想される結果が得られるのは、おそらく何よりも異常です。赤+黄色は(510、255、0)なので、0.5を掛けるとオレンジ(255、127、0)になります。
あなたと私が学年で学んだことは、 subtractivecolor model と、 additiveカラーモデル RGBで使用。下部の2つの図を見ると、左側にRGBカラーモデル(加法)、右側にCMYKカラーモデル(減法)があります。問題をすぐに確認できるはずです。代わりに減法混色モデルを使用すると、希望する結果が得られます。
EDIT:もちろん、それは言うよりも簡単です。つまり、RGBの代わりにCMYKカラーモデルを採用した場合でも(RGBからCMYKへの変換はデバイス依存でデバイスに依存しており、簡単ではないため、すでに困難です)おそらく、純粋な青(0、0、255)と純粋な黄色(255、255、0)を混ぜて緑になるという衝動をまだ満たしていないでしょう。 CMYKは、赤、黄、青ではなく、シアン、マゼンタ、黄を3つの原色として使用します。また、選択した言語で RYBカラーモデル を実装する場合は、lotを先に実行します。
RGBカラーを現実的に組み合わせるようなアルゴリズムは知りません。私は自分の答えの中で、なぜそれが不可能なのか、少なくとも非常に難しいのかを説明しようとしていました。この質問をあと数日間開いたままにして、他の人が何かアイデアを持っているかどうかを確認することもできますが、RGBモデルに固執する必要がある場合は、このルックアップテーブルから始めましょう。 ;-)
これに基づいて 文書化された応答 およびこの alghoritm対応応答 に基づいて、加法および減法アプローチを使用して色を混合するシンプルなインターフェイスを試しました。
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;
}
}
基本的に、この操作は論理ANDおよび論理ORに似ています。 (まさしく正確ではありません)
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
2番目に引用された応答で言及された希釈/減法アルゴリットもありますが、それが何に基づいているのか、テストに追加されたばかりではありません。
実際の答えは、RGBカラーベクトル空間を加法的なものに変更してから、RGBに戻すことです。この新しいベクトル空間では、2つの光ベクトルを追加すると、光の加法性と色の認識を考慮して加法混色が生成されます。
そのため、CIE XYZベクトル空間がうまく機能することがわかります。
XYZベクトルはこの空間で加算的であり、光源と同様に混合します。
混色に関するこの論文 Creeを参照:
X_mix = X1 + X2 + ...
Y_mix = Y1 + Y2 + ...
Z_mix = Z1 + Z2 + ...
その後、基底をRGBに戻すことができます。ベクトル空間間で色を変更するために利用できる多くのライブラリがあり、CIEXYZは標準化され、広くサポートされています。
この方法により、ほとんどの目的に合った現実的な結果が得られます。
CIE 1931色空間 に関する詳細情報。
コーディ・グレイの答えを見て、色を組み合わせる方法を提案できると思います。カラーホイールを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
それがあなたに合うかどうか確かめてください。
編集:これは物理的に正しいふりをしているのではなく、単に概算しようとしているだけです。ルックアップテーブルのアイデアは、2つの理由で頭がおかしくなります。2つの引数に依存するため、サイズが非常に大きくなります。そして自然の法則は通常連続的であり、まれなケースもまれです。ルックアップテーブルに入力できる場合は、アルゴリズムを知っている必要があります。そのための関数を記述するだけです。
Blueを追加すると灰色になる理由を指摘したかっただけです。これは、シアンではなく、ブルーを追加しているためです。
または、より数学的に:
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)
以下はJava RGB色を混合するためのKubelka-Munk反射理論の実装です。この実装では、ブレンドとすべての色が不透明であること。
上記の答えが適切なミキシング結果を与えるとは思わない。
RGBとRYBの両方でこの問題に取り組んでいます(RGBからの変換後)。ここでのRGBからRYBへの変換は良好です。 http://www.insanit.net/tag/rgb-to-ryb/ (リクエストに応じてコードを共有します)。
光として混合する場合、それほど悪くはありません(以下を参照)。ペイントなどの物理的な素材としてミックスしたい場合は、littleトリッキーです-私はそれを探求するためにアプリに取り組んでいます。
元の質問に戻ります-これが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;
}
私のアプリで暗いテーマまたは明るいテーマのいずれかで色を混ぜるのと同じ問題があるため、私はすばやく簡単な解決策を探していました。
暗いテーマでは、RGBカラーを単純に論理和し、結果は大丈夫でしたが、明るいテーマでは非常に明るい色が見えなくなりました。
色を試してみただけで、うまくいきました。青+黄色は緑を、マゼンタ+シアンは少なくとも青を与えてくれました。
だから、暗いテーマ(背景)で私は:
mixed_color = color1 | color2; // Dark theme, like RGB mixing
明るいテーマ:
mixed_color = color1 & color2; // Light theme, like CMY mixing
ミックスにはリアリズムはほとんどありませんが、私のニーズ(写真ソフトウェアからはほど遠い)には非常に満足のいくものでした。
RGBモデルの「Yellow」は、RYBモデルの「Yellow」と同じではありません。RYBモデルは、Blueと混合すると緑を生成するはずです。
例として:(255、255、0)はRGBモデルの(0、0、255)の(約)2倍の「強烈な」です。一方、RYBモデルでは、等しい量の黄色と青が緑を与えることになっています。同様に、2つのモデルの赤と青は異なります。
それらをベクトル空間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つの方程式(これら2つの空間で3つの色が等しい)が必要です。
残念ながら、私は思うモデルは線形にスケーリングしないため、精度のためにルックアップテーブルを使用する必要があるかもしれません。
別の良いアイデアは、HSVまたはYCbCrスペースに変換することです。これは、これらのスペースで色情報がより明確に抽象化されるためです。 (RGBからRYBへの変換が存在する場合、RGB-> YCbCr-> RYBルートが見つけやすいかもしれません)。
黄色(=赤+緑)と青を混合すると物理学に従って白色が得られます- http://en.wikipedia.orgを参照)/wiki/Additive_color 。
この問題についてはすでに多くのことが述べられていますが、色を混ぜる方法を共有したかっただけです(光の操作を考慮して:加算スキーム)。
Damien Del Russoのサンプルコードを試してみました。これは、RGB平均を計算するためにホワイトアベレージを使用して、私の好みではナイスなアプローチのように見えました。結果を自分の(基本および線形)コードと比較したかった。
以前のコードは残念ながら255を超える値を返す場合があります...しかし、これらの場合、比率を適用して0〜255の範囲に戻すと結果は同じになります。
他の場合(主に白いコンポーネントの場合)、結果にいくつかの違いが見られます。違いは、色度よりも明度に関するものです。取得した値を縮小しようとすると、以前のコード結果に非常に近くなります...
どの計算方法で明度がより近い結果になるかはまだわかりませんが、答えが得られたら、この投稿を更新して結果を共有します。
それを知っているので、rgb色のn個のタプルを混合するための私の未完成のコード(Pythonでは、それは私の原則のテストベンチであるため)です:
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))