glur 1.0.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +11 -3
- package/index.js +179 -151
- package/mono16.js +96 -67
- package/package.json +6 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
1.1.2 / 2016-05-05
|
|
2
|
+
------------------
|
|
3
|
+
|
|
4
|
+
- Fixed typo in RGBA blur math equations (regression from 1.1.0),
|
|
5
|
+
thanks to @tonykwok.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
1.1.1 / 2015-11-10
|
|
9
|
+
------------------
|
|
10
|
+
|
|
11
|
+
- Fixed line buffer size for mono blur when vertical images used.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
1.1.0 / 2015-11-05
|
|
15
|
+
------------------
|
|
16
|
+
|
|
17
|
+
- Changed interpolation fn to one from Intel's whitepaper.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
1.0.1 / 2015-11-04
|
|
21
|
+
------------------
|
|
22
|
+
|
|
23
|
+
- Maintenance: general cleanup, demo improvements.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
1.0.0 / 2015-11-02
|
|
27
|
+
------------------
|
|
28
|
+
|
|
29
|
+
- First release.
|
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
glur
|
|
2
2
|
====
|
|
3
3
|
|
|
4
|
+
[](https://travis-ci.org/nodeca/glur)
|
|
4
5
|
[](https://www.npmjs.org/package/glur)
|
|
5
6
|
|
|
6
7
|
> Fast Gaussian Blur in pure JavaScript, via IIR filer. Speed does not depend on
|
|
7
8
|
> blur radius.
|
|
8
9
|
|
|
9
|
-
__[
|
|
10
|
+
__[demo 1](http://nodeca.github.io/glur/demo)__,
|
|
11
|
+
__[demo 2](http://nodeca.github.io/glur/demo/mono16.html)__.
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
Install
|
|
@@ -32,13 +34,19 @@ input data is grayscale Uint16Array. Can be useful to calculate unsharp mask via
|
|
|
32
34
|
brightness/ligthness channel.
|
|
33
35
|
|
|
34
36
|
|
|
37
|
+
Authors
|
|
38
|
+
-------
|
|
39
|
+
|
|
40
|
+
- Andrey Tupitsin [@anrd83](https://github.com/andr83)
|
|
41
|
+
- Alexander Rodin [@a-rodin](https://github.com/a-rodin)
|
|
42
|
+
- Vitaly Puzrin [@puzrin](https://github.com/puzrin)
|
|
43
|
+
|
|
44
|
+
|
|
35
45
|
References
|
|
36
46
|
----------
|
|
37
47
|
|
|
38
48
|
- [IIR Gaussian Blur Filter Implementation using Intel® Advanced Vector Extensions](https://software.intel.com/en-us/articles/iir-gaussian-blur-filter-implementation-using-intel-advanced-vector-extensions) -
|
|
39
49
|
very good article with technical details for programmers.
|
|
40
|
-
- [Быстрое размытие по Гауссу](http://habrahabr.ru/post/151157/) (RUS) - alternative
|
|
41
|
-
with more simple aproximation function (we use it here in glur).
|
|
42
50
|
|
|
43
51
|
|
|
44
52
|
Licence
|
package/index.js
CHANGED
|
@@ -1,168 +1,196 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// Calculate Gaussian blur of an image using IIR filter
|
|
2
|
+
// The method is taken from Intel's white paper and code example attached to it:
|
|
3
|
+
// https://software.intel.com/en-us/articles/iir-gaussian-blur-filter
|
|
4
|
+
// -implementation-using-intel-advanced-vector-extensions
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
var coef_W = sigma_inv_4 * (sigma * (sigma * (sigma * 1.3642870 + 0.0088755) - 0.3255340) + 0.3016210);
|
|
7
|
-
var coef_B = sigma_inv_4 * (sigma * (sigma * (sigma * 1.2397166 - 0.0001644) - 0.6363580) - 0.0536068);
|
|
6
|
+
var a0, a1, a2, a3, b1, b2, left_corner, right_corner;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var z2 = Math.exp(coef_B);
|
|
14
|
-
|
|
15
|
-
var z0_abs_2 = z0_abs * z0_abs;
|
|
16
|
-
|
|
17
|
-
var a2 = 1.0 / (z2 * z0_abs_2),
|
|
18
|
-
a0 = (z0_abs_2 + 2 * z0_real * z2) * a2,
|
|
19
|
-
a1 = -(2 * z0_real + z2) * a2,
|
|
20
|
-
b0 = 1.0 - (a0 + a1 + a2);
|
|
21
|
-
|
|
22
|
-
return new Float32Array([ b0, a0, a1, a2 ]);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var convolveRGBA = function (src, out, tmp, coeff, width, height) {
|
|
27
|
-
var x, y, rgba, r, g, b, a, out_index, y_offset, x_offset;
|
|
28
|
-
var r0, g0, b0, a0, r1, g1, b1, a1, r2, g2, b2, a2;
|
|
29
|
-
|
|
30
|
-
var coeff_b0 = coeff[0];
|
|
31
|
-
var coeff_a0 = coeff[1];
|
|
32
|
-
var coeff_a1 = coeff[2];
|
|
33
|
-
var coeff_a2 = coeff[3];
|
|
34
|
-
|
|
35
|
-
// console.time('convolve');
|
|
36
|
-
for (y = 0; y < height; y++) {
|
|
37
|
-
y_offset = y * width;
|
|
38
|
-
|
|
39
|
-
rgba = src[y_offset];
|
|
40
|
-
|
|
41
|
-
r = rgba & 0xff;
|
|
42
|
-
g = (rgba >> 8) & 0xff;
|
|
43
|
-
b = (rgba >> 16) & 0xff;
|
|
44
|
-
a = (rgba >> 24) & 0xff;
|
|
45
|
-
|
|
46
|
-
r0 = r;
|
|
47
|
-
g0 = g;
|
|
48
|
-
b0 = b;
|
|
49
|
-
a0 = a;
|
|
50
|
-
|
|
51
|
-
r1 = r0;
|
|
52
|
-
g1 = g0;
|
|
53
|
-
b1 = b0;
|
|
54
|
-
a1 = a0;
|
|
55
|
-
|
|
56
|
-
r2 = r1;
|
|
57
|
-
g2 = g1;
|
|
58
|
-
b2 = b1;
|
|
59
|
-
a2 = a1;
|
|
60
|
-
|
|
61
|
-
x_offset = 0;
|
|
62
|
-
|
|
63
|
-
for (x = 0; x < width; x++) {
|
|
64
|
-
rgba = src[y_offset + x];
|
|
65
|
-
|
|
66
|
-
r = rgba & 0xff;
|
|
67
|
-
g = (rgba >> 8) & 0xff;
|
|
68
|
-
b = (rgba >> 16) & 0xff;
|
|
69
|
-
a = (rgba >> 24) & 0xff;
|
|
70
|
-
|
|
71
|
-
r = coeff_b0 * r + (coeff_a0 * r0 + coeff_a1 * r1 + coeff_a2 * r2);
|
|
72
|
-
g = coeff_b0 * g + (coeff_a0 * g0 + coeff_a1 * g1 + coeff_a2 * g2);
|
|
73
|
-
b = coeff_b0 * b + (coeff_a0 * b0 + coeff_a1 * b1 + coeff_a2 * b2);
|
|
74
|
-
a = coeff_b0 * a + (coeff_a0 * a0 + coeff_a1 * a1 + coeff_a2 * a2);
|
|
75
|
-
|
|
76
|
-
r2 = r1;
|
|
77
|
-
g2 = g1;
|
|
78
|
-
b2 = b1;
|
|
79
|
-
a2 = a1;
|
|
80
|
-
|
|
81
|
-
r1 = r0;
|
|
82
|
-
g1 = g0;
|
|
83
|
-
b1 = b0;
|
|
84
|
-
a1 = a0;
|
|
85
|
-
|
|
86
|
-
r0 = r;
|
|
87
|
-
g0 = g;
|
|
88
|
-
b0 = b;
|
|
89
|
-
a0 = a;
|
|
90
|
-
|
|
91
|
-
tmp[x_offset] = r;
|
|
92
|
-
tmp[x_offset + 1] = g;
|
|
93
|
-
tmp[x_offset + 2] = b;
|
|
94
|
-
tmp[x_offset + 3] = a;
|
|
8
|
+
function gaussCoef(sigma) {
|
|
9
|
+
if (sigma < 0.5) {
|
|
10
|
+
sigma = 0.5;
|
|
11
|
+
}
|
|
95
12
|
|
|
96
|
-
|
|
13
|
+
var a = Math.exp(0.726 * 0.726) / sigma,
|
|
14
|
+
g1 = Math.exp(-a),
|
|
15
|
+
g2 = Math.exp(-2 * a),
|
|
16
|
+
k = (1 - g1) * (1 - g1) / (1 + 2 * a * g1 - g2);
|
|
17
|
+
|
|
18
|
+
a0 = k;
|
|
19
|
+
a1 = k * (a - 1) * g1;
|
|
20
|
+
a2 = k * (a + 1) * g1;
|
|
21
|
+
a3 = -k * g2;
|
|
22
|
+
b1 = 2 * g1;
|
|
23
|
+
b2 = -g2;
|
|
24
|
+
left_corner = (a0 + a1) / (1 - b1 - b2);
|
|
25
|
+
right_corner = (a2 + a3) / (1 - b1 - b2);
|
|
26
|
+
|
|
27
|
+
// Attempt to force type to FP32.
|
|
28
|
+
return new Float32Array([ a0, a1, a2, a3, b1, b2, left_corner, right_corner ]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function convolveRGBA(src, out, line, coeff, width, height) {
|
|
32
|
+
// takes src image and writes the blurred and transposed result into out
|
|
33
|
+
|
|
34
|
+
var rgba;
|
|
35
|
+
var prev_src_r, prev_src_g, prev_src_b, prev_src_a;
|
|
36
|
+
var curr_src_r, curr_src_g, curr_src_b, curr_src_a;
|
|
37
|
+
var curr_out_r, curr_out_g, curr_out_b, curr_out_a;
|
|
38
|
+
var prev_out_r, prev_out_g, prev_out_b, prev_out_a;
|
|
39
|
+
var prev_prev_out_r, prev_prev_out_g, prev_prev_out_b, prev_prev_out_a;
|
|
40
|
+
|
|
41
|
+
var src_index, out_index, line_index;
|
|
42
|
+
var i, j;
|
|
43
|
+
var coeff_a0, coeff_a1, coeff_b1, coeff_b2;
|
|
44
|
+
|
|
45
|
+
for (i = 0; i < height; i++) {
|
|
46
|
+
src_index = i * width;
|
|
47
|
+
out_index = i;
|
|
48
|
+
line_index = 0;
|
|
49
|
+
|
|
50
|
+
// left to right
|
|
51
|
+
rgba = src[src_index];
|
|
52
|
+
|
|
53
|
+
prev_src_r = rgba & 0xff;
|
|
54
|
+
prev_src_g = (rgba >> 8) & 0xff;
|
|
55
|
+
prev_src_b = (rgba >> 16) & 0xff;
|
|
56
|
+
prev_src_a = (rgba >> 24) & 0xff;
|
|
57
|
+
|
|
58
|
+
prev_prev_out_r = prev_src_r * coeff[6];
|
|
59
|
+
prev_prev_out_g = prev_src_g * coeff[6];
|
|
60
|
+
prev_prev_out_b = prev_src_b * coeff[6];
|
|
61
|
+
prev_prev_out_a = prev_src_a * coeff[6];
|
|
62
|
+
|
|
63
|
+
prev_out_r = prev_prev_out_r;
|
|
64
|
+
prev_out_g = prev_prev_out_g;
|
|
65
|
+
prev_out_b = prev_prev_out_b;
|
|
66
|
+
prev_out_a = prev_prev_out_a;
|
|
67
|
+
|
|
68
|
+
coeff_a0 = coeff[0];
|
|
69
|
+
coeff_a1 = coeff[1];
|
|
70
|
+
coeff_b1 = coeff[4];
|
|
71
|
+
coeff_b2 = coeff[5];
|
|
72
|
+
|
|
73
|
+
for (j = 0; j < width; j++) {
|
|
74
|
+
rgba = src[src_index];
|
|
75
|
+
curr_src_r = rgba & 0xff;
|
|
76
|
+
curr_src_g = (rgba >> 8) & 0xff;
|
|
77
|
+
curr_src_b = (rgba >> 16) & 0xff;
|
|
78
|
+
curr_src_a = (rgba >> 24) & 0xff;
|
|
79
|
+
|
|
80
|
+
curr_out_r = curr_src_r * coeff_a0 + prev_src_r * coeff_a1 + prev_out_r * coeff_b1 + prev_prev_out_r * coeff_b2;
|
|
81
|
+
curr_out_g = curr_src_g * coeff_a0 + prev_src_g * coeff_a1 + prev_out_g * coeff_b1 + prev_prev_out_g * coeff_b2;
|
|
82
|
+
curr_out_b = curr_src_b * coeff_a0 + prev_src_b * coeff_a1 + prev_out_b * coeff_b1 + prev_prev_out_b * coeff_b2;
|
|
83
|
+
curr_out_a = curr_src_a * coeff_a0 + prev_src_a * coeff_a1 + prev_out_a * coeff_b1 + prev_prev_out_a * coeff_b2;
|
|
84
|
+
|
|
85
|
+
prev_prev_out_r = prev_out_r;
|
|
86
|
+
prev_prev_out_g = prev_out_g;
|
|
87
|
+
prev_prev_out_b = prev_out_b;
|
|
88
|
+
prev_prev_out_a = prev_out_a;
|
|
89
|
+
|
|
90
|
+
prev_out_r = curr_out_r;
|
|
91
|
+
prev_out_g = curr_out_g;
|
|
92
|
+
prev_out_b = curr_out_b;
|
|
93
|
+
prev_out_a = curr_out_a;
|
|
94
|
+
|
|
95
|
+
prev_src_r = curr_src_r;
|
|
96
|
+
prev_src_g = curr_src_g;
|
|
97
|
+
prev_src_b = curr_src_b;
|
|
98
|
+
prev_src_a = curr_src_a;
|
|
99
|
+
|
|
100
|
+
line[line_index] = prev_out_r;
|
|
101
|
+
line[line_index + 1] = prev_out_g;
|
|
102
|
+
line[line_index + 2] = prev_out_b;
|
|
103
|
+
line[line_index + 3] = prev_out_a;
|
|
104
|
+
line_index += 4;
|
|
105
|
+
src_index++;
|
|
97
106
|
}
|
|
98
107
|
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
108
|
+
src_index--;
|
|
109
|
+
line_index -= 4;
|
|
110
|
+
out_index += height * (width - 1);
|
|
111
|
+
|
|
112
|
+
// right to left
|
|
113
|
+
rgba = src[src_index];
|
|
114
|
+
|
|
115
|
+
prev_src_r = rgba & 0xff;
|
|
116
|
+
prev_src_g = (rgba >> 8) & 0xff;
|
|
117
|
+
prev_src_b = (rgba >> 16) & 0xff;
|
|
118
|
+
prev_src_a = (rgba >> 24) & 0xff;
|
|
119
|
+
|
|
120
|
+
prev_prev_out_r = prev_src_r * coeff[7];
|
|
121
|
+
prev_prev_out_g = prev_src_g * coeff[7];
|
|
122
|
+
prev_prev_out_b = prev_src_b * coeff[7];
|
|
123
|
+
prev_prev_out_a = prev_src_a * coeff[7];
|
|
124
|
+
|
|
125
|
+
prev_out_r = prev_prev_out_r;
|
|
126
|
+
prev_out_g = prev_prev_out_g;
|
|
127
|
+
prev_out_b = prev_prev_out_b;
|
|
128
|
+
prev_out_a = prev_prev_out_a;
|
|
129
|
+
|
|
130
|
+
curr_src_r = prev_src_r;
|
|
131
|
+
curr_src_g = prev_src_g;
|
|
132
|
+
curr_src_b = prev_src_b;
|
|
133
|
+
curr_src_a = prev_src_a;
|
|
134
|
+
|
|
135
|
+
coeff_a0 = coeff[2];
|
|
136
|
+
coeff_a1 = coeff[3];
|
|
137
|
+
|
|
138
|
+
for (j = width - 1; j >= 0; j--) {
|
|
139
|
+
curr_out_r = curr_src_r * coeff_a0 + prev_src_r * coeff_a1 + prev_out_r * coeff_b1 + prev_prev_out_r * coeff_b2;
|
|
140
|
+
curr_out_g = curr_src_g * coeff_a0 + prev_src_g * coeff_a1 + prev_out_g * coeff_b1 + prev_prev_out_g * coeff_b2;
|
|
141
|
+
curr_out_b = curr_src_b * coeff_a0 + prev_src_b * coeff_a1 + prev_out_b * coeff_b1 + prev_prev_out_b * coeff_b2;
|
|
142
|
+
curr_out_a = curr_src_a * coeff_a0 + prev_src_a * coeff_a1 + prev_out_a * coeff_b1 + prev_prev_out_a * coeff_b2;
|
|
143
|
+
|
|
144
|
+
prev_prev_out_r = prev_out_r;
|
|
145
|
+
prev_prev_out_g = prev_out_g;
|
|
146
|
+
prev_prev_out_b = prev_out_b;
|
|
147
|
+
prev_prev_out_a = prev_out_a;
|
|
148
|
+
|
|
149
|
+
prev_out_r = curr_out_r;
|
|
150
|
+
prev_out_g = curr_out_g;
|
|
151
|
+
prev_out_b = curr_out_b;
|
|
152
|
+
prev_out_a = curr_out_a;
|
|
153
|
+
|
|
154
|
+
prev_src_r = curr_src_r;
|
|
155
|
+
prev_src_g = curr_src_g;
|
|
156
|
+
prev_src_b = curr_src_b;
|
|
157
|
+
prev_src_a = curr_src_a;
|
|
158
|
+
|
|
159
|
+
rgba = src[src_index];
|
|
160
|
+
curr_src_r = rgba & 0xff;
|
|
161
|
+
curr_src_g = (rgba >> 8) & 0xff;
|
|
162
|
+
curr_src_b = (rgba >> 16) & 0xff;
|
|
163
|
+
curr_src_a = (rgba >> 24) & 0xff;
|
|
164
|
+
|
|
165
|
+
rgba = ((line[line_index] + prev_out_r) << 0) +
|
|
166
|
+
((line[line_index + 1] + prev_out_g) << 8) +
|
|
167
|
+
((line[line_index + 2] + prev_out_b) << 16) +
|
|
168
|
+
((line[line_index + 3] + prev_out_a) << 24);
|
|
169
|
+
|
|
170
|
+
out[out_index] = rgba;
|
|
171
|
+
|
|
172
|
+
src_index--;
|
|
173
|
+
line_index -= 4;
|
|
149
174
|
out_index -= height;
|
|
150
|
-
out[out_index] = (a << 24) | (b << 16) | (g << 8) | r;
|
|
151
175
|
}
|
|
152
176
|
}
|
|
153
|
-
|
|
154
|
-
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
function blurRGBA(src, width, height, radius) {
|
|
181
|
+
// Quick exit on zero radius
|
|
182
|
+
if (!radius) { return; }
|
|
155
183
|
|
|
184
|
+
// Unify input data type, to keep convolver calls isomorphic
|
|
185
|
+
var src32 = new Uint32Array(src.buffer);
|
|
156
186
|
|
|
157
|
-
var
|
|
158
|
-
|
|
159
|
-
out = new Uint32Array(width * height),
|
|
160
|
-
tmp_line = new Float32Array(width * 4);
|
|
187
|
+
var out = new Uint32Array(src32.length),
|
|
188
|
+
tmp_line = new Float32Array(Math.max(width, height) * 4);
|
|
161
189
|
|
|
162
190
|
var coeff = gaussCoef(radius);
|
|
163
191
|
|
|
164
192
|
convolveRGBA(src32, out, tmp_line, coeff, width, height, radius);
|
|
165
193
|
convolveRGBA(out, src32, tmp_line, coeff, height, width, radius);
|
|
166
|
-
}
|
|
194
|
+
}
|
|
167
195
|
|
|
168
196
|
module.exports = blurRGBA;
|
package/mono16.js
CHANGED
|
@@ -1,90 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// Calculate Gaussian blur of an image using IIR filter
|
|
2
|
+
// The method is taken from Intel's white paper and code example attached to it:
|
|
3
|
+
// https://software.intel.com/en-us/articles/iir-gaussian-blur-filter
|
|
4
|
+
// -implementation-using-intel-advanced-vector-extensions
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
var coef_W = sigma_inv_4 * (sigma * (sigma * (sigma * 1.3642870 + 0.0088755) - 0.3255340) + 0.3016210);
|
|
7
|
-
var coef_B = sigma_inv_4 * (sigma * (sigma * (sigma * 1.2397166 - 0.0001644) - 0.6363580) - 0.0536068);
|
|
6
|
+
var a0, a1, a2, a3, b1, b2, left_corner, right_corner;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var z2 = Math.exp(coef_B);
|
|
14
|
-
|
|
15
|
-
var z0_abs_2 = z0_abs * z0_abs;
|
|
16
|
-
|
|
17
|
-
var a2 = 1.0 / (z2 * z0_abs_2),
|
|
18
|
-
a0 = (z0_abs_2 + 2 * z0_real * z2) * a2,
|
|
19
|
-
a1 = -(2 * z0_real + z2) * a2,
|
|
20
|
-
b0 = 1.0 - (a0 + a1 + a2);
|
|
21
|
-
|
|
22
|
-
return new Float32Array([ b0, a0, a1, a2 ]);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var convolveMono16 = function (src, out, tmp, coeff, width, height) {
|
|
27
|
-
var x, y, out_index, y_offset, x_offset;
|
|
28
|
-
var v, v0, v1, v2;
|
|
29
|
-
|
|
30
|
-
var coeff_b0 = coeff[0];
|
|
31
|
-
var coeff_a0 = coeff[1];
|
|
32
|
-
var coeff_a1 = coeff[2];
|
|
33
|
-
var coeff_a2 = coeff[3];
|
|
34
|
-
|
|
35
|
-
for (y = 0; y < height; y++) {
|
|
36
|
-
y_offset = y * width;
|
|
37
|
-
|
|
38
|
-
v = src[y_offset];
|
|
39
|
-
v0 = v;
|
|
40
|
-
v1 = v0;
|
|
41
|
-
v2 = v1;
|
|
42
|
-
|
|
43
|
-
x_offset = 0;
|
|
8
|
+
function gaussCoef(sigma) {
|
|
9
|
+
if (sigma < 0.5) {
|
|
10
|
+
sigma = 0.5;
|
|
11
|
+
}
|
|
44
12
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
13
|
+
var a = Math.exp(0.726 * 0.726) / sigma,
|
|
14
|
+
g1 = Math.exp(-a),
|
|
15
|
+
g2 = Math.exp(-2 * a),
|
|
16
|
+
k = (1 - g1) * (1 - g1) / (1 + 2 * a * g1 - g2);
|
|
17
|
+
|
|
18
|
+
a0 = k;
|
|
19
|
+
a1 = k * (a - 1) * g1;
|
|
20
|
+
a2 = k * (a + 1) * g1;
|
|
21
|
+
a3 = -k * g2;
|
|
22
|
+
b1 = 2 * g1;
|
|
23
|
+
b2 = -g2;
|
|
24
|
+
left_corner = (a0 + a1) / (1 - b1 - b2);
|
|
25
|
+
right_corner = (a2 + a3) / (1 - b1 - b2);
|
|
26
|
+
|
|
27
|
+
// Attempt to force type to FP32.
|
|
28
|
+
return new Float32Array([ a0, a1, a2, a3, b1, b2, left_corner, right_corner ]);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function convolveMono16(src, out, line, coeff, width, height) {
|
|
32
|
+
// takes src image and writes the blurred and transposed result into out
|
|
33
|
+
|
|
34
|
+
var prev_src, curr_src, curr_out, prev_out, prev_prev_out;
|
|
35
|
+
var src_index, out_index, line_index;
|
|
36
|
+
var i, j;
|
|
37
|
+
var coeff_a0, coeff_a1, coeff_b1, coeff_b2;
|
|
38
|
+
|
|
39
|
+
for (i = 0; i < height; i++) {
|
|
40
|
+
src_index = i * width;
|
|
41
|
+
out_index = i;
|
|
42
|
+
line_index = 0;
|
|
43
|
+
|
|
44
|
+
// left to right
|
|
45
|
+
prev_src = src[src_index];
|
|
46
|
+
prev_prev_out = prev_src * coeff[6];
|
|
47
|
+
prev_out = prev_prev_out;
|
|
48
|
+
|
|
49
|
+
coeff_a0 = coeff[0];
|
|
50
|
+
coeff_a1 = coeff[1];
|
|
51
|
+
coeff_b1 = coeff[4];
|
|
52
|
+
coeff_b2 = coeff[5];
|
|
53
|
+
|
|
54
|
+
for (j = 0; j < width; j++) {
|
|
55
|
+
curr_src = src[src_index];
|
|
56
|
+
|
|
57
|
+
curr_out = curr_src * coeff_a0 +
|
|
58
|
+
prev_src * coeff_a1 +
|
|
59
|
+
prev_out * coeff_b1 +
|
|
60
|
+
prev_prev_out * coeff_b2;
|
|
61
|
+
|
|
62
|
+
prev_prev_out = prev_out;
|
|
63
|
+
prev_out = curr_out;
|
|
64
|
+
prev_src = curr_src;
|
|
65
|
+
|
|
66
|
+
line[line_index] = prev_out;
|
|
67
|
+
line_index++;
|
|
68
|
+
src_index++;
|
|
69
|
+
}
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
src_index--;
|
|
72
|
+
line_index--;
|
|
73
|
+
out_index += height * (width - 1);
|
|
52
74
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
75
|
+
// right to left
|
|
76
|
+
prev_src = src[src_index];
|
|
77
|
+
prev_prev_out = prev_src * coeff[7];
|
|
78
|
+
prev_out = prev_prev_out;
|
|
79
|
+
curr_src = prev_src;
|
|
56
80
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
v2 = v1;
|
|
81
|
+
coeff_a0 = coeff[2];
|
|
82
|
+
coeff_a1 = coeff[3];
|
|
60
83
|
|
|
61
|
-
|
|
84
|
+
for (j = width - 1; j >= 0; j--) {
|
|
85
|
+
curr_out = curr_src * coeff_a0 +
|
|
86
|
+
prev_src * coeff_a1 +
|
|
87
|
+
prev_out * coeff_b1 +
|
|
88
|
+
prev_prev_out * coeff_b2;
|
|
62
89
|
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
prev_prev_out = prev_out;
|
|
91
|
+
prev_out = curr_out;
|
|
65
92
|
|
|
66
|
-
|
|
67
|
-
|
|
93
|
+
prev_src = curr_src;
|
|
94
|
+
curr_src = src[src_index];
|
|
68
95
|
|
|
69
|
-
|
|
70
|
-
v1 = v0;
|
|
71
|
-
v0 = v;
|
|
96
|
+
out[out_index] = line[line_index] + prev_out;
|
|
72
97
|
|
|
98
|
+
src_index--;
|
|
99
|
+
line_index--;
|
|
73
100
|
out_index -= height;
|
|
74
|
-
out[out_index] = v;
|
|
75
101
|
}
|
|
76
102
|
}
|
|
77
|
-
}
|
|
103
|
+
}
|
|
104
|
+
|
|
78
105
|
|
|
106
|
+
function blurMono16(src, width, height, radius) {
|
|
107
|
+
// Quick exit on zero radius
|
|
108
|
+
if (!radius) { return; }
|
|
79
109
|
|
|
80
|
-
var
|
|
81
|
-
|
|
82
|
-
tmp_line = new Float32Array(width);
|
|
110
|
+
var out = new Uint16Array(src.length),
|
|
111
|
+
tmp_line = new Float32Array(Math.max(width, height));
|
|
83
112
|
|
|
84
113
|
var coeff = gaussCoef(radius);
|
|
85
114
|
|
|
86
115
|
convolveMono16(src, out, tmp_line, coeff, width, height, radius);
|
|
87
116
|
convolveMono16(out, src, tmp_line, coeff, height, width, radius);
|
|
88
|
-
}
|
|
117
|
+
}
|
|
89
118
|
|
|
90
119
|
module.exports = blurMono16;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glur",
|
|
3
3
|
"description": "Fast Gaussian Blur in pure JavaScript, via IIR filer. Speed does not depend on blur radius.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blur",
|
|
7
7
|
"gaussian"
|
|
@@ -13,8 +13,12 @@
|
|
|
13
13
|
"index.js",
|
|
14
14
|
"mono16.js"
|
|
15
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "./node_modules/.bin/eslint ."
|
|
18
|
+
},
|
|
16
19
|
"devDependencies": {
|
|
17
20
|
"ansi": "0.3.x",
|
|
18
|
-
"benchmark": "1.0.x"
|
|
21
|
+
"benchmark": "1.0.x",
|
|
22
|
+
"eslint": "^1.8.0"
|
|
19
23
|
}
|
|
20
24
|
}
|