1. 最近做项目遇到一个使用电脑摄像头拍摄二维码并解析二维码的内容需求,于是发现并没有对此有详细的记录,特开设这篇文章介绍怎么实现,如有更好的建议可以在评论区进行留言。
1.1 首先前台拍摄二维码使用的是插件jquery-webcam-plugin,这个插件是调用浏览器的falsh插件进行摄像头与麦克风的调用。
1.2 解析二维码写在了后台,使用java进行解析。
1.3 简单介绍下完成这个功能的流程:首先使用pc摄像头进行对二维码的拍摄,然后通过ajax进行发送到后台,然后后台使用zxing.jar包解析二维码
2 使用到的js与jar
2.1 前台对应jscam.swf文件,后台对应jar包稍后我会以maven形式贴出。
3. 代码示例:
pom.xml:
<!--生成解析二维码-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>net.glxn</groupId>
<artifactId>qrgen</artifactId>
<version>1.4</version>
</dependency>
前台代码段:
<input type="button" class="btn" onclick="openQRcode()" value="点击拍照"/>
<!-- 下边代码为弹出拍照窗口-->
<div class="modal fade" id="smbModal" tabindex="-1" role="dialog" aria-labelledby="mySmbModal" aria-hidden="true">
<div class="modal-dialog" style="width:400px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="smbLabel">拍摄窗口</h4>
</div>
<div class="modal-body">
<div id="smbwebcam"></div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-primary pull-left" onclick="saveSmbhoto()" value="拍照">
<input type="button" class="btn btn-primary pull-right" onclick="closeSmbModal()" value="返回">
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal -->
</div>
对应js方法:
//打开拍摄二维码窗口
function openQRcode(){
$('#smbLabel').html("拍摄窗口");
$('#smbModal').modal('show');
smbWebcam();
}
function smbWebcam() {
$("#smbwebcam").empty();
/**
* jquery webcam拍照
*/
var w = 375, h = 400;
var pos = 0, ctx = null ,image = [];
var canvas = document.createElement("canvas");
$(function() {
canvas.style.behavior = "url(/plugins/canvasforIE/ie-css3.htc)";
});
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
ctx = canvas.getContext("2d");
image = ctx.getImageData(0, 0, w, h);
jQuery("#smbwebcam").webcam({
mode: "callback",
swffile: "<%=appUrl%>/js/jscam.swf",
onTick: function (remain) {
},
onSave: function (data) {
var col = data.split(";");
var img = image;
for (var i = 0; i < w; i++) {
var tmp = parseInt(col[i]);
img.data[pos + 0] = (tmp >> 16) & 0xff;
img.data[pos + 1] = (tmp >> 8) & 0xff;
img.data[pos + 2] = tmp & 0xff;
img.data[pos + 3] = 0xff;
pos += 4;
}
if (pos >= 4 * w * h) {
// 将图片显示到canvas中
ctx.putImageData(img, 0, 0);
// 取得图片的base64码
var base64 = canvas.toDataURL("image/png",0.92);
// 将图片base64码设置给img
//传到后台
$.ajax({
url: 'updal.do',//改写成对应的controller路径即可
dataType: 'json',
data:{
"images":base64
},
type: 'post',
async:false,
success: function (res) {
if (res.success) {
$('#smbModal').modal('hide');
showOrinfo(res.data);
}else{
alert(res.message);
smbWebcam();
}
}
});
image = ctx.clearRect(0, 0, w, h);
pos = 0;
}
},
onCapture: function () {
webcam.save();
},
debug: function (type, string) {
},
onLoad: function () {
}
});
}
//关闭拍照model
function closeSmbModal() {
$('#smbModal').modal('hide')
}
//拍照
function saveSmbhoto() {
webcam.capture();
}
对应controller代码示例:
/**
* 上传二维码,并解析出人员数据
*/
@RequestMapping("upload.do")
@ResponseBody
public R uploadPath(@RequestParam("images") String images) {
R r = new R();
try {
//解析二维码
Result hasCode = QRCodeUtil.zxingCodeAnalyze(images);
if(hasCode==null){
return r.setMessage("无法解析二维码,请重新拍摄!").setSuccess(false);
}
system.out.println("解析二维码内容为"+hasCode); // 到此为止二维码已经解析
//以下为自己的业务逻辑省略...............
} catch (Exception e) {
return r.setMessage("获取信息失败,请重试!").setSuccess(false);
}
}
使用到的工具类:
/**
* zxing方式生成二维码的解析方法
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Result zxingCodeAnalyze(String base64String) {
MultiFormatReader formatReader = new MultiFormatReader();
BASE64Decoder decoder = new BASE64Decoder();
String base64 = base64String.replace("data:image/png;base64,","");
try {
byte[] bytes = decoder.decodeBuffer(base64);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
if (bais!=null) {
BufferedImage image = ImageIO.read(bais);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map hints = new HashMap();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
Result result = formatReader.decode(binaryBitmap, hints);
return result;
}
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
return null;
}
以上代码展示了整个拍照+解析二维码的流程,这个功能暂时只能手动点击拍照不能实现自动解析。可以尝试在js里边加一个定时功能,还有拍摄的照片是不进行保存的。每次拍摄都会出现falsh提示“是否允许使用摄像头与麦克风”。这个提示可以去掉具体操作的方法访问http://www.macromedia.com/support/documentation/cn/flashplayer/help/help05.html#117121。