[comp.graphics] RGB color mixing/averaging

tpd6908@yak.COM (Tom Dickens) (03/15/90)

I am looking for a simple routine that will take 2 rgb values, a ratio
for mixing them (ie. 0.5), and will return the resulting rgb value.
This is desired for determining a pixel color after super-sampling, or when
combining colors while working with transparent surfaces.

The problem I have is I expect the resulting rgb value to follow 
'real world' results.  (ie. case1: red+blue=purple, case2: blue+yellow=green)
Case1 works in rgb space, but case2 does not.  I have read multiple
articles on the subject and have experimented with converting to HSV,
CMY, HLS spaces, linearly mixing, then converting back, but have not
gotten satisfactory results.  I have an appreaciation for the physical
aspects of light and properties of different materials etc., but what I
need is a quick and simple method that works as expected.  I am in the
process of deriving such a method since I have not found any papers
which address this.  

Any information, references, code samples, or other ideas would be more
than welcome.
Thanks in advance.   Tom Dickens, Areodynamic Research
		     Boeing Computer Services
		     (206) 865-6122

bdb@becker.UUCP (Bruce Becker) (03/15/90)

In article <173@yak.COM> tpd6908@yak.COM (Tom Dickens) writes:
|I am looking for a simple routine that will take 2 rgb values, a ratio
|for mixing them (ie. 0.5), and will return the resulting rgb value.
|This is desired for determining a pixel color after super-sampling, or when
|combining colors while working with transparent surfaces.
|
|The problem I have is I expect the resulting rgb value to follow 
|'real world' results.  (ie. case1: red+blue=purple, case2: blue+yellow=green)
|Case1 works in rgb space, but case2 does not.  I have read multiple
|articles on the subject and have experimented with converting to HSV,
|CMY, HLS spaces, linearly mixing, then converting back, but have not
|gotten satisfactory results.  I have an appreaciation for the physical
|aspects of light and properties of different materials etc., but what I
|need is a quick and simple method that works as expected.  I am in the
|process of deriving such a method since I have not found any papers
|which address this.  

	You need to convert to CIE coordinates in order
	to do this properly. In this color coordinate
	space color mixing occurs along a straight line
	between the given colors - this is not true of
	HLS, HSV, CMY, RGB, etc. Probably you ought to
	convert from rgb to CIE at the beginning and
	work in this form all the way through. Besides
	the efficiency gain, you end up with values
	that are independent of the color characteristics
	of any given display device or class of devices.

	Some references in which to look for more info
	and code are:

	Raster Graphics Handbook, 2nd Ed., Conrac Corporation,
	Van Nostrand Reinhold, 1985

	Illumination and Color in Computer Generated Imagery,
	Roy Hall, Springer-Verlag, 1989

Cheers,
-- 
  (__)	 Bruce Becker	Toronto, Ontario
w \@@/	 Internet: bdb@becker.UUCP, bruce@gpu.utcs.toronto.edu
 `/v/-e	 UUCP: ...!uunet!mnetor!becker!bdb
_/  \_	 "So far from God, so close to the United States" - Old Mexican proverb

legrady@ug.cs.dal.ca (Tom Legrady) (03/15/90)

In article <173@yak.COM> tpd6908@yak.COM (Tom Dickens) writes:
>I am looking for a simple routine that will take 2 rgb values, a ratio
>for mixing them (ie. 0.5), and will return the resulting rgb value.
>This is desired for determining a pixel color after super-sampling, or when
>combining colors while working with transparent surfaces.
>
>The problem I have is I expect the resulting rgb value to follow 
>'real world' results.  (ie. case1: red+blue=purple, case2: blue+yellow=green)

The problem is not in the algorithmn, but in you selection of
'primary' colours.  Blue paint mixed with yellow paint looks green.
That's subtractive mixing.  You started with white light and reduced
level of non-yellow colours.  Then from that you reduced the non-blue 
colours. Since green is between yellow and green, it passed through
both filters.

When you mix RGB values, as when you point several stage lights at the
same location, you get additive mixing.  You start with Black, add some
Blue, then add some yellow (which is a mixture of red and green) ...
Voila ... _WHITE_!!!  It took me a while to pound the additive rules into
my head:

PRIMARIES			Red		Green		Blue

Red		+	Green	=	Yellow
Green	+	Blue	=	Cyan	(pale blue)
Red		+	Green	=	Magenta	(deep purple)

The sequence of combinations brightes to darkest is

White	Yellow	Cyan	Green	Magenta	Red	Blue	Black.

fishkin@pixar.UUCP (Ken Fishkin) (03/17/90)

In article <173@yak.COM> tpd6908@yak.COM (Tom Dickens) writes:
|I am looking for a simple routine that will take 2 rgb values, a ratio
|for mixing them (ie. 0.5), and will return the resulting rgb value.
|This is desired for determining a pixel color after super-sampling, or when
|combining colors while working with transparent surfaces.
|
|The problem I have is I expect the resulting rgb value to follow 
|'real world' results.  (ie. case1: red+blue=purple, case2: blue+yellow=green)
    [various proposals for 'real world' results deleted].

    The confusion is due to the vagueness of the term "real world results".
Different color models and algorithms are appropriate for modeling
different phenomona.
    For modeling the effect of collecting light rays (as in the results
obtained from super-sampling a surface), any additive color space is
appropriate: RGB, XYZ, etc.
    For modeling the effect of shining light through a colored filter,
you have to go to wavelength-based spaces like XYZ.
    For modeling the effect of combining colored paints (what I
believe Mr. Dickens is alluding to with his "real world" examples),
you have to go to XYZ space and do some awful, complicated
physics, which will require you to know the _chemical_ as well as _optical_
properties of the paints, the surface the paints lie on, and so forth.
Trust me: I did my masters on this.
    A quick-and-dirty approximation is to linearly interpolate in HSL
(note: not HSV!) space, after re-mapping the hue wheel such that Red,
_Yellow_, and Blue form an equilateral triangle within the whell.
    Hope this helps,
-- 
Ken Fishkin	...ucbvax!pixar!fishkin

jgk@osc.COM (Joe Keane) (03/17/90)

In article <173@yak.COM> tpd6908@yak.COM (Tom Dickens) writes:
>The problem I have is I expect the resulting rgb value to follow 
>'real world' results.  (ie. case1: red+blue=purple, case2: blue+yellow=green)
>Case1 works in rgb space, but case2 does not.

Averaging in RGB space does in fact average the colors, assuming you account
for gamma correction.  I think the problem is that your `real world' cases are
wrong, or at least over-simplified.  If you combine pure blue and pure yellow
light, you get washed-out green light, not pure green.  Similarly, if you mix
bright blue and bright yellow paint, you get dirty green paint, not bright
green.  Try these some time if you don't believe me.  Also, despite what some
people might say, mixing red and green light gives you only passable yellow
light, which is why you can't get a really good yellow on an RGB monitor.
Purple is sort of a special case.  It doesn't correspond to any point in the
spectrum, and you can get it exactly by mixing pure red and pure blue light.

dave@imax.com (Dave Martindale) (03/18/90)

In article <2201@osc.COM> jgk@osc.COM (Joe Keane) writes:
>
>Also, despite what some
>people might say, mixing red and green light gives you only passable yellow
>light, which is why you can't get a really good yellow on an RGB monitor.

Depends on the red and green light you start with.  The eye has only
three colour receptors.  Spectrally pure yellow light produces responses
in these three receptors in a certain ratio; any other combination of
colours that produces the same ratio will also be perceived as yellow.

The CIE chromaticity diagram is a way of displaying perceived colour.
It also shows you what colours you can obtain by mixing 2 or 3 other
colours.  Spectrally pure colours are on the curved line around
the edge of the chart.  Now, the area between red and green that
contains yellow is almost a straight line.  This indicates that, given
almost any spectrally pure red, and a spectrally pure green that is
somewhat on the yellowish side, you can find a ratio to mix them that
gives extremely good yellow.

So, you can get good yellow from red and green light - but the light
would have to be generated by lasers, or by separating white light
with a prism or grating.  The red and green phosphors used in CRTs
are nowhere near spectrally pure, and in fact were chosen more for
efficiency (brightness) rather than colour.  That's why you can't get
a good yellow, and the best green is still yellowish, and there are
no pure reds.

On the other hand, there are some colours that you can't get by
mixing lights - pure cyan (blue-green) for example.  That portion
of the CIE diagram is continuously curved, so any pure cyan-like colour
lies outside a straight line joining anything you could call pure green
to any pure blue, thus you can't obtain pure cyan even by mixing
single-frequency green and blue.