博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android开发——深度毛玻璃效果
阅读量:6039 次
发布时间:2019-06-20

本文共 6555 字,大约阅读时间需要 21 分钟。

hot3.png

ImageView在开发中使用毛玻璃效果时,一般是以Dialog的形式弹出的,如果跳转到另一个Activity显示的话,在速度上明显不如Dialog.我遇到的情况是需要先把原先的界面进行截屏,然后将截屏的界面进行毛玻璃深度处理。

流程如下:

1.截取原先的界面生成Bitmap

 
  1. View view = activity.getWindow().getDecorView();
  2. view.setDrawingCacheEnabled(true);
  3. view.buildDrawingCache();
  4. Bitmap screenshotBitmap = view.getDrawingCache();

2.将图片进行质量压缩

 
  1. screenshotBitmap = compressImage(screenshotBitmap);// 将图片进行压缩
 
  1. /**
  2. * 将图片的进行质量压缩
  3. */
  4. private static Bitmap compressImage(Bitmap image) {
  5.  
  6. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  7. image.compress(Bitmap.CompressFormat.JPEG, 30, baos);// 质量压缩方法,30是压缩率表示压缩70%,把压缩后的数据存放到baos中
  8. int options = 100;
  9. while (baos.toByteArray().length / 1024 > 200) { // 循环判断如果压缩后图片是否大于200kb,大于继续压缩
  10. baos.reset();// 重置baos即清空baos
  11. options -= 10;// 每次都减少10
  12. image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
  13.  
  14. }
  15. ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
  16. return BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
  17. }

3.去掉状态栏,

 
  1. // 获取状态栏高度
  2. Rect frame = new Rect();
  3. activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  4. int statusBarHeight = frame.top;
  5. // 获取屏幕长和高
  6. int width = activity.getWindowManager().getDefaultDisplay().getWidth();
  7. int height = activity.getWindowManager().getDefaultDisplay()
  8. .getHeight();
  9. try {
  10. // 去掉标题栏
  11. screenshotBitmap = Bitmap.createBitmap(screenshotBitmap, 0,
  12. statusBarHeight, width, height - statusBarHeight);
  13. } catch (OutOfMemoryError e) {
  14. e.printStackTrace();
  15. }

4.当系统sdk版本大于16时使用API提供的ScriptIntrinsicBlur方法进行模糊化,值是从1--25.小于16时采用算法进行.

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

5.当使用前4步的时候,会发现并不能达到自己想要的特别深入的模糊。那么我们就需要回到需求上,既然是深度模糊,那么在截屏压缩的时候就不需要在意其得到的图片分辨率的大小了,那么可以先获取长宽,然后将其变小,生成新的Bitmap。

 
  1. // 将去掉标题栏的Bitmap再次失真,
  2. screenshotBitmap = Bitmap.createScaledBitmap(screenshotBitmap,
  3. screenshotBitmap.getWidth() / scaleRatio,
  4. screenshotBitmap.getHeight() / scaleRatio, false);

我在这里把其处理放在去掉标题栏之后。scaleRatio值越大,模糊程度越高。

 

转载于:https://my.oschina.net/u/2438447/blog/827156

你可能感兴趣的文章
thrift 远程服务调用 简单示例
查看>>
FPGA与simulink联合实时环路系列——实验三 按键key
查看>>
Java并发编程:线程池的使用
查看>>
Docker 下系统日志恢复
查看>>
KBEngine 服务器端-loginapp-协议构建、解析执行
查看>>
spring mvc ehcache 详细配置 亲测可用
查看>>
ssm整合详解
查看>>
Wepy--小程序自定义底部tabBar
查看>>
linux的目录结构
查看>>
理解 JavaScript 中的 this
查看>>
Centos7关闭防火墙
查看>>
ES搜索引擎集群模式搭建【Kibana可视化】
查看>>
php去除html标签
查看>>
django常见问题
查看>>
使用eclipse上传代码到SVN服务器-----学习总结(一)
查看>>
c#4.8-4.11学习总结
查看>>
使用expdp的心得
查看>>
SIP进行时
查看>>
webmagic使用手册
查看>>
2761: [JLOI2011]不重复数字(哈希表)
查看>>