boostworthyisryantaylor

AS3: Drawing Color Spectrums

I have a collection of handy color spectrum classes in my personal library that are useful for creating a variety of color-picker components and what not. I thought I would share a few of them with you, as well as discuss the math that is involved in drawing a color spectrum.

Before diving in, I want to clarify how individual RGB channels are merged into one color value to ensure that everyone can follow along. Since each R, G, and B value is commonly represented by a value of ’0′ to ’255′, but when combined make up a single 24-bit color value, you need to understand a little bit about bitwise operations to understand how and why this is the case. In binary, you need 8 bits to represent a value that is up to 255, so ’00000000′ to ’11111111′. That means to represent three of these 8-bit numbers, you need to combine them into one big value of 16.7 million colors. Reading from right to left in binary, the first eight digits are blue, the second set are green, and the third set are red, making up a range of black ’000000000000000000000000′ to white ’111111111111111111111111′.

Now, a bitwise rotation will move a set of digits over to the left or right. So 255 (which is ’000000000000000011111111′) rotated left by 8 becomes ’000000001111111100000000′. So in practice:

ActionScript
< view plain text >
  1. nRed   = nR << 16;
  2. nGreen = nG << 8;
  3. nBlue  = nB;

Moving along…

You may be familiar with the use of sine waves for animation-related tasks, but did you know that they are also the key to drawing a color spectrum? A full cycle of ’0′ to ’2Pi’ with some additional math for offsetting the wave position for each color channel will gracefully rotate through the various color values of the visible spectrum. Once you have calculated each of the individual RGB channels, you can OR the values together to form a single color value.

ActionScript
< view plain text >
  1. nR = Math.cos(nRadians)                   * 127 + 128 << 16;
  2. nG = Math.cos(nRadians + 2 * Math.PI / 3) * 127 + 128 << 8;
  3. nB = Math.cos(nRadians + 4 * Math.PI / 3) * 127 + 128;
  4.  
  5. nColor  = nR | nG | nB;

In the case of a horizontal color spectrum, you can calculate the angle for the RGB values by using the percentage of the width you are drawing and then converting the degree to radians.

ActionScript
< view plain text >
  1. nColorPercent = i / nWidth;
  2.                
  3. nRadians = (-360 * nColorPercent) * (Math.PI / 180);

Now that you have the necessary color information, you are ready to use the Flash drawing API to draw the data to the display. In the case of my ‘ColorBar’ class, I simulate the color bar seen in the Photoshop color palette (with the horizontal color spectrum and a vertical fade from white to black).

ActionScript
< view plain text >
  1. objMatrixW = new Matrix();
  2. objMatrixW.createGradientBox(1, nHalfHeight, Math.PI * 0.5, 0, 0);
  3. objMatrixB = new Matrix();
  4. objMatrixB.createGradientBox(1, nHalfHeight, Math.PI * 0.5, 0, nHalfHeight);
  5.  
  6. graphics.lineStyle(1, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
  7. graphics.lineGradientStyle(GradientType.LINEAR, [0xFFFFFF, nColor], [100, 100], [0, 255], objMatrixW);
  8. graphics.moveTo(i, 0);
  9. graphics.lineTo(i, nHalfHeight);
  10. graphics.lineGradientStyle(GradientType.LINEAR, [nColor, 0], [100, 100], [0, 255], objMatrixB);
  11. graphics.moveTo(i, nHalfHeight);
  12. graphics.lineTo(i, nHeight);

Here is the result:

Example output from the ColorBar class.

Another nice way to present this data is in circular form (also known as a color wheel). We use the same method for calculating the RGB channels as before; however this time we can loop from ’0′ to ’360′ degrees and simply convert the degree to radians.

ActionScript
< view plain text >
  1. nRadians = i * (Math.PI / 180);

To render the circle itself, we use the angle of the color to plot the coordinate we are drawing the line to from the center of the circle.

ActionScript
< view plain text >
  1. nX = nRadius * Math.cos(nRadians);
  2. nY = nRadius * Math.sin(nRadians);

Now, like last time, we just use the Flash drawing API to draw the data. Note that the critical piece here is the matrix which is used to transform the gradient for the line being drawn; it must be rotated to match the angle of the line itself.

ActionScript
< view plain text >
  1. objMatrix = new Matrix();
  2. objMatrix.createGradientBox(nRadius * 2, nRadius * 2, nRadians, -nRadius, -nRadius);
  3.  
  4. graphics.lineStyle(iThickness, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
  5. graphics.lineGradientStyle(GradientType.LINEAR, [0xFFFFFF, nColor], [100, 100], [127, 255], objMatrix);
  6. graphics.moveTo(0, 0);
  7. graphics.lineTo(nX, nY);

And the result:

Example output from the ColorWheel class.

The math I have just demonstrated is extremely useful in working with color and can be used for much more than just simple little color-picker components. Below is a zip file that contains all the source for the color spectrums shown above.

Download ‘boostworthy_color_demos.zip’

I hope you will find this both useful and inspiring.

22 comments

22 Comments so far

  1. gabriel September 9th, 2007 11:35 am

    cool ryan, this is pretty nice.

  2. tim September 11th, 2007 3:06 am

    Cool! Any chance you can up the contrast on your CSS though, I had to read some of the code snippets using echo location ;-)

  3. Paul October 23rd, 2007 4:30 pm

    I really like the way you exploit the lineGradientStyle to quickly draw your gradient box, that’s a very smart and fast way to a wide range of colours displaying.

    However, I have to correct you on the way you generate your colours. While your method certainly works to some degree, many colours are unattainable this way. Take full yellow for instance: 0xffff00 can never occur because using the three offset, overlapping sinusoidal waves causes the red channel to begin decreasing before the green channel reaches its maximum value. You can see this most clearly in the circular spectrum in your article – the colours all have a pastel tone to them.

    I wrote a very basic utility for this some time ago with the same basic premise: iterate through the spectrum using an angle. Please feel free to use and improve on it. Pardon its sketchy state, I tried to quickly clean it up before packaging it.

    http://www.paulcoyle.com/code/AngularColour_1.0.zip

  4. Ryan Taylor October 24th, 2007 12:13 am

    Paul,

    Thank you for the kind words. I kind of knew that my approach wasn’t completely accurate. This stuff was more-or-less an experiment with sine waves and color channels that I happened to find some decent results with.

    Thanks for sharing your utility with me, I’ll definitely check it out!

  5. killmenosnueve February 11th, 2008 7:45 am

    thnx a lot!!!

  6. filip May 7th, 2008 2:05 pm

    Hi, thanks for sharing. I made a class for a color picker based on some of your maths … here’s the result:
    http://www.trickundtronic.at/swf/colorbar/

    thank you,
    filip


    http://www.filip-sound.com | http://www.myspace.com/feedmestarsmusic | http://www.trickundtronic.at

  7. filip May 9th, 2008 8:15 am

    Hi again,

    do you have some maths to reverse calculate the position of ANY given color to the x and y position in a ColorBar (the rectangular one)? since there are not all colors drawn in the bar, a simple loop does not do the job – except looking for the nearest color each time, wich is too cpu-eating. the resulting position sure should point to the nearest color.

    would be a great help, thanks,
    filip

  8. Justin Byrne July 23rd, 2008 3:25 pm

    Thank you so much. I found this extremely useful in some audio visualizations I’m working on.

    -Justin
    ___

    http://www.justinjbyrne.com/

  9. Chris September 18th, 2008 4:53 pm

    I know this is a way late post. I’m interested in grabbing the complimentary color based on an algorithm. So I understand how you are drawing the line and the color to the angle. How would you reverse that effect and say, color 0x00ff00 goes to x/y?

  10. Seba October 24th, 2008 2:34 pm

    Hi,

    This is great stuff, have you integrated this in a colorpicker??

    thanks

    Seba

  11. tox February 25th, 2009 3:55 pm

    thx a lot, this is great stuff. :)

  12. christian June 25th, 2009 2:59 pm

    hey. first thank you for that code explaination.
    Now im having a question. is it possible to perform a color gradient from only a few colors. I’m tryiing to sort colors in an Array with yout method, but im new to AS.

    greetz
    christian

  13. Edson Hilios July 21st, 2009 3:40 pm

    Thanks for the very good explanation, I liked the binary part a lot, that was a very clever way convert hexa in integer and vice versa.

    I rewrite your code like Paul said, considering the primary and secundary colors, but something is intriguing me, if i use the sine/cosine equation to draw a curve, this curve can be seen in the spectrum. When passing the primary to the secundary you will notice a large range of the secundary color spreading because of the sine equation, if you draw that in a graphic you will know better, the mix of colors will have an apperence of an U.

    For a more homogeneus spread i gonna be trying the slope equation y = 1 – x for the sin and y = x for cos

  14. alex silver October 21st, 2009 6:03 am

    Hi Ryan – i just found your example whilst teaching an as3 course – I was going through a drawing example using AS3 and was using an array to hold hex colours.
    But I decided to go looking to see if anyone had created a proper colour wheel or bar – lo and behold you had!
    Is it ok for me to use your code in my courses? with the comments kept in for proper attribution if course.
    Also, i have come across an oddity between Flex 4 and Flash CS4. In Flash CS4 the wheel and bar look nice and smooth, but in Flex 4 they look like separate lines, no smooth graduation – I have not had a chance to go through your code yet to see what might be the cause of this ( I am using Flex 4 beta 2) so I do not know of it is Flex causing the problem or not.

    regards
    alex

  15. theDarkIn1978 March 28th, 2010 10:08 am

    i officially fucking love you. oh, the hours i’ve spent trying to program / understand how to accomplish exactly this. xox.

  16. Drawing Color Spectrums : sprit3 April 7th, 2011 7:12 pm

    [...] Drawing Color Spectrums [...]

  17. R Petz June 21st, 2011 3:46 pm

    bah, looks like my code got jacked up a bit from the post protocol….here’s the class as an actionscript file:
    http://www.mediafire.com/?d7qf9idc469i7ii

    I use this in conjunction with Jeremiah Stephenson’s circular slider component here:
    http://jeremiahstephenson.blogspot.com/2011/06/flex-4-circular-slider.html

    That gives you a color wheel to pick hues a la Paint Shop Pro

  18. [...] First, I utilized the code from Ryan Taylor of BoostWorthy.com that was brought up in this tutorial: http://www.boostworthy.com/blog/?p=200 [...]

  19. jake May 4th, 2012 3:25 am

    This is fantastic! Thanks so much for the great code and explanation.

  20. [...] example builds upon the color scpectrum examples by boostworthyisryantaylor (http://www.boostworthy.com/blog/?p=200) and Paul Coyle’s AngularColour [...]

  21. [...] example builds upon the color scpectrum examples by boostworthyisryantaylor (http://www.boostworthy.com/blog/?p=200) and Paul Coyle’s AngularColour [...]

Leave a reply

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image