图片高斯模糊效果

为实现一些玻璃蒙版的效果,需要用到高斯算法对图片进行模糊处理,基础算法代码如下

  1 public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) {
  2 
  3         if (VERSION.SDK_INT > 20) {
  4             Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
  5 
  6             final RenderScript rs = RenderScript.create(context);
  7             final Allocation input = Allocation.createFromBitmap(rs, sentBitmap,
  8                     Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
  9             final Allocation output = Allocation.createTyped(rs, input.getType());
 10             final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
 11             script.setRadius(radius /* e.g. 3.f */);
 12             script.setInput(input);
 13             script.forEach(output);
 14             output.copyTo(bitmap);
 15             return bitmap;
 16         }
 17 
 18         Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
 19 
 20         if (radius < 1) {
 21             return (null);
 22         }
 23 
 24         int w = bitmap.getWidth();
 25         int h = bitmap.getHeight();
 26 
 27         int[] pix = new int[w * h];
 28         Log.e("pix", w + " " + h + " " + pix.length);
 29         bitmap.getPixels(pix, 0, w, 0, 0, w, h);
 30 
 31         int wm = w - 1;
 32         int hm = h - 1;
 33         int wh = w * h;
 34         int div = radius + radius + 1;
 35 
 36         int r[] = new int[wh];
 37         int g[] = new int[wh];
 38         int b[] = new int[wh];
 39         int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
 40         int vmin[] = new int[Math.max(w, h)];
 41 
 42         int divsum = (div + 1) >> 1;
 43         divsum *= divsum;
 44         int dv[] = new int[256 * divsum];
 45         for (i = 0; i < 256 * divsum; i++) {
 46             dv[i] = (i / divsum);
 47         }
 48 
 49         yw = yi = 0;
 50 
 51         int[][] stack = new int[div][3];
 52         int stackpointer;
 53         int stackstart;
 54         int[] sir;
 55         int rbs;
 56         int r1 = radius + 1;
 57         int routsum, goutsum, boutsum;
 58         int rinsum, ginsum, binsum;
 59 
 60         for (y = 0; y < h; y++) {
 61             rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
 62             for (i = -radius; i <= radius; i++) {
 63                 p = pix[yi + Math.min(wm, Math.max(i, 0))];
 64                 sir = stack[i + radius];
 65                 sir[0] = (p & 0xff0000) >> 16;
 66                 sir[1] = (p & 0x00ff00) >> 8;
 67                 sir[2] = (p & 0x0000ff);
 68                 rbs = r1 - Math.abs(i);
 69                 rsum += sir[0] * rbs;
 70                 gsum += sir[1] * rbs;
 71                 bsum += sir[2] * rbs;
 72                 if (i > 0) {
 73                     rinsum += sir[0];
 74                     ginsum += sir[1];
 75                     binsum += sir[2];
 76                 } else {
 77                     routsum += sir[0];
 78                     goutsum += sir[1];
 79                     boutsum += sir[2];
 80                 }
 81             }
 82             stackpointer = radius;
 83 
 84             for (x = 0; x < w; x++) {
 85 
 86                 r[yi] = dv[rsum];
 87                 g[yi] = dv[gsum];
 88                 b[yi] = dv[bsum];
 89 
 90                 rsum -= routsum;
 91                 gsum -= goutsum;
 92                 bsum -= boutsum;
 93 
 94                 stackstart = stackpointer - radius + div;
 95                 sir = stack[stackstart % div];
 96 
 97                 routsum -= sir[0];
 98                 goutsum -= sir[1];
 99                 boutsum -= sir[2];
100 
101                 if (y == 0) {
102                     vmin[x] = Math.min(x + radius + 1, wm);
103                 }
104                 p = pix[yw + vmin[x]];
105 
106                 sir[0] = (p & 0xff0000) >> 16;
107                 sir[1] = (p & 0x00ff00) >> 8;
108                 sir[2] = (p & 0x0000ff);
109 
110                 rinsum += sir[0];
111                 ginsum += sir[1];
112                 binsum += sir[2];
113 
114                 rsum += rinsum;
115                 gsum += ginsum;
116                 bsum += binsum;
117 
118                 stackpointer = (stackpointer + 1) % div;
119                 sir = stack[(stackpointer) % div];
120 
121                 routsum += sir[0];
122                 goutsum += sir[1];
123                 boutsum += sir[2];
124 
125                 rinsum -= sir[0];
126                 ginsum -= sir[1];
127                 binsum -= sir[2];
128 
129                 yi++;
130             }
131             yw += w;
132         }
133         for (x = 0; x < w; x++) {
134             rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
135             yp = -radius * w;
136             for (i = -radius; i <= radius; i++) {
137                 yi = Math.max(0, yp) + x;
138 
139                 sir = stack[i + radius];
140 
141                 sir[0] = r[yi];
142                 sir[1] = g[yi];
143                 sir[2] = b[yi];
144 
145                 rbs = r1 - Math.abs(i);
146 
147                 rsum += r[yi] * rbs;
148                 gsum += g[yi] * rbs;
149                 bsum += b[yi] * rbs;
150 
151                 if (i > 0) {
152                     rinsum += sir[0];
153                     ginsum += sir[1];
154                     binsum += sir[2];
155                 } else {
156                     routsum += sir[0];
157                     goutsum += sir[1];
158                     boutsum += sir[2];
159                 }
160 
161                 if (i < hm) {
162                     yp += w;
163                 }
164             }
165             yi = x;
166             stackpointer = radius;
167             for (y = 0; y < h; y++) {
168                 // Preserve alpha channel: ( 0xff000000 & pix[yi] )
169                 pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
170 
171                 rsum -= routsum;
172                 gsum -= goutsum;
173                 bsum -= boutsum;
174 
175                 stackstart = stackpointer - radius + div;
176                 sir = stack[stackstart % div];
177 
178                 routsum -= sir[0];
179                 goutsum -= sir[1];
180                 boutsum -= sir[2];
181 
182                 if (x == 0) {
183                     vmin[y] = Math.min(y + r1, hm) * w;
184                 }
185                 p = x + vmin[y];
186 
187                 sir[0] = r[p];
188                 sir[1] = g[p];
189                 sir[2] = b[p];
190 
191                 rinsum += sir[0];
192                 ginsum += sir[1];
193                 binsum += sir[2];
194 
195                 rsum += rinsum;
196                 gsum += ginsum;
197                 bsum += binsum;
198 
199                 stackpointer = (stackpointer + 1) % div;
200                 sir = stack[stackpointer];
201 
202                 routsum += sir[0];
203                 goutsum += sir[1];
204                 boutsum += sir[2];
205 
206                 rinsum -= sir[0];
207                 ginsum -= sir[1];
208                 binsum -= sir[2];
209 
210                 yi += w;
211             }
212         }
213 
214         Log.e("pix", w + " " + h + " " + pix.length);
215         bitmap.setPixels(pix, 0, w, 0, 0, w, h);
216         return (bitmap);
217     }

但是此类实现模糊效果效率是个很大的问题,所以我们需要把原图先处理一下,再进行模糊操作。

1 private static Bitmap small(Bitmap bitmap) {
2         Matrix matrix = new Matrix();
3         matrix.postScale(0.08f, 0.08f); // 长和宽放大缩小的比例
4         Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,
5                 true);
6         return resizeBmp;
7     }

在使用模糊图的地方可以再添加一些透明蒙版来实现高亮偏暗的效果。

原文地址:https://www.cnblogs.com/nick-zhang/p/3733645.html