Skip to content

Instantly share code, notes, and snippets.

@VoQn
Created May 13, 2010 13:36
Show Gist options
  • Save VoQn/399832 to your computer and use it in GitHub Desktop.
Save VoQn/399832 to your computer and use it in GitHub Desktop.
Color model definission and Convert function each color models for HTML Canvas Element
// -*- mode: js2; coding: utf-8; -*-
/**
* colorspace.js
* Color Space Utility Functions for HTML Canvas Element
*
* Author: VoQn
*/
/** Utility Functions */
/**
* Compare and return value that is keep in range.
* If value is less than min, return min.
* If value more than max, return max.
* Otherwise return value.
* @param min lower limit
* @param value target compare value
* @param max upper limit
* @return value in range of (min <= value <= max)
*/
var innerVal = function(min, value, max){
return Math.max(min, Math.min(value, max));
};
/**
* formated String.
* USASE: format("%2s, %1s%3s", 'World', 'Hello', '!') -> "Hello, World!"
* @param fmt format string template
* @return string inserted arguments
*/
var format = function(fmt){
const loop = function(fmt, i, args){
return i < args.length ? loop(fmt.replace(new RegExp('%' + i + '\\$s', "g"), args[i]), ++i, args) : fmt;
};
return loop(fmt, 1, arguments);
};
/**
* setter access function for define setting
* @param arg argument of define constrator
* @param defvalue default value of the property
* @param proc control value function
*/
var defSet = function(arg, defValue, proc){
return !arg ? defValue : !proc ? arg : proc(arg);
};
/** Object Models */
/**
* HSV Color Space Model (& Added AlphaChannel)
* @param hue Hue of Color (0 <= H < 360)
* @param sat Saturation of Color (0.0 <= S <= 1.0)
* @param val Value(Brightness) of Color (0.0 <= V <= 1.0)
* @param alpha AlphaChannel (0.0 <= alpha <= 1.0)
*/
var HSVA = function(hue, sat, val, alpha){
var rate = 1.0;
this.rate = rate;
/**
* @param value target to compare
* @return value keep in range (0.0 <= value <= 1.0)
*/
const innerRange = function(value){
return innerVal(0.0, value, rate);
};
/**
* @param hue new Hue Value for this instance
* @return modified new Hue value
*/
const innerHueRange = function(hue){
return (function(value, mods){
return value < 0 ? mods - (-value % mods) % mods : value % mods;
})(hue, 360);
};
this.setHue = function(hue){
this.hue = defSet(hue, 0, innerHueRange);
};
this.setSat = function(sat){
this.sat = defSet(sat, 0, innerRange);
};
this.setVal = function(val){
this.val = defSet(val, 0, innerRange);
};
this.setAlpha = function(alpha){
this.alpha = defSet(alpha, 1, innerRange);
};
this.setHue(hue);
this.setSat(sat);
this.setVal(val);
this.setAlpha(alpha);
this.toString = function(){
return (function(hsva){
if(hsva.alpha == 1){
return format('hsv(%1$s, %2$s, %3$s)',
hsva.hue, hsva.sat, hsva.val);
}
return format('hsva(%1$s, %2$s, %3$s, %4$s)',
hsva.hue, hsva.sat, hsva.val, hsva.alpha);
})(this);
};
};
HSVA.prototype = {
'hue' :0.0,
'sat' :0.0,
'val' :0.0,
'alpha' :1.0,
'rate' :1.0
};
/**
* HLS Color Space Model (& Added AlphaChannel)
* @param hue
* @param lum
* @param sat
* @param alpha
*/
var HLSA = function(hue, lum, sat, alpha){
var rate = 1.0;
this.rate = rate;
/**
* @param value target to compare
* @return value keep in range (0.0 <= value <= 1.0)
*/
const innerRange = function(value){
return innerVal(0.0, value, rate);
};
/**
* @param hue new Hue Value for this instance
* @return modified new Hue value
*/
const innerHueRange = function(hue){
return (function(value, mods){
return value < 0 ? mods - (-value % mods) % mods : value % mods;
})(hue, 360);
};
this.setHue = function(hue){
this.hue = defSet(hue, 0, innerHueRange);
};
this.setLum = function(lum){
this.lum = defSet(lum, 0, innerRange);
};
this.setSat = function(sat){
this.sat = defSet(sat, 0, innerRange);
};
this.setAlpha = function(alpha){
this.alpha = defSet(alpha, 1, innerRange);
};
this.setHue(hue);
this.setLum(lum);
this.setSat(sat);
this.setAlpha(alpha);
/**
* @return information string about this Object status
*/
this.toString = function(){
return (function(hlsa){
if(hlsa.alpha == 1){
return format('hls(%1$s, %2$s, %3$s)',
hlsa.hue, hlsa.lum, hlsa.sat);
}
return format('hlsa(%1$s, %2$s, %3$s, %4$s)',
hlsa.hue, hlsa.lum, hlsa.sat, hlsa.alpha);
})(this);
};
};
HLSA.prototype = {
'hue' :0,
'lum' :0,
'sat' :0,
'alpha':1
};
/**
* RGB Color Space Model (And Added AlphaChannel)
* @param red Red Light Value
* @param blue Blue Light Value
* @param green Green Light Value
* @param alpha AlphaChannel
*/
var RGBA = function(red, blue, green, alpha){
var rate = 255.0;
this.rate = rate;
/**
* @param value target to compare
* @return value keep in range (0.0 <= value <= 255.0)
*/
const innerRangeRGB = function(value){
return innerVal(0.0, value, rate);
};
/**
* @param value target to compare
* @return value keep in range (0.0 <= value <= 1.0)
*/
const innerRangeAlpha = function(value){
return innerVal(0.0, value, 1.0);
};
this.setRed = function(red){
this.red = defSet(red, 0, innerRangeRGB);
};
this.setGreen = function(green){
this.green = defSet(green, 0, innerRangeRGB);
};
this.setBlue = function(blue){
this.blue = defSet(blue, 0, innerRangeRGB);
};
this.setAlpha = function(alpha){
this.alpha = defSet(alpha, 1, innerRangeAlpha);
};
this.setRed(red);
this.setGreen(green);
this.setBlue(blue);
this.setAlpha(alpha);
/**
* @return information string about this Object status
*/
this.toString = function(){
return (function(rgba) {
if(rgba.alpha == 1){
return format('rgb(%1$s, %2$s, %3$s)',
rgba.red, rgba.green, rgba.blue);
}
return format('rgba(%1$s, %2$s, %3$s, %4$s)',
rgba.red, rgba.green, rgba.blue, rgba.alpha);
})(this);
};
};
RGBA.prototype = {
'red' :0,
'blue' :0,
'green' :0,
'alpha' :1
};
/**
* RGB Box Model
* @param H hue segment status
* @param C chroma
* @param X the intermediate value for second largest component of this color
*/
var RGB = function(H, C, X){
var red, green, blue;
/**
* define setting menber
* @param _red new Red Value
* @param _green new Green Value
* @param _blue new Blue Value
*/
const make = function(_red, _green, _blue){
red = _red;
green = _green;
blue = _blue;
};
// Initialize
switch(Math.floor(H)){
case 0: make(C, X, 0); break;
case 1: make(X, C, 0); break;
case 2: make(0, C, X); break;
case 3: make(0, X, C); break;
case 4: make(X, 0, C); break;
case 5: make(C, 0, X); break;
default: make(0, 0, 0);
}
this.red = red;
this.green = green;
this.blue = blue;
};
const makeRGBA = function(H, C, X, alpha, m){
const rgb = new RGB(H, C, X);
const rate = (new RGBA).rate;
const calc = function(v){
return Math.round((v + m) * rate);
};
return new RGBA(calc(rgb.red), calc(rgb.green), calc(rgb.blue), alpha);
};
/**
* convert Color from HSVA Model to RGBA Model
* @param hsva HSVA Color Model Object
*/
const convertHSVAtoRGBA = function(hsva){
const H = hsva.hue / 60.0;
const S = hsva.sat / hsva.rate;
const V = hsva.val / hsva.rate;
const A = hsva.alpha / hsva.rate;
const C = V * S; // chroma
const X = C * (1 - Math.abs(H % 2 - 1));
const m = V - C;
return makeRGBA(H, C, X, A, m);
};
/**
* convert Color from HLSA Model to RGBA Model
* @param hlsa HLSA Color Model Object
*/
const convertHLSAtoRGBA = function(hlsa){
const H = hlsa.hue / 60.0;
const L = hlsa.lum / hlsa.rate;
const S = hlsa.sat / hlsa.rate;
const A = hlsa.alpha / hlsa.rate;
const C = (L <= 1 / 2) ? 2 * L * S : 2 * (1 - L) * S; // chroma
const X = C * (1 - Math.abs(H % 2 - 1));
const m = L - C / 2;
return makeRGBA(H, C, X, A, m);
};
/**
* convert Color from RGBA Model to HSVA Model
* @param rgba RGBA Color Model Object
*/
const convertRGBAtoHSVA = function(rgba){
const red = rgba.red / rgba.rate;
const green = rgba.green / rgba.rate;
const blue = rgba.blue / rgba.rate;
const alpha = rgba.alpha;
const max = Math.max(red, green, blue);
const min = Math.min(red, green, blue);
const val = max;
if(val == 0){
return new HSVA(val, val, val, alpha);
}
const sat = (max - min) / max;
const calc = function(value){
return (max - value) / (max - min);
};
const cr = calc(red);
const cg = calc(green);
const cb = calc(blue);
const hue = ((red == max ? cb - cg
: green == max ? 2 + cr - cb
: 4 + cg - cr)
* 60 + 360);
return new HSVA(hue, sat, val, alpha);
};
/**
* convert Color from RGBA Model to HLSA
* @param rgba RGBA Color Model Object
*/
const convertRGBAtoHLSA = function(rgba){
const red = rgba.red / rgba.rate;
const green = rgba.green / rgba.rate;
const blue = rgba.blue / rgba.rate;
const alpha = rgba.alpha / rgba.rate;
const max = Math.max(red, green, blue);
const min = Math.min(red, green, blue);
const lum = (max + min) / 2;
if(max == min){
return new HLSA(0, 0, lum, alpha);
}
const sat = lum <= 0.5
? (max - min) / (max + min)
: (max - min) / (2 - max - min);
const calc = function(value){
return (max - value) / (max - min);
};
const cr = calc(red);
const cg = calc(green);
const cb = calc(blue);
const hue = ((red == max ? cb - cg : green == max ? 2 + cr - cb : 4 + cg - cr) * 60 + 360);
return new HLSA(hue, sat, lum, alpha);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment