hiebeler@cardinal.lanl.gov (David Hiebeler) (07/25/89)
Here are the results (or at least most of them; I think I got a couple more which I saved somewhere and can't find just this moment... :-) ) of my query about generating RGB triples for a rainbow. I think sines/cosines are a good approach, but didn't quite like the ones that were sent to me. Probably with some tuning I can get something more to my tastes. Thanks to everyone who took the time to send me a message about this. ========== I don't know if this will help, but it was posted about a week ago to this same newsgroup. it deals with converting visible wavlengths into RGB triples. Here it is ------- cut here -------- >From awpaeth@watcgl.waterloo.edu Tue Jun 27 22:27:33 1989 From: awpaeth@watcgl.waterloo.edu (Alan Wm Paeth) Newsgroups: comp.graphics Subject: Re: Wavelength to XYZ or RGB coordinates Date: 27 Jun 89 18:47:36 GMT Reply-To: awpaeth@watcgl.waterloo.edu (Alan Wm Paeth) Distribution: na Organization: U. of Waterloo, Ontario What is required is an electronic transcription of the CIE's table of color- matching functions -- perhaps their best-known publication (excerpted below). Note that all table values are non-negative and all columns sum (integrate) to the same value, which can serve as a normalization constant (eg, make the brightest white in the scene map to [255 255 255]). Conversion using a 3x3 matrix multiply to/from broadcast RGB is also given. (RGB can mean anything to anyone -- no two monitors are alike; I've chosen the NTSC chromaticities of commercial color broadcasting as they are well- defined). Most of this technique is over a half-century old; the lengthy posting is offered in part to help better acquaint and encourage "graphicists" with known technique from the field of color science. /Alan Paeth Computer Graphics Laboratory University of Waterloo ------------------- # Excerpted Tristimulus values for spectral colors (L = wavelength in nm) # for the CIE 1931 Standard Colorimetric Observer (2 degree field of view) # L X Y Z x' y' u' v' 380 0.0014 0.0000 0.0065 0.1772 0.0000 0.2679 0.0000 390 0.0042 0.0001 0.0201 0.1721 0.0041 0.2545 0.0136 400 0.0143 0.0004 0.0679 0.1731 0.0048 0.2554 0.0161 410 0.0435 0.0012 0.2074 0.1726 0.0048 0.2545 0.0158 420 0.1344 0.0040 0.6456 0.1714 0.0051 0.2523 0.0169 430 0.2839 0.0116 1.3856 0.1689 0.0069 0.2461 0.0226 440 0.3483 0.0230 1.7471 0.1644 0.0109 0.2348 0.0349 450 0.3362 0.0380 1.7721 0.1566 0.0177 0.2161 0.0550 460 0.2908 0.0600 1.6692 0.1440 0.0297 0.1877 0.0871 470 0.1954 0.0910 1.2876 0.1241 0.0578 0.1441 0.1510 480 0.0956 0.1390 0.8130 0.0913 0.1327 0.0828 0.2708 490 0.0320 0.2080 0.4652 0.0454 0.2950 0.0281 0.4116 500 0.0049 0.3230 0.2720 0.0082 0.5384 0.0035 0.5131 510 0.0093 0.5030 0.1582 0.0139 0.7502 0.0046 0.5638 520 0.0633 0.7100 0.0782 0.0743 0.8338 0.0231 0.5837 530 0.1655 0.8620 0.0422 0.1547 0.8058 0.0501 0.5867 540 0.2904 0.9540 0.0203 0.2296 0.7543 0.0792 0.5856 550 0.4334 0.9950 0.0087 0.3016 0.6924 0.1127 0.5821 560 0.5945 0.9950 0.0039 0.3731 0.6245 0.1531 0.5766 570 0.7621 0.9520 0.0021 0.4441 0.5547 0.2026 0.5694 580 0.9163 0.8700 0.0017 0.5125 0.4866 0.2623 0.5604 590 1.0263 0.7570 0.0011 0.5752 0.4242 0.3315 0.5501 600 1.0622 0.6310 0.0008 0.6270 0.3725 0.4031 0.5393 610 1.0026 0.5030 0.0003 0.6658 0.3340 0.4691 0.5296 620 0.8544 0.3810 0.0002 0.6915 0.3084 0.5202 0.5219 630 0.6424 0.2650 0.0000 0.7080 0.2920 0.5565 0.5165 640 0.4479 0.1750 0.0000 0.7191 0.2809 0.5830 0.5125 650 0.2835 0.1070 0.0000 0.7260 0.2740 0.6005 0.5099 660 0.1649 0.0620 0.0000 0.7268 0.2732 0.6024 0.5096 670 0.0874 0.0320 0.0000 0.7320 0.2680 0.6161 0.5076 680 0.0468 0.0170 0.0000 0.7335 0.2665 0.6203 0.5070 690 0.0227 0.0082 0.0000 0.7346 0.2654 0.6232 0.5065 700 0.0114 0.0041 0.0000 0.7355 0.2645 0.6255 0.5062 ----------- CIE-XYZ to NTSC-RGB | R | | 1.73 -.48 -.26 | | X | # inverse of matrix below, all | G | = | -.81 1.65 -.02 | * | Y | # columns sum to 1.0 | B | | .08 -.17 1.28 | | Z | # neg results are out of gamut NTSC-RGB to CIE-XYZ | X | | .67 .21 .14 | | R | # inverse of matrix above, all | Y | = | .33 .71 .08 | * | G | # columns sum to 1.0 | Z | | 0.0 .08 .78 | | B | # Red phosphor (u',v') = .67,.33, etc. -------- cut here -------- Have fun with it! ========== I wrote an algorithm to create a lookup table to do just this several years ago. I used cosine bells for each of the colors. Red was centered on the first entry, green 1/3 of the way (85) through the table and blue 2/3's of the way (170) through the table. In tabular form they looked like. Start Peak End Rel. Hgt. Comments Red - 1 85 1.0 Green 1 85 170 1.0 Blue 85 170 255 1.0 Red 170 212 255 0.5 To get violet This implies that the half-period of the cosine bell used is 170. I used a cosine bell because it produced much better color mixing at constant intensity than using a triangle or parabolic function. ========== [ Note -- I wrote this C program based on some pseudo-code someone sent me. -DH ] #include <stdio.h> main() { int red[256], green[256], blue[256], Loop, x; FILE *fp; for (Loop=0;Loop<=42;++Loop) { red[Loop] = 255 ; green[Loop] = (int) Loop * 127/42 ; blue[Loop] = 0 ; } for (Loop=43;Loop<=84;++Loop) { red[Loop] = 255 ; green[Loop] = 127 + (Loop-43) * 128/41 ; blue[Loop] = 0 ; } for (Loop=85;Loop<=126;++Loop) { red[Loop] = 255 - (int) (Loop-85) * 255/41 ; green[Loop] = 255 ; blue[Loop] = 0 ; } for (Loop=127;Loop<=169;++Loop) { red[Loop] = 0 ; green[Loop] = 255 - (int) (Loop-127) * 255/42 ; blue[Loop] = (int) (Loop-127) * 255/42 ; } for (Loop=170;Loop<=211;++Loop) { red[Loop] = 0 ; green[Loop] = 0 ; blue[Loop] = 255 - (int) (Loop-170) * 128/41 ; } for (Loop=212;Loop<=255;++Loop) { red[Loop] = (int) (Loop-212) * 120/42 ; green[Loop] = 0 ; blue[Loop]= 127 ; } if ((fp=fopen("rbow.cmap.256","w"))==NULL) { fprintf(stderr,"Could not open file\n"); exit(1); } for (Loop = 0; Loop < 256; Loop++) { x = (red[Loop]<<16) + (blue[Loop]<<8) + green[Loop]; fwrite(&x, sizeof(int), 1, fp); } } ========== [ This is a little C program Chris Langton threw together some time ago; it produces a pretty decent rainbow. -DH ] #include "stdio.h" #define S 256 #define OUTFILE "rainbow.256.cmap" main() { int Map[S]; int i,j,k,r,g,b, inc; FILE *fp; inc = 6; r = 255; g = 0; b = 0; for (i = 0; i <= 60; i++) { Map[i] = (r<<16) + (g<<8) + b; g += inc; if (g > 255) g = 255; } g = 255; for (i = 61; i <= 105; i++) { r -= inc; if (r < 0) r = 0; Map[i] = (r<<16) + (g<<8) + b; } r = 0; for (i = 106; i <= 165; i++) { b += inc; if (b > 255) b = 255; Map[i] = (r<<16) + (g<<8) + b; } b = 255; for (i = 166; i <= 210; i++) { g -= inc; if (g < 0) g = 0; Map[i] = (r<<16) + (g<<8) + b; } g = 0; for (i = 211; i <= 255; i++) { r += inc; if (r > 255) r = 255; Map[i] = (r<<16) + (g<<8) + b; } fp = fopen(OUTFILE, "w"); fwrite(Map, sizeof(int), 256, fp); fclose(fp); } -- Dave Hiebeler hiebeler@cardinal.lanl.gov Center for Nonlinear Studies hiebeler@cs.rpi.edu MS B258 "xue zai shao" ("snow is burning") Los Alamos National Laboratory / Los Alamos, NM 87545