floydsteinberg = {
function diffuseError(mydata, r, c, error, factor){
var idx = rowcol2index(r, c, w, h);
mydata[idx+0] = Math.max(Math.min(mydata[idx+0] + factor*error.r,255),0);
mydata[idx+1] = Math.max(Math.min(mydata[idx+1] + factor*error.g,255),0);
mydata[idx+2] = Math.max(Math.min(mydata[idx+2] + factor*error.b,255),0);
return(mydata)
}
var context = DOM.context2d(w, h);
var imgData = context.createImageData(w, h);
var dithered = [];
for (var ii=0; ii<raw_rgba.length; ii++){
imgData.data[ii] = raw_rgba[ii];
dithered.push(raw_rgba[ii]);
}
var paletteIDs = [];
for (var ii=0; ii<dithered.length; ii+=4){
var RC = index2rowcol(ii, w, h);
var myRow = RC.r;
var myCol = RC.c;
var thisRawColor = d3.rgb(dithered[ii+0],
dithered[ii+1],
dithered[ii+2]);
var thisOrigColor = d3.rgb(raw_rgba[ii+0],
raw_rgba[ii+1],
raw_rgba[ii+2]);
if(starMatrix[myRow][myCol]){ //
var closeColorID = -1;
var thisPalleteColor = d3.rgb(starColor);
}else{
if(Math.random()<pRand(myRow)){
var closeColorID = FindClosestColorIDFrom(colorPalette, thisOrigColor);
}else{
var closeColorID = FindClosestColorIDFrom(colorPalette, thisRawColor);
}
var thisPalleteColor = d3.rgb(colorPalette[closeColorID]);
}
paletteIDs.push(closeColorID)
dithered[ii+0] = thisPalleteColor.r;
dithered[ii+1] = thisPalleteColor.g;
dithered[ii+2] = thisPalleteColor.b;
dithered[ii+3] = 255;
// quant_error := oldpixel - newpixel
var quant_error = {r:(thisRawColor.r-thisPalleteColor.r),
g:(thisRawColor.g-thisPalleteColor.g),
b:(thisRawColor.b-thisPalleteColor.b)}
if ((myRow<(h-2))&(myCol<(w-2))&(myCol>(1))){
dithered = diffuseError(dithered, myRow+0, myCol+1, quant_error, 7/48); // this is so f***ing cool
dithered = diffuseError(dithered, myRow+0, myCol+2, quant_error, 5/48); //
dithered = diffuseError(dithered, myRow+1, myCol-2, quant_error, 3/48); // basically we take the error
dithered = diffuseError(dithered, myRow+1, myCol-1, quant_error, 5/48); // in how close we came
dithered = diffuseError(dithered, myRow+1, myCol+0, quant_error, 7/48); // to approximating true color
dithered = diffuseError(dithered, myRow+1, myCol+1, quant_error, 5/48); // and we add
dithered = diffuseError(dithered, myRow+1, myCol+2, quant_error, 3/48); // (a portion of) that delta
dithered = diffuseError(dithered, myRow+2, myCol-2, quant_error, 1/48); // to the nearby pixels
dithered = diffuseError(dithered, myRow+2, myCol-1, quant_error, 3/48); //
dithered = diffuseError(dithered, myRow+2, myCol+0, quant_error, 5/48); // how cool is that
dithered = diffuseError(dithered, myRow+2, myCol+1, quant_error, 3/48); //
dithered = diffuseError(dithered, myRow+2, myCol+2, quant_error, 1/48); // and it works
}
} // end of pixel by pixel FOR loop
//
for (var ii=0; ii<dithered.length; ii++){
imgData.data[ii] = dithered[ii];
}
return({rgba: imgData.data, paletteData: paletteIDs})
}