Browse the notebook

Tag: color

(HSV HSB) to RGB

[SWF(width=720,height=360,backgroundColor=0x000000,frameRate=30)]

// ported from here:
//http://www.cs.rit.edu/~ncs/color/t_convert.html

function hsv(h:Number, s:Number, v:Number):Array{
	var r:Number, g:Number, b:Number;
	var i:int;
	var f:Number, p:Number, q:Number, t:Number;
	 
	if (s == 0){
		r = g = b = v;
		return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
	}
	
	h /= 60;
	i  = Math.floor(h);
	f = h - i;
	p = v *  (1 - s);
	q = v * (1 - s * f);
	t = v * (1 - s * (1 - f));
	
	switch( i ) {
		case 0:
			r = v;
			g = t;
			b = p;
			break;
		case 1:
			r = q;
			g = v;
			b = p;
			break;
		case 2:
			r = p;
			g = v;
			b = t;
			break;
		case 3:
			r = p;
			g = q;
			b = v;
			break;
		case 4:
			r = t;
			g = p;
			b = v;
			break;
		default:		// case 5:
			r = v;
			g = p;
			b = q;
			break;
	}
	return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}


//
//  -- test it out by drawing a few things
//

var canvas:BitmapData = new BitmapData(720, 360, false, 0x000000);

addChild(new Bitmap(canvas));
 
canvas.lock();
var size:int = canvas.width * canvas.height;
var xp:int, yp:int, c:Array, i:int;

for (i = 0; i<size; i++){
	xp = i % 360;
	yp = i / 360;
	c =  hsv(xp, 1, yp / 360);
	canvas.setPixel(xp, yp, c[0] << 16 | c[1] << 8 | c[2]);
}

var dx:Number, dy:Number, dist:Number, ang:Number;

for (i = 0; i<size; i++){
	xp = i % 360;
	yp = i / 360;
	dx = xp - 180;
	dy = yp - 180;
	dist = 1 - Math.sqrt((dx * dx) + (dy * dy)) / 360;
	ang = Math.atan2(dy, dx) / Math.PI * 180;
	if (ang < 0){
		ang += 360;
	}
	c =  hsv(ang, 1, dist);
	canvas.setPixel(360 + xp, yp, c[0] << 16 | c[1] << 8 | c[2]);
}
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.

Read snippet: (HSV HSB) to RGB

Basic Tint Function

// display object, red (0-255), green, blue, amount (0-1)
function tint(dsp:DisplayObject, r:Number, g:Number, b:Number, amount:Number=1):void {
	if (amount != 1) {
		r *= amount;
		g *= amount;
		b *= amount;
	}
	amount = 1-amount;
	var ct:ColorTransform = transform.colorTransform;
	ct.redOffset = r;
	ct.redMultiplier = amount;
	ct.greenOffset = g;
	ct.greenMultiplier = amount;
	ct.blueOffset = b;
	ct.blueMultiplier = amount;
	dsp.transform.colorTransform = ct;
}

// test out the tint function on a circle with a stroke:
var circle:Shape = Shape(addChild(new Shape()));
with (circle.graphics) {
	lineStyle(5, 0x339999);
	beginFill(0x003333);
	drawCircle(0,0,50);
	x = 100;
	y = 100;
}

// tint the circle 50% green
tint(circle, 0, 255, 0, .5);

The ColorTransform object is a little confusing with its “redMultiplier, redOffset, greenMultiplier etc…” properties. Once you understand them it’s not a big deal, but I still find them a bit cumbersome. So when I just want to tint a clip similar to the way you might tint a clip in the IDE… I use this tint function. Rather than taking a hexidecimal number it takes values for red, green and blue (0-255) – and an amount argument (0-1).

Read snippet: Basic Tint Function

XOR Color Invert

var yellow:uint = 0xFFFF00;

// draws yellow circle
with(graphics) beginFill(yellow), drawCircle(100,100,50);

// invert the color using XOR assignment
// yellow becomes 0x0000FF
yellow ^= 0xFFFFFF;

// draws blue  circle 
with(graphics) beginFill(yellow), drawCircle(200,100,50);

Just a fun use for XOR. You could also do it without XOR assignment:

with(graphics) beginFill(yellow ^ 0xFFFFFF), drawCircle(200,100,50);

Playing a little with bitwise operators is a good way to make sure you understand them. Try tweaking this trace statement:

trace((0x543210 ^ 0xFFFFFF).toString(16));

If you’d like to read about bitwise operators, I recommend wikipedia’s article.

Read snippet: XOR Color Invert