(HSV HSB) to RGB

Actionscript:
  1. [SWF(width=720,height=360,backgroundColor=0x000000,frameRate=30)]
  2.  
  3. // ported from here:
  4. //http://www.cs.rit.edu/~ncs/color/t_convert.html
  5.  
  6. function hsv(h:Number, s:Number, v:Number):Array{
  7.     var r:Number, g:Number, b:Number;
  8.     var i:int;
  9.     var f:Number, p:Number, q:Number, t:Number;
  10.      
  11.     if (s == 0){
  12.         r = g = b = v;
  13.         return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
  14.     }
  15.    
  16.     h /= 60;
  17.     i  = Math.floor(h);
  18.     f = h - i;
  19.     p = v *  (1 - s);
  20.     q = v * (1 - s * f);
  21.     t = v * (1 - s * (1 - f));
  22.    
  23.     switch( i ) {
  24.         case 0:
  25.             r = v;
  26.             g = t;
  27.             b = p;
  28.             break;
  29.         case 1:
  30.             r = q;
  31.             g = v;
  32.             b = p;
  33.             break;
  34.         case 2:
  35.             r = p;
  36.             g = v;
  37.             b = t;
  38.             break;
  39.         case 3:
  40.             r = p;
  41.             g = q;
  42.             b = v;
  43.             break;
  44.         case 4:
  45.             r = t;
  46.             g = p;
  47.             b = v;
  48.             break;
  49.         default:        // case 5:
  50.             r = v;
  51.             g = p;
  52.             b = q;
  53.             break;
  54.     }
  55.     return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
  56. }
  57.  
  58.  
  59. //
  60. //  -- test it out by drawing a few things
  61. //
  62.  
  63. var canvas:BitmapData = new BitmapData(720, 360, false, 0x000000);
  64.  
  65. addChild(new Bitmap(canvas));
  66.  
  67. canvas.lock();
  68. var size:int = canvas.width * canvas.height;
  69. var xp:int, yp:int, c:Array, i:int;
  70.  
  71. for (i = 0; i<size; i++){
  72.     xp = i % 360;
  73.     yp = i / 360;
  74.     c =  hsv(xp, 1, yp / 360);
  75.     canvas.setPixel(xp, yp, c[0] <<16 | c[1] <<8 | c[2]);
  76. }
  77.  
  78. var dx:Number, dy:Number, dist:Number, ang:Number;
  79.  
  80. for (i = 0; i<size; i++){
  81.     xp = i % 360;
  82.     yp = i / 360;
  83.     dx = xp - 180;
  84.     dy = yp - 180;
  85.     dist = 1 - Math.sqrt((dx * dx) + (dy * dy)) / 360;
  86.     ang = Math.atan2(dy, dx) / Math.PI * 180;
  87.     if (ang <0){
  88.         ang += 360;
  89.     }
  90.     c =  hsv(ang, 1, dist);
  91.     canvas.setPixel(360 + xp, yp, c[0] <<16 | c[1] <<8 | c[2]);
  92. }
  93. canvas.unlock();

This is one of those things I've been meaning to play with for awhile. The above demos a function called hsv() which takes 3 arguments: angle (0-360), saturation(0-1) and value(0-1). The function returns an array of rgb values each with a range of (0-255).

There's some room for optimization here, but for clarity I left as is. Even just playing with HSV (also know as HSB) for a few minutes, I see some interesting potential for dynamically generating color palettes for generative style experiments.

I looked around for the most elegant looking code snippet to port in order to write this... I eventually stumbled upon this great resource.

If you test the above on your timeline it will generate this image:

I usually only post one snippet a day... not sure why I decided to post two today.

This entry was posted in BitmapData, color, graphics algorithms, pixel manipulation, setPixel and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

5 Comments

  1. Posted September 27, 2009 at 11:53 am | Permalink

    This is surprisingly intense for what it is… very cool though!

    j

  2. Posted September 27, 2009 at 4:49 pm | Permalink

    yeah you’d think converting between HSV and RGB would be simpler :)

  3. sydd
    Posted November 11, 2009 at 3:01 am | Permalink

    Thanks for the snipplet, really useful to me

  4. Pascal
    Posted October 12, 2010 at 9:55 pm | Permalink

    There is an omission in the hsv to rgb function, above, which would cause a rendering anomaly, if you provided a hue of 360.

    Basically: h needs to be wrapped prior to being divided by 60, like so:

    h %= 360; // this guarantees that h can only range within [0, 360)
    h /= 60;

    Also, you can exit early if:

    if (v == 0){
    r = g = b = 0;
    return [0, 0, 0,];
    }

  5. Filipe Luchini
    Posted October 22, 2010 at 12:57 pm | Permalink

    IN: Thanks for post, helped me a lot o/
    BR: Obrigado pelo post, me ajudou muito o/

One Trackback

  1. By Mandelbrot set with haXe « Georg Graf on November 7, 2009 at 2:25 pm

    [...] I modified the RGB class, i found on the web. [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*