-
Notifications
You must be signed in to change notification settings - Fork 66
/
SuperFastBlur.java
99 lines (84 loc) · 3.05 KB
/
SuperFastBlur.java
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
package at.favre.app.blurbenchmark.blur.algorithms;
import android.graphics.Bitmap;
import at.favre.app.blurbenchmark.blur.IBlur;
/**
* Super Fast Blur by Mario Klingemann<br/>
* Resource: http://incubator.quasimondo.com/processing/superfast_blur.php<br/>
* StackOverflow - Understanding super fast blur algorithm: http://stackoverflow.com/questions/21418892/understanding-super-fast-blur-algorithm<br/>
*/
public class SuperFastBlur implements IBlur {
@Override
public Bitmap blur(int radius, Bitmap original) {
int w = original.getWidth();
int h = original.getHeight();
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int r[] = new int[wh];
int g[] = new int[wh];
int b[] = new int[wh];
int rsum, gsum, bsum, x, y, i, p, p1, p2, yp, yi, yw;
int vmin[] = new int[Math.max(w, h)];
int vmax[] = new int[Math.max(w, h)];
int[] pix = new int[w * h];
original.getPixels(pix, 0, w, 0, 0, w, h);
int dv[] = new int[256 * div];
for (i = 0; i < 256 * div; i++) {
dv[i] = (i / div);
}
yw = yi = 0;
for (y = 0; y < h; y++) {
rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
rsum += (p & 0xff0000) >> 16;
gsum += (p & 0x00ff00) >> 8;
bsum += p & 0x0000ff;
}
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
vmax[x] = Math.max(x - radius, 0);
}
p1 = pix[yw + vmin[x]];
p2 = pix[yw + vmax[x]];
rsum += ((p1 & 0xff0000) - (p2 & 0xff0000)) >> 16;
gsum += ((p1 & 0x00ff00) - (p2 & 0x00ff00)) >> 8;
bsum += (p1 & 0x0000ff) - (p2 & 0x0000ff);
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
rsum += r[yi];
gsum += g[yi];
bsum += b[yi];
yp += w;
}
yi = x;
for (y = 0; y < h; y++) {
pix[yi] = 0xff000000 | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
if (x == 0) {
vmin[y] = Math.min(y + radius + 1, hm) * w;
vmax[y] = Math.max(y - radius, 0) * w;
}
p1 = x + vmin[y];
p2 = x + vmax[y];
rsum += r[p1] - r[p2];
gsum += g[p1] - g[p2];
bsum += b[p1] - b[p2];
yi += w;
}
}
original.setPixels(pix, 0, w, 0, 0, w, h);
return original;
}
}