A True Color Wheel 

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.

CArray m_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.