#星光计划2.0#应用开发-独家发布-摄像头扫描二维码(Java版) 原创 精华
【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】
昨天周日,在酒店撸了一下午,加晚上到12点,终于把摄像头扫码的java版本撸了个大概,可以实现的效果就是打开摄像头扫描一张二维码图片然后显示二维码里面的内容,看个视频一睹为快吧(界面待优化):
可以看到二维码扫描成功之后会在屏幕底下弹出一个带有内容的气泡
1.前面的话:
其实我也不知道是怎么回事,对于扫码这么高频的需求官方竟然没有集成进来(最新的消息js已经集成了,但是java还没有,只有一个生成二维码的代码),我翻了全网的文档找到了几个相关的:
1.https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/HarmonyOS-QRCode
这个是官方的codelabs的一篇帖子,无法模拟运行,就等于是个帖子,而且这帖子还被许多网友搬到了博客上,这个帖子本身没毛病,但是他最大的问题就是没搞定,具体说来就是给你一个模糊的基础让你知道怎么回事而已,但是这帖子有一些可取的地方我们稍后再说
2.https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-camera-guidelines-0000000000031782
这个是HarmonyOS的官方开发文档,里面有介绍怎么启用相机拍照,录视频,这个文档最大的作用就是告诉你怎么操作摄像头,但是对于扫码,只字未提
3.https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ai-code-genration-overview-0000001051062161
这个基本没用,只有码生成而没有解析,差评
4.https://developer.harmonyos.com/cn/docs/documentation/doc-references/ibarcodedetector-0000001054120097
这个帖子是javaAPI的使用手册,同样只有码生成而没有解析,还是差评
翻了一堆的帖子,我就纳闷了,二维码扫描这东西都出来这么多年了,技术上有啥难题吗,怎么全网都没有在弄的,要知道,微信小程序里面可是直接自带扫码接口的呀既然没有,就到了咱显一显身手的时候了哈哈.
2.技术思路
其实思路基本没啥,咱们日常生活中碰到扫描无非是三种:
一种是摄像头扫码
一种是图片直接解
还有一种在微信上比较常见的是长按某张图片帮你扫码,其实就是图片扫码一样的,
这里咱们着重处理摄像头扫码,因为图片扫描是摄像头扫码后面那部分,就是你摄像头已经取得图片了,然后再解析扫码,可以这样说:如果你学会了摄像头扫码,那么图片解析二维码你自动就会了,怎么样,是不是很心动,快跟我学起来吧
原理:启用手机摄像头–>摄像头预览–>对准二维码–>解析摄像头数据–>保存成图片–>发给二维码解析库解析–>获取解析结果
3.开工
3.1 打开你的手机摄像头
摄像头的启用,怎么拍图片在这篇官方文档上讲的很清楚了:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-camera-guidelines-0000000000031782
而且文档下面还有一个gitee仓库给你看源码,这块我寻思不用多讲吧:
https://gitee.com/harmonyos/harmonyos_app_samples/tree/master/media/Camera
请首先顺利得能让你的手机拍一张照片出来
提示,此处有坑:真机调试时需要在手机权限里手动把摄像头权限打开,否则你得到的是一个黑屏,这个问题折腾了我半个小时,我以为在代码里面加了权限,而手机也没有弹出权限提示框就以为权限是正常的,结果进到设置一看尼玛禁的死死的
3.2 把官方代码的图片保存函数替换掉
其实就是这个函数:
private void saveImage(ImageReceiver receiver)
怎么改呢,咱有参考,还记得上面提到的官方codelabs吗,对就是他:
https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/HarmonyOS-QRCode
这地方有怎么把你拍到的图片转换成Pixel像素图
3.3 上大招,zxing闪亮登场
以下为心路历程:
在官方的那个codelabs里面,最后一句话他说:—-结束
what?
怎么就结束了?
当时给我看的那叫懵啊,不过好在咱有逻辑思维分析能力,往上翻,上一篇叫二维码识别,好,看吧:
哦哦,引入一下这三个文件是吧,简单,我找一下哈
…
请问文件在哪?
唉不整了,玩个游戏先
打了会游戏,又觉无聊,唉,还是学习吧,谁叫咱热爱学习呢.
几经搜索,给我找到了一个叫做zxing的库,这个库着实强大,谷歌官方维护的,翻译一下这就叫惊喜,
二话不多整活了
3.3.1 下载zxing库
官方网址在这:https://github.com/zxing/zxing,最新版是3.4.1,直接下载过来
打开来一看,都是啥:
这里面东西不少,但凭着咱技术人的直觉,自己只需要里面的core,但是要怎么使用呢,官方readme上面有一句话:
那咱打开吧:https://github.com/zxing/zxing/wiki/Getting-Started-Developing
这里面有一句话引发了我的思考:
对,说到心坎里了,我只要一个jar包
合着前面的下载白弄了…
3.3.2 其实有更好的方式
根据自己的悟性领悟了,Maven转gradle的方式,直接在项目build.gradle里面加一句:
改完这个文件,ide提示你要同步一下,点击同步,这时候zxing-core就集成到你的项目中了,方便
3.3.3 集成,集成
这块我直接贴代码吧,讲起来有点啰嗦:
private void saveImage(ImageReceiver receiver) {
HiLog.info(LABEL_LOG,"==>saveImage");
ohos.media.image.Image image = receiver.readNextImage();
ohos.media.image.Image.Component component = image.getComponent(ImageFormat.ComponentType.JPEG);
byte[] jpgbytes = new byte[component.remaining()];
component.read(jpgbytes);
HiLog.info(LABEL_LOG,"....==>saveImage:%{public}d",jpgbytes.length);
ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
sourceOptions.formatHint = "image/jpg";
ImageSource imageSource = ImageSource.create(jpgbytes, sourceOptions);
PixelMap pixelMap = imageSource.createPixelmap(null);
int width = pixelMap.getImageInfo().size.width;
int height = pixelMap.getImageInfo().size.height;
int[] pis=new int[width * height];
HiLog.info(LABEL_LOG,"pix number byte %{public}d,size ==>%{public}s" +
" w %{public}d h %{public}d",
pixelMap.getPixelBytesNumber(),
pixelMap.getBytesNumberPerRow(),
width,height);
try{
pixelMap.readPixels(pis,0,width, new Rect(0,0,width,height));
}catch(Exception e){
HiLog.error(LABEL_LOG,"read Pixels error:%{public}s",e.toString());
return;
}
RGBLuminanceSource rgbSource = new RGBLuminanceSource(
pixelMap.getImageInfo().size.width,pixelMap.getImageInfo().size.height,pis);
HiLog.info(LABEL_LOG,"source :%{public}s",rgbSource.toString());
LuminanceSource source = rgbSource.crop(0,0,rgbSource.getWidth(),rgbSource.getHeight());
BinaryBitmap bMap = new BinaryBitmap(new HybridBinarizer(source));
final Map<DecodeHintType, Object> hints = new HashMap<>();
hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
QRCodeReader reader=new QRCodeReader();
Result result = null;
try{
result =reader.decode(bMap,hints);
HiLog.info(LABEL_LOG,"==>result:"+result.toString());
showTips(this.getContext(),result.toString());
}catch (NotFoundException e){
HiLog.info(LABEL_LOG,"not found:"+e.toString());
}catch (Exception e){
HiLog.error(LABEL_LOG,"catch Exception:"+e.toString());
}
}
短短的60行左右就搞定了(实际上折腾了5Hour+)
前面一直到第13行大家都能看懂,就是转换Pixel图片,不懂的同学往上翻去复习哈
后面就是把像素取出来,传给zxing去解析,核心代码在QRcode.decode()这里,前面的都是辅料
3.3.4 打完收工
到这里我java版本的二维码识别扫描就初步完成了,大家可以行测试了
4.总结
是不是感觉挺简单的,说来也是奇怪,这么简单的东西为啥就是没人做呢,借星光计划给大家发第一篇文章,一起期待下一篇吧
感谢楼主开路