Created
May 13, 2010 13:36
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- 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