// 8-bit Palette Classes for use in HTML5 Canvas
// Ported from a C++ library written by Joseph Huckaby
// BlendShift Technology conceived, designed and coded by Joseph Huckaby
// Copyright (c) 2001-2002, 2010 Joseph Huckaby.
// Released under the LGPL v3.0: http://www.opensource.org/licenses/lgpl-3.0.html
Class.create( 'Color', {
// represents one 24-bit RGB color
red: 0,
green: 0,
blue: 0,
__construct: function(r, g, b) {
this.set(r, g, b);
},
set: function(r, g, b) {
this.red = r;
this.green = g;
this.blue = b;
}
} );
Class.create( 'Cycle', {
// represents one cycle (one range of colors that animate)
rate: 0,
reverse: 0,
low: 0,
high: 0,
__construct: function(r, rev, l, h) {
this.rate = r;
this.reverse = rev;
this.low = l;
this.high = h;
}
} );
Class.create( 'Palette', {
// represents a single palette, which can have
// multiple "cycles" (animated color ranges) defined.
colors: null,
baseColors: null,
cycles: null,
numColors: 0,
numCycles: 0,
__static: {
// static class members
PRECISION: 100,
USE_BLEND_SHIFT: 1,
CYCLE_SPEED: 280,
ENABLE_CYCLING: 1,
// this utility function allows for variable precision floating point modulus
DFLOAT_MOD: function(a,b) { return (Math.floor(a*Palette.PRECISION) % Math.floor(b*Palette.PRECISION))/Palette.PRECISION; }
},
__construct: function(clrs, cycls) {
// class constructor
this.colors = [];
this.baseColors = [];
for (var idx = 0, len = clrs.length; idx < len; idx++) {
var clr = clrs[idx];
this.baseColors.push( new Color( clr[0], clr[1], clr[2] ) );
}
this.cycles = [];
for (var idx = 0, len = cycls.length; idx < len; idx++) {
var cyc = cycls[idx];
this.cycles.push( new Cycle( cyc.rate, cyc.reverse, cyc.low, cyc.high ) );
}
this.numColors = this.baseColors.length;
this.numCycles = this.cycles.length;
},
copyColors: function(source, dest) {
// copy one array of colors to another
for (var idx = 0, len = source.length; idx < len; idx++) {
if (!dest[idx]) dest[idx] = new Color();
dest[idx].red = source[idx].red;
dest[idx].green = source[idx].green;
dest[idx].blue = source[idx].blue;
}
},
swapColors: function(a, b) {
// swap the color values of a with b
var temp;
temp = a.red; a.red = b.red; b.red = temp;
temp = a.green; a.green = b.green; b.green = temp;
temp = a.blue; a.blue = b.blue; b.blue = temp;
},
reverseColors: function(colors, range) {
// reverse order of colors
var i;
var cycleSize = (range.high - range.low) + 1;
for (i=0; i max) frame = max;
tempColor.red = Math.floor( sourceColor.red + (((destColor.red - sourceColor.red) * frame) / max) );
tempColor.green = Math.floor( sourceColor.green + (((destColor.green - sourceColor.green) * frame) / max) );
tempColor.blue = Math.floor( sourceColor.blue + (((destColor.blue - sourceColor.blue) * frame) / max) );
return(tempColor);
},
shiftColors: function(colors, range, amount) {
// shift (hard cycle) colors by amount
var i, j, temp;
amount = Math.floor(amount);
for (i = 0; i < amount; i++) {
temp = colors[range.high];
for (j=range.high-1; j>=range.low; j--)
colors[j+1] = colors[j];
colors[range.low] = temp;
} // i loop
},
blendShiftColors: function(colors, range, amount) {
// shift colors using BlendShift (fade colors creating a smooth transition)
// BlendShift Technology conceived, designed and coded by Joseph Huckaby
var j, temp;
this.shiftColors(colors, range, amount);
var frame = Math.floor( (amount - Math.floor(amount)) * Palette.PRECISION );
temp = colors[range.high];
for (j=range.high-1; j>=range.low; j--)
colors[j+1] = this.fadeColor(colors[j+1], colors[j], frame, Palette.PRECISION);
colors[range.low] = this.fadeColor(colors[range.low], temp, frame, Palette.PRECISION);
},
cycle: function(sourceColors, timeNow, speedAdjust, blendShift) {
// cycle all animated color ranges in palette based on timestamp
var i;
var cycleSize, cycleRate;
var cycleAmount;
this.copyColors( sourceColors, this.colors );
if (Palette.ENABLE_CYCLING) {
for (i=0; i= cycleSize) cycleAmount = (cycleSize*2) - cycleAmount;
}
else if (cycle.reverse < 6) {
// sine wave
cycleAmount = DFLOAT_MOD((timeNow / (1000 / cycleRate)), cycleSize);
cycleAmount = Math.sin((cycleAmount * 3.1415926 * 2)/cycleSize) + 1;
if (cycle.reverse == 4) cycleAmount *= (cycleSize / 4);
else if (cycle.reverse == 5) cycleAmount *= (cycleSize / 2);
}
if (cycle.reverse == 2) this.reverseColors(this.colors, cycle);
if (Palette.USE_BLEND_SHIFT && blendShift) this.blendShiftColors(this.colors, cycle, cycleAmount);
else this.shiftColors(this.colors, cycle, cycleAmount);
if (cycle.reverse == 2) this.reverseColors(this.colors, cycle);
cycle.cycleAmount = cycleAmount;
} // active cycle
} // i loop
}
},
fade: function(destPalette, frame, max) {
// fade entire palette to another, by adjustable amount
var idx;
for (idx=0; idx