10 | * Java Author: Mario Klingemann mario@quasimondo.com 11 | * http://incubator.quasimondo.com 12 | * created Feburary 29, 2004 13 | * Android port : Yahel Bouaziz yahel@kayenko.com 14 | * http://www.kayenko.com 15 | * ported april 5th, 2012 16 | *
17 | * This is a compromise between Gaussian HokoBlur and Box blur 18 | * It creates much better looking blurs than Box HokoBlur, but is 19 | * 7x faster than my Gaussian HokoBlur implementation. 20 | *
21 | * I called it Stack HokoBlur because this describes best how this 22 | * filter works internally: it creates a kind of moving stack 23 | * of colors whilst scanning through the image. Thereby it 24 | * just has to add one new block of color to the right side 25 | * of the stack and remove the leftmost color. The remaining 26 | * colors on the topmost layer of the stack are either added on 27 | * or reduced by one, depending on if they are on the right or 28 | * on the left side of the stack. 29 | *
30 | * If you are using this algorithm in your code please add 31 | * the following line: 32 | *
33 | * Stack HokoBlur Algorithm by Mario Klingemann mario@quasimondo.com
34 | **/
35 | final class StackBlurFilter {
36 |
37 | public static void doBlur(int[] pix, int w, int h, int radius, @Direction int direction) {
38 | if (direction == HokoBlur.HORIZONTAL) {
39 | doHorizontalBlur(pix, w, h, radius);
40 | } else if (direction == HokoBlur.VERTICAL) {
41 | doVerticalBlur(pix, w, h, radius);
42 | } else {
43 | doHorizontalBlur(pix, w, h, radius);
44 | doVerticalBlur(pix, w, h, radius);
45 | }
46 |
47 | }
48 |
49 | private static void doHorizontalBlur(int[] pix, int w, int h, int radius) {
50 | int wm = w - 1;
51 | int wh = w * h;
52 | int div = radius + radius + 1;
53 |
54 | int[] r = new int[wh];
55 | int[] g = new int[wh];
56 | int[] b = new int[wh];
57 | int rsum, gsum, bsum, x, y, i, p, yi, yw;
58 | int[] vmin = new int[Math.max(w, h)];
59 |
60 | int divsum = (div + 1) >> 1;
61 | divsum *= divsum;
62 | int[] dv = new int[256 * divsum];
63 | for (i = 0; i < 256 * divsum; i++) {
64 | dv[i] = (i / divsum);
65 | }
66 |
67 | yw = yi = 0;
68 |
69 | int[][] stack = new int[div][3];
70 | int stackpointer;
71 | int stackstart;
72 | int[] sir;
73 | int rbs;
74 | int r1 = radius + 1;
75 | int routsum, goutsum, boutsum;
76 | int rinsum, ginsum, binsum;
77 |
78 | for (y = 0; y < h; y++) {
79 | rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
80 | for (i = -radius; i <= radius; i++) {
81 | p = pix[yi + Math.min(wm, Math.max(i, 0))];
82 | sir = stack[i + radius];
83 | sir[0] = (p & 0xff0000) >> 16;
84 | sir[1] = (p & 0x00ff00) >> 8;
85 | sir[2] = (p & 0x0000ff);
86 | rbs = r1 - Math.abs(i);
87 | rsum += sir[0] * rbs;
88 | gsum += sir[1] * rbs;
89 | bsum += sir[2] * rbs;
90 | if (i > 0) {
91 | rinsum += sir[0];
92 | ginsum += sir[1];
93 | binsum += sir[2];
94 | } else {
95 | routsum += sir[0];
96 | goutsum += sir[1];
97 | boutsum += sir[2];
98 | }
99 | }
100 | stackpointer = radius;
101 |
102 | for (x = 0; x < w; x++) {
103 |
104 | r[yi] = dv[rsum];
105 | g[yi] = dv[gsum];
106 | b[yi] = dv[bsum];
107 |
108 | pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
109 |
110 | rsum -= routsum;
111 | gsum -= goutsum;
112 | bsum -= boutsum;
113 |
114 | stackstart = stackpointer - radius + div;
115 | sir = stack[stackstart % div];
116 |
117 | routsum -= sir[0];
118 | goutsum -= sir[1];
119 | boutsum -= sir[2];
120 |
121 | if (y == 0) {
122 | vmin[x] = Math.min(x + radius + 1, wm);
123 | }
124 | p = pix[yw + vmin[x]];
125 |
126 | sir[0] = (p & 0xff0000) >> 16;
127 | sir[1] = (p & 0x00ff00) >> 8;
128 | sir[2] = (p & 0x0000ff);
129 |
130 | rinsum += sir[0];
131 | ginsum += sir[1];
132 | binsum += sir[2];
133 |
134 | rsum += rinsum;
135 | gsum += ginsum;
136 | bsum += binsum;
137 |
138 | stackpointer = (stackpointer + 1) % div;
139 | sir = stack[(stackpointer) % div];
140 |
141 | routsum += sir[0];
142 | goutsum += sir[1];
143 | boutsum += sir[2];
144 |
145 | rinsum -= sir[0];
146 | ginsum -= sir[1];
147 | binsum -= sir[2];
148 |
149 | yi++;
150 | }
151 | yw += w;
152 | }
153 | }
154 |
155 | private static void doVerticalBlur(int[] pix, int w, int h, int radius) {
156 | int wm = w - 1;
157 | int hm = h - 1;
158 | int wh = w * h;
159 | int div = radius + radius + 1;
160 |
161 | int[] r = new int[wh];
162 | int[] g = new int[wh];
163 | int[] b = new int[wh];
164 | int rsum, gsum, bsum, x, y, i, p, yp, yi;
165 | int[] vmin = new int[Math.max(w, h)];
166 |
167 | int divsum = (div + 1) >> 1;
168 | divsum *= divsum;
169 | int[] dv = new int[256 * divsum];
170 | for (i = 0; i < 256 * divsum; i++) {
171 | dv[i] = (i / divsum);
172 | }
173 |
174 | int[][] stack = new int[div][3];
175 | int stackpointer;
176 | int stackstart;
177 | int[] sir;
178 | int rbs;
179 | int r1 = radius + 1;
180 | int routsum, goutsum, boutsum;
181 | int rinsum, ginsum, binsum;
182 |
183 | for (i = 0; i < wh; i++) {
184 | r[i] = (pix[i] & 0xff0000) >> 16;
185 | g[i] = (pix[i] & 0x00ff00) >> 8;
186 | b[i] = (pix[i] & 0x0000ff);
187 | }
188 |
189 | for (x = 0; x < w; x++) {
190 | rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
191 | yp = -radius * w;
192 | for (i = -radius; i <= radius; i++) {
193 | yi = Math.max(0, yp) + x;
194 |
195 | sir = stack[i + radius];
196 |
197 | sir[0] = r[yi];
198 | sir[1] = g[yi];
199 | sir[2] = b[yi];
200 |
201 | rbs = r1 - Math.abs(i);
202 |
203 | rsum += r[yi] * rbs;
204 | gsum += g[yi] * rbs;
205 | bsum += b[yi] * rbs;
206 |
207 | if (i > 0) {
208 | rinsum += sir[0];
209 | ginsum += sir[1];
210 | binsum += sir[2];
211 | } else {
212 | routsum += sir[0];
213 | goutsum += sir[1];
214 | boutsum += sir[2];
215 | }
216 |
217 | if (i < hm) {
218 | yp += w;
219 | }
220 | }
221 | yi = x;
222 | stackpointer = radius;
223 | for (y = 0; y < h; y++) {
224 | // Preserve alpha channel: ( 0xff000000 & pix[yi] )
225 | pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
226 |
227 | rsum -= routsum;
228 | gsum -= goutsum;
229 | bsum -= boutsum;
230 |
231 | stackstart = stackpointer - radius + div;
232 | sir = stack[stackstart % div];
233 |
234 | routsum -= sir[0];
235 | goutsum -= sir[1];
236 | boutsum -= sir[2];
237 |
238 | if (x == 0) {
239 | vmin[y] = Math.min(y + r1, hm) * w;
240 | }
241 | p = x + vmin[y];
242 |
243 | sir[0] = r[p];
244 | sir[1] = g[p];
245 | sir[2] = b[p];
246 |
247 | rinsum += sir[0];
248 | ginsum += sir[1];
249 | binsum += sir[2];
250 |
251 | rsum += rinsum;
252 | gsum += ginsum;
253 | bsum += binsum;
254 |
255 | stackpointer = (stackpointer + 1) % div;
256 | sir = stack[stackpointer];
257 |
258 | routsum += sir[0];
259 | goutsum += sir[1];
260 | boutsum += sir[2];
261 |
262 | rinsum -= sir[0];
263 | ginsum -= sir[1];
264 | binsum -= sir[2];
265 |
266 | yi += w;
267 | }
268 | }
269 | }
270 | }
271 |
272 |
--------------------------------------------------------------------------------
/hoko-blur/src/main/java/com/hoko/blur/opengl/BitmapTexture.java:
--------------------------------------------------------------------------------
1 | package com.hoko.blur.opengl;
2 |
3 | import android.graphics.Bitmap;
4 | import android.opengl.GLES20;
5 | import android.opengl.GLUtils;
6 |
7 | import java.lang.ref.WeakReference;
8 |
9 | /**
10 | * Created by yuxfzju on 2017/1/24.
11 | */
12 |
13 | class BitmapTexture extends Texture {
14 |
15 | private final WeakReference