-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdither.js
More file actions
126 lines (115 loc) · 2.89 KB
/
dither.js
File metadata and controls
126 lines (115 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//Dithering
var dataFn;
function matIndex(dim, x, y){
return ((y%2==0?x%dim:dim-x%dim)+notFactor(dim)*y)%dim;
}
//finds the number which is not a factor which is closest to 1/2 the number
function notFactor(n){
var half = Math.floor(n/2);
for(var i=0; i<half; i++){
if(n%(half-i)){
return half-i;
}
if(n%(half+i)){
return half+i;
}
}
return 1;
}
function getColors(image, numColors){
var means = [];
var groups = [];
for(var i=0; i<numColors; i++){
groups.push([]);
means.push([]);
for(var j=0; j<3; j++){
means[i].push(image.data[Math.floor(i*image.data.length/numColors)+j]);
}
}
var pp = 0;
do{
prevMeans = means.slice(0,means.length);
for(var i=0; i<groups.length; i++){
groups[i] = [];
}
for(var i=0; i<image.data.length; i+=4){
var curPxl = image.data.slice(i,i+3);
groups[closest(curPxl, means)].push(curPxl);
}
for(var i=0; i<means.length; i++){
if(groups[i].length !== 0){
means[i] = [0, 0, 0];
for(var j=0; j<groups[i].length; j++){
for(var k=0; k<groups[i][j].length; k++){
means[i][k] += groups[i][j][k];
}
}
for(var j=0; j<3; j++){
if(groups[i].length !== 0){
means[i][j] = Math.floor(means[i][j]/groups[i].length);
}
}
}
}
pp++;
}while(totalDif(prevMeans, means) > 1 && pp<128);
console.log("PP");
console.log(pp);
console.log("Dif");
console.log(totalDif(prevMeans, means));
console.log("Color");
console.log(means);
return means;
}
function totalDif(arr1, arr2){
var total = 0;
for(var i=0; i<arr1.length; i++){
total += dif(arr1[i], arr2[i]);
}
return total
}
function dif(arr1, arr2){
var d = 0;
for(var i=0; i<arr1.length; i++){
d += Math.pow(arr1[i] - arr2[i], 2);
}
return Math.pow(d,1/2);
}
function closest(pixel, colors){
var min = 256*3;
var ind = 0;
for(var i=0; i<colors.length;i++){
var d = dif(pixel, colors[i]);
if(d < min){ind = i; min = d;}
}
return ind;
}
var avg = function(array1, array2, weight2){
if(weight2 === undefined){weight2 = 1;}
return array1.map(function (num, idx) {
return (num + weight2*array2[idx])/(1+weight2);
});
}
//returns an imageProcess
function dither(colors, matDim){
return function(dat){
var buffer8 = new Uint8ClampedArray(dat.data.length);
for(var i=0; i<dat.data.length; i+=4){
var x = (i/4)%dat.width;
var y = Math.floor(i/(4*dat.width));
var g = closest(
avg(
dat.data.slice(i,i+3),
colors[matIndex(matDim, x, y)%colors.length],
1/(colors.length*(1+matIndex(matDim+1, x, y)/(matDim+1+1)))
),
colors);
//reversing gamma correction
buffer8[i] = colors[g][0];
buffer8[i+1] = colors[g][1];
buffer8[i+2] = colors[g][2];
buffer8[i+3] = 255;
}
return new ImageData(buffer8, dat.width, dat.height);
};
}