Skip to content

Instantly share code, notes, and snippets.

@toja
Last active June 3, 2016 08:14
Show Gist options
  • Save toja/e6e5583a1f5bab5e10b5ef00acc372e8 to your computer and use it in GitHub Desktop.
Save toja/e6e5583a1f5bab5e10b5ef00acc372e8 to your computer and use it in GitHub Desktop.
4096 Random Colors - DeltaE00
height: 480
license: gpl-3.0
// code adapted from https://github.com/zschuessler/DeltaE
function dE00(x1,x2){var sqrt=Math.sqrt;var pow=Math.pow;this.x1=x1;this.x2=x2;this.deltaLPrime=x2.l-x1.l;this.LBar=(x1.l+x2.l)/2;this.C1=sqrt(pow(x1.a,2)+pow(x1.a,2));this.C2=sqrt(pow(x2.b,2)+pow(x2.b,2));this.CBar=(this.C1+this.C2)/2;this.aPrime1=x1.a+x1.a/2*(1-sqrt(pow(this.CBar,7)/(pow(this.CBar,7)+pow(25,7))));this.aPrime2=x2.a+x2.a/2*(1-sqrt(pow(this.CBar,7)/(pow(this.CBar,7)+pow(25,7))));this.CPrime1=sqrt(pow(this.aPrime1,2)+pow(x1.b,2));this.CPrime2=sqrt(pow(this.aPrime2,2)+pow(x2.b,2));this.CBarPrime=(this.CPrime1+this.CPrime2)/2;this.deltaCPrime=this.CPrime2-this.CPrime1;this.SsubL=1+.015*pow(this.LBar-50,2)/sqrt(20+pow(this.LBar-50,2));this.SsubC=1+.045*this.CBarPrime;this.hPrime1=0;this.hPrime2=0;this.deltahPrime=0;this.deltaHPrime=0;this.HBarPrime=0;this.T=0;this.SsubH=0;this.RsubT=0}dE00.prototype.getDeltaE=function(){var sqrt=Math.sqrt;var sin=Math.sin;var pow=Math.pow;this.hPrime1=this.gethPrime1();this.hPrime2=this.gethPrime2();this.deltahPrime=this.getDeltahPrime();this.deltaHPrime=2*sqrt(this.CPrime1*this.CPrime2)*sin(this.degreesToRadians(this.deltahPrime)/2);this.HBarPrime=this.getHBarPrime();this.T=this.getT();this.SsubH=1+.015*this.CBarPrime*this.T;this.RsubT=this.getRsubT();var lightness=this.deltaLPrime/this.SsubL;var chroma=this.deltaCPrime/this.SsubC;var hue=this.deltaHPrime/this.SsubH;return sqrt(pow(lightness,2)+pow(chroma,2)+pow(hue,2)+this.RsubT*chroma*hue)};dE00.prototype.getRsubT=function(){var sin=Math.sin;var sqrt=Math.sqrt;var pow=Math.pow;var exp=Math.exp;return-2*sqrt(pow(this.CBarPrime,7)/(pow(this.CBarPrime,7)+pow(25,7)))*sin(this.degreesToRadians(60*exp(-pow((this.HBarPrime-275)/25,2))))};dE00.prototype.getT=function(){var cos=Math.cos;return 1-.17*cos(this.degreesToRadians(this.HBarPrime-30))+.24*cos(this.degreesToRadians(2*this.HBarPrime))+.32*cos(this.degreesToRadians(3*this.HBarPrime+6))-.2*cos(this.degreesToRadians(4*this.HBarPrime-63))};dE00.prototype.getHBarPrime=function(){var abs=Math.abs;if(abs(this.hPrime1-this.hPrime2)>180){return(this.hPrime1+this.hPrime2+360)/2}return(this.hPrime1+this.hPrime2)/2};dE00.prototype.getDeltahPrime=function(){var abs=Math.abs;if(0===this.C1||0===this.C2){return 0}if(abs(this.hPrime1-this.hPrime2)<=180){return this.hPrime2-this.hPrime1}if(this.hPrime2<=this.hPrime1){return this.hPrime2-this.hPrime1+360}else{return this.hPrime2-this.hPrime1-360}};dE00.prototype.gethPrime1=function(){return this._gethPrimeFn(this.x1.b,this.aPrime1)};dE00.prototype.gethPrime2=function(){return this._gethPrimeFn(this.x2.b,this.aPrime2)};dE00.prototype._gethPrimeFn=function(x,y){var hueAngle;if(x===0&&y===0){return 0}hueAngle=this.radiansToDegrees(Math.atan2(x,y));if(hueAngle>=0){return hueAngle}else{return hueAngle+360}};dE00.prototype.radiansToDegrees=function(radians){return radians*(180/Math.PI)};dE00.prototype.degreesToRadians=function(degrees){return degrees*(Math.PI/180)};
<!DOCTYPE html>
<meta charset="utf-8">
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="deltaE00.min.js"></script>
<body>
<script>
var width = 960,
height = 480,
deltaMin = 3.0,
numColors = 4096;
var x = d3.scale.linear()
.domain([0, 360])
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var dots = svg.append("g");
var num = svg.append("text")
.attr("x", 5)
.attr("y", 15);
var sample = colorSampler(numColors),
colors = [];
d3.timer(function() {
var hsl = sample();
if (!hsl) return true;
dots.append("circle")
.attr("cx", x(hsl.h))
.attr("cy", y(hsl.l))
.attr("r", 0)
.style("fill", hsl.toString())
.transition()
.attr("r", 4);
num.text(colors.length);
});
function colorSampler(numSamplesMax) {
return function() {
if (colors.length >= numSamplesMax) return false;
do {
var hsl = d3.hsl(Math.random() * 360, Math.random(), Math.random());
var lab = d3.lab(hsl);
}
while (!hsl.h || !isValidColor(lab));
colors.push(lab);
return hsl;
};
}
function isValidColor(lab) {
if (colors.length == 0)
return true;
for (i = 0; i < colors.length; i++) {
var delta = new dE00(lab, colors[i]).getDeltaE();
if (delta < deltaMin)
return false;
}
return true;
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment