前言
目前市面上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线程不断的分析流并解码.
private void decode( byte [] data, int width, int height)
这个data是YUV格式的,谷歌也提供了相关的转换方法Yuvimage.
将YUV转换为agb方法(网上摘抄,天下文章一大抄)
private int [] decodeYUV420SP( byte [] yuv420sp, int width, int height) {
final int frameSize = width * height;
int rgb[] = new int [width * height];
for ( int j = 0 , yp = 0 ; j < height; j++) {
int uvp = frameSize + (j >> 1 ) * width, u = 0 , v = 0 ;
for ( int i = 0 ; i < width; i++, yp++) {
int y = ( 0xff & (( int ) yuv420sp[yp])) - 16 ;
if (y < 0 ) y = 0 ;
if ((i & 1 ) == 0 ) {
v = (0xff & yuv420sp[uvp++]) - 128 ;
u = (0xff & yuv420sp[uvp++]) - 128 ;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0 ) r = 0 ;
else if (r > 262143 ) r = 262143 ;
if (g < 0 ) g = 0 ;
else if (g > 262143 ) g = 262143 ;
if (b < 0 ) b = 0 ;
else if (b > 262143 ) b = 262143 ;
rgb[yp] = 0xff000000 | ((r << 6 ) & 0xff0000 ) | ((g >> 2 ) &
0xff00 ) | ((b >> 10 ) & 0xff );
}
}
return rgb;
}
使用Bitmap.createBitmap转换为bitmap图片下,分析图片颜色的平均值,颜色都是16进制的,不懂的可以网上搜下,黑色的颜色 对应int = -16777216, 所以我们认为当前的平均值 / black(-16777216) 小于等于1 同时大于0.99,就认为是弱光(这个值还可以调节)
private int getAverageColor(Bitmap bitmap) {
int redBucket = 0 ;
int greenBucket = 0 ;
int blueBucket = 0 ;
int pixelCount = 0 ;
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 推荐
收藏