# A True Color Wheel

**John Killingbeck**on

**August 1st, 1999**

__Environment:__ VC4

The following is a code snippet written in VC++ 4.0. It generates a CArray of COLORREF objects that forms a true color circle. The two input parameters are integers in the range of 0 to 5 to accomodate two sets of radio buttons in a dialog box. I developed this routine to use in a Mandelbrot fractal generator program. It can be used in math displays where the color indicates phase shift.

The requirements that I set are that the three primary colors (red, green, blue) be guaranteed pure and that shadings be evenly spaced. This leads to the palette sizes being solutions to 3 * 2^n (3 < (int)n < 8). This way the palette starts at a reasonable size and run to the resolution of 24 bit systems. A bug in the 4.0 compiler led me to write this as in-line code rather than a separate function. 4.0 doesn't like accessing template arrays from within a function. The generation code may be written as a separate function in later MFC releases (untested).

Even brightness is achieved by ramping the colors up and down with the sine/cosine function from 0 to pi/2. I left the ramp calculations unoptimized so that the equations are more decipherable (ie. 256 * pi / 2 instead of 128 * pi). Even so, the VC compiler will optimize this calculation for us.

// Input variables. both are in range of 0-5 to work with // dialog box radio buttons. // Color shift radio buttons are arranged for the three primary colors // (Blue, Green Red) in the top row of a 3X2 arrangement and the // complementary color (Yellow, Magenta, Cyan) in the bottom row. // Palette generates Blue-Red-Green-Blue sequence as written. // Palette sizes are calculated by 3 * 2^n (3 < (int)n < 8). int nPalSize; int nColorShift; double pi = 3.1415926535; // Generate color palette. // Colors represent the outer edge of a 24 bit (maximum) color palette. // Colors are equally spaced around the edge of the color circle. // Use CArray object to use functions and dynamic sizing. CArraym_colorArray; // Arrays to translate palette size and color shift // from parameter array integers. Initial integers // correspond to radio button values in parameter // dialog box. int PalSizeArray[] = { 24, 48, 96, 192, 384, 768 }; // Color shift blue, green, red, yellow, magenta, cyan int ColorShiftArray[] = { 0, 511, 255, 383, 127, 639 }; nPalSize = PalSizeArray[ nPalSize ]; nColorShift = ColorShiftArray[ nColorShift ]; // First range check if ( nPalSize > 768 ) nPalSize = 768; if ( nPalSize < 24 ) nPalSize = 24; // Now set the array size. May be one too big after modifications. // At least not harmful. m_colorArray.SetSize( nPalSize + 1 ); // Then set the palette for ( int n = 0; n <= nPalSize; ++n ) { // nFactor calculate position of n in maximized palette ( 768 total colors ) int nFactor; int nRed, nGreen, nBlue; nFactor = 768 * n / nPalSize; // Assure that it runs 0 to 768 nFactor = nFactor + nColorShift; if ( nFactor >= 768 ) // Adjust for color shift nFactor = nFactor - 768; // Color calculations include sine/cosine functions to create // colors at constant radius from center of color circle. This // creates a constant brightness level. Math not optimized, left in readable state. if ( nFactor <= 256 ) { // Red increasing, no green, blue decreasing nRed = int( (double)255 * (sin( ( (double)nFactor/256) * pi / 2 ) ) ); nGreen = 0; nBlue = int( (double)255 * (cos( ( (double)nFactor/256) * pi / 2 ) ) ); m_colorArray.SetAt( n, COLORREF( RGB( nRed, nGreen, nBlue ) ) ); } else if ( ( nFactor > 256 ) && ( nFactor <= 512 ) ) { // Red decreasing, green increasing, blue 0. nRed = int( (double)255 * (cos( ( (double)(nFactor - 256 ) /256) * pi / 2 ) ) ); nGreen = int( (double)255 * (sin( ( (double)(nFactor - 256 ) /256) * pi / 2 ) ) ); nBlue = 0; m_colorArray.SetAt( n, COLORREF( RGB( nRed, nGreen, nBlue ) ) ); } else if ( ( nFactor > 512 ) ) { // Red 0, green decreasing, blue increasing nRed = 0; nGreen = int( (double)255 * (cos( ( (double)(nFactor - 512 ) /256) * pi / 2 ) ) ); nBlue = int( (double)255 * (sin( ( (double)(nFactor - 512 ) /256) * pi / 2 ) ) ); m_colorArray.SetAt( n, COLORREF( RGB( nRed, nGreen, nBlue ) ) ); } } // Now there is CArray of COLORREF objects of nPalSize size. // The palette guarantees a pure red, blue and green with // constant brightness and even spacing of colors between primaries. // If the color shift is set to a secondary color (cyan, magenta // yellow) then the seconday colors are guaranteed pure.