Android高仿微信/支付宝 扫一扫(弱光检测扫一扫自动放大功能) - Go语言中文社区

Android高仿微信/支付宝 扫一扫(弱光检测扫一扫自动放大功能)


前言


 目前市面上App携带的扫一扫功能大多是乞丐版,怎么说,就是只有扫一扫.而目前来说扫一扫做的最好的还是微信,微信有弱光环境的检测(可以自动提示用户打开闪光灯),同时,当发现扫描目标距离过远时,还可以自动的放大镜头,亲测可以多次的放大,所以说细节决定成败,支付宝虽然也有微信的功能,但是我觉得支付宝的弱光做的一般,自动放大也有点鸡肋,不过也很不错了,毕竟一般来说,实现扫一扫乞丐版就基本完事了,而我也遇到了这个需求,就是要实现微信和支付宝类似的效果.


效果图走一波(用的gif大师,录制的质量比较低,质量过高的传不上去,见谅)


第一帧gif当为弱光时,动态显示“手电筒”,点击打开后,一直显示“关系手电筒”.

第二个gif帧就是扫一扫自动放大的效果.

 



需求分析


1.中间的frame框就不说了,比较的简单,ondraw里边修改,用安卓纯纯的坐标系,就可以实现.
2.弱光检测: 这块我花了两天的时间研究,ios获取后置摄像头的光感比较的方便,几行代码就可以获取,他们的是brightnessvalue这个值;而安卓第一版我用的光传感器,你要知道,光传感器是在前置摄像头附近,而扫一扫是用后置摄像头来扫描的,光传感器晚上是没有问题的,白天不是非常的精确,就放弃了这个方案,最后查了相关的资料我使用jpegReader.metadata(),exifinterface来读取实时帧流,均以失败告终,我想Camera2应该提供了某些的api,但是要求是5.0之后了,我也就没有细研究,之后,我看到支付宝的效果后,我就明白了,他分析的是后摄像头拍照的图片颜色来区分的,多次尝试发现,是这样,同理,微信应该也是类似的实现,只不过他调的比较细,优化的比较好而已.
3.扫一扫自动放大:这个你思考下,其实也很简单,Camera有放大的属性,无非是触发条件怎么来判断,微信扫一扫是当镜头中有二维码的是才会进行自动放大,并且会多次的放大.


代码实现


我们项目用的是zxing,不用说了要修改源码.

ui层就不说了,真的简单,安卓坐标系,cavas 画布api,来绘制rect区域,在ViewFindView这个类里边的onDraw方法修改即可.


弱光检测


  上面分析完后,就知道了,咱们要实时的分析图片的颜色值(agb值),既然说到了实时的分析,我们就要找到二维码处理解码实时帧的方法,zxing使用decodeThread,decodeHanlder,decodeThread线程不断的分析流并解码.
  1. /** 
  2.      * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, 
  3.      * reuse the same reader objects from one decode to the next. 
  4.      * 
  5.      * @param data   The YUV preview frame. 
  6.      * @param width  The width of the preview frame. 
  7.      * @param height The height of the preview frame. 
  8.      */  
  9.     private void decode(byte[] data, int width, int height)   

这个data是YUV格式的,谷歌也提供了相关的转换方法Yuvimage.

将YUV转换为agb方法(网上摘抄,天下文章一大抄)

[java] view plain copy
  1. private int[] decodeYUV420SP(byte[] yuv420sp, int width, int height) {  
  2.         final int frameSize = width * height;  
  3.   
  4.         int rgb[] = new int[width * height];  
  5.         for (int j = 0, yp = 0; j < height; j++) {  
  6.             int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;  
  7.             for (int i = 0; i < width; i++, yp++) {  
  8.                 int y = (0xff & ((int) yuv420sp[yp])) - 16;  
  9.                 if (y < 0) y = 0;  
  10.                 if ((i & 1) == 0) {  
  11.                     v = (0xff & yuv420sp[uvp++]) - 128;  
  12.                     u = (0xff & yuv420sp[uvp++]) - 128;  
  13.                 }  
  14.   
  15.                 int y1192 = 1192 * y;  
  16.                 int r = (y1192 + 1634 * v);  
  17.                 int g = (y1192 - 833 * v - 400 * u);  
  18.                 int b = (y1192 + 2066 * u);  
  19.   
  20.                 if (r < 0) r = 0;  
  21.                 else if (r > 262143) r = 262143;  
  22.                 if (g < 0) g = 0;  
  23.                 else if (g > 262143) g = 262143;  
  24.                 if (b < 0) b = 0;  
  25.                 else if (b > 262143) b = 262143;  
  26.   
  27.                 rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &  
  28.                         0xff00) | ((b >> 10) & 0xff);  
  29.   
  30.   
  31.             }  
  32.         }  
  33.         return rgb;  
  34.     }  


使用Bitmap.createBitmap转换为bitmap图片下,分析图片颜色的平均值,颜色都是16进制的,不懂的可以网上搜下,黑色的颜色 对应int = -16777216, 所以我们认为当前的平均值 / black(-16777216) 小于等于1 同时大于0.99,就认为是弱光(这个值还可以调节)

[java] view plain copy
  1. private int getAverageColor(Bitmap bitmap) {  
  2.      int redBucket = 0;  
  3.      int greenBucket = 0;  
  4.      int blueBucket = 0;  
  5.      int pixelCount = 0;  
  6.   
  7.      for (int y =  版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
    原文链接:https://blog.csdn.net/primezpy/article/details/78628030
    站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-04-19 11:09:39
  • 阅读 ( 1161 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢