Tuesday, July 21, 2009

Revision to calculateDerivedColor()

First, an explanation. What I'm trying to do is answer the question: what color is to blue as green is to beige? It's kind of a silly question, but it's very useful for recoloring an entire theme.

Without further ado, here's the code:


public class ColorUtils
{
/**
* Returns result, where a is to result as b is to c. The parameters and result are between 0 and 1.
*
* This is somewhat ambiguous. When b is 0.5 and c is 1, should this return a * 2, or a + 0.5?
* There's no simple answer, so use both approaches and return the average.
*/
private static function applyDifference(a:Number, b:Number, c:Number):Number
{
var linearAdjusted:Number = a + c - b;
var multiplierAdjusted:Number;
if (b == 0)
multiplierAdjusted = 2;
else
{
multiplierAdjusted = a * c / b;
multiplierAdjusted = Math.min(multiplierAdjusted, 2);
}
a = (linearAdjusted + multiplierAdjusted) / 2;
return Math.max(0, Math.min(a, 1));
}


/**
* Return a color derived from baseColor using sampleStartColor and sampleEndColor as a guide.
* For example, this function would return dark blue if baseColor was light blue, sampleStartColor
* was pink and sampleEndColor was dark red.
*
* It's like an SAT question: red is to x as dark green is to greenish gray. What's x?
*/
public static function calculateDerivedColor(baseColor:uint, sampleStartColor:uint, sampleEndColor:uint):uint
{
var baseColorHSL:HslColor = new HslColor(baseColor);

var sampleStartColorHSL:HslColor = new HslColor(sampleStartColor);
var sampleEndColorHSL:HslColor = new HslColor(sampleEndColor);

// rotate the hue and offset the saturation and lightness based on the inputs
baseColorHSL.h = (baseColorHSL.h + sampleEndColorHSL.h - sampleStartColorHSL.h + 360) % 360;

baseColorHSL.s = applyDifference(baseColorHSL.s, sampleStartColorHSL.s, sampleEndColorHSL.s);
baseColorHSL.l = applyDifference(baseColorHSL.l, sampleStartColorHSL.l, sampleEndColorHSL.l);

return baseColorHSL.rgb;
}

No comments:

Post a Comment