Created
October 22, 2010 23:01
-
-
Save mikelikespie/641528 to your computer and use it in GitHub Desktop.
Quick code to convert sRGB to CIE L*a*b* and back.
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
/* | |
* To try it: | |
* c = $c.sRGB8(23,58,32); | |
* c.Lab(); | |
* c.Lab().sRGB8(); | |
*/ | |
var $c = {}; | |
( | |
function () { | |
function Lab (l, a, b) { | |
this.l = l; | |
this.a = a; | |
this.b = b; | |
} | |
$c.Lab = function (l,a,b) { | |
return new Lab(l,a,b); | |
}; | |
function XYZ (x, y, z) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
} | |
$c.XYZ = function (l,a,b) { | |
return new XYZ(x, y, z); | |
}; | |
function sRGBLinear (r, g, b) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
} | |
$c.sRGBLinear = function (r,g,b) { | |
return new sRGBLinear(r,g,b); | |
}; | |
function sRGBPrime (r, g, b) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
} | |
$c.sRGBPrime = function (r,g,b) { | |
return new sRGBPrime(r,g,b); | |
}; | |
function sRGB8 (r, g, b) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
} | |
$c.sRGB8 = function (r,g,b) { | |
return new sRGB8(r,g,b); | |
}; | |
var D65 = new XYZ(0.9504, 1.0000, 1.0888); | |
Lab.prototype.XYZ = function () { | |
var p = (this.l + 16.0) / 116.0; | |
var x_part = p + this.a / 500.0; | |
var z_part = (p - this.b / 200.0); | |
return new XYZ ( | |
D65.x * x_part * x_part * x_part, | |
D65.y * p * p * p, | |
D65.z * z_part * z_part * z_part | |
); | |
}; | |
Lab.prototype.sRGB8 = function () { | |
return this.XYZ().sRGBLinear().sRGBPrime().sRGB8(); | |
}; | |
function _XYZf(t) { | |
if (t > 0.008856) { | |
return Math.pow(t, 1.0/3.0); | |
} else { | |
return 7.787 * t + 16.0/116.0; | |
} | |
} | |
XYZ.prototype.Lab = function () { | |
var x_xn = this.x / D65.x; | |
var y_yn = this.y / D65.y; | |
var z_zn = this.z / D65.z; | |
var f_x_xn = _XYZf(x_xn); | |
var f_y_yn = _XYZf(y_yn); | |
var f_z_zn = _XYZf(z_zn); | |
return new Lab ( | |
y_yn > 0.008856 ? | |
116.8 * Math.pow(y_yn, 1.0/3.0) - 16 : | |
903.3 * y_yn, | |
500.0 * (f_x_xn - f_y_yn), | |
200.0 * (f_y_yn - f_z_zn) | |
); | |
}; | |
var XYZ_TO_RGB = [ | |
[ 3.240479, -1.537150, -0.498535], | |
[-0.969256, 1.875992, 0.041556], | |
[ 0.055648, -0.204043, 1.057311] | |
]; | |
XYZ.prototype.sRGBLinear = function () { | |
return new sRGBLinear( | |
this.x * XYZ_TO_RGB[0][0] + this.y * XYZ_TO_RGB[0][1] + this.z * XYZ_TO_RGB[0][2], | |
this.x * XYZ_TO_RGB[1][0] + this.y * XYZ_TO_RGB[1][1] + this.z * XYZ_TO_RGB[1][2], | |
this.x * XYZ_TO_RGB[2][0] + this.y * XYZ_TO_RGB[2][1] + this.z * XYZ_TO_RGB[2][2] | |
); | |
}; | |
var RGB_TO_XYZ = [ | |
[0.412453, 0.357580, 0.180423], | |
[0.212671, 0.715160, 0.072169], | |
[0.019334, 0.119193, 0.950227] | |
]; | |
sRGBLinear.prototype.XYZ = function () { | |
return new XYZ ( | |
this.r * RGB_TO_XYZ[0][0] + this.g * RGB_TO_XYZ[0][1] + this.b * RGB_TO_XYZ[0][2], | |
this.r * RGB_TO_XYZ[1][0] + this.g * RGB_TO_XYZ[1][1] + this.b * RGB_TO_XYZ[1][2], | |
this.r * RGB_TO_XYZ[2][0] + this.g * RGB_TO_XYZ[2][1] + this.b * RGB_TO_XYZ[2][2] | |
); | |
}; | |
var ALPHA = 0.055; | |
function _linearToLog(c) { | |
if ( c <= 0.0031308) { | |
return 12.92 * c; | |
} else { | |
return (1 + ALPHA) * Math.pow(c, 1/2.4) - ALPHA; | |
} | |
} | |
sRGBLinear.prototype.sRGBPrime = function () { | |
return new sRGBPrime( | |
_linearToLog(this.r), | |
_linearToLog(this.g), | |
_linearToLog(this.b) | |
); | |
}; | |
function _logToLinear(c) { | |
if ( c <= 0.04045) { | |
return c / 12.92; | |
} else { | |
return Math.pow((c + ALPHA) / (1 + ALPHA), 2.4); | |
} | |
} | |
sRGBPrime.prototype.sRGBLinear = function () { | |
return new sRGBLinear( | |
_logToLinear(this.r), | |
_logToLinear(this.g), | |
_logToLinear(this.b) | |
); | |
}; | |
sRGBPrime.prototype.sRGB8 = function () { | |
return new sRGB8( | |
this.r * 255.0, | |
this.g * 255.0, | |
this.b * 255.0 | |
); | |
}; | |
sRGB8.prototype.sRGBPrime = function () { | |
return new sRGBPrime( | |
this.r/255.0, | |
this.g/255.0, | |
this.b/255.0 | |
); | |
}; | |
sRGB8.prototype.Lab = function () { | |
return this.sRGBPrime().sRGBLinear().XYZ().Lab(); | |
}; | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment