一 简介
二维码的重要性不言而喻。二维条形码最早发明于日本,它是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的,在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理。它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化等特点。
常用的二维码开发工具包有QRCode,ZXing和barcode4j。QRCode是日本人开发的,也是最早的二维码开发包; ZXing是google开发的,barcode4j也是老美开发的,barcode4j对一维条形码处理的很好,而且支持的格式很多,当然也可以对二维码进行处理,效果个人感觉没有前两种好。这里以QRCode为例阐述二维码的开发应用。
二 案例
工程结构图
二维码实现类MyQrCodeImage.java
package com.accp.utils;
import java.awt.image.BufferedImage;
import jp.sourceforge.qrcode.data.QRCodeImage;
/**
* 二维码实现类
* @author wx
* 解析二维码时需要
*/
public class MyQrCodeImage implements QRCodeImage{
BufferedImage bufferedImage;
public MyQrCodeImage(BufferedImage bufferedImage) {
this.bufferedImage = bufferedImage;
}
public int getHeight() {
return bufferedImage.getHeight();
}
public int getPixel(int arg0, int arg1) {
return bufferedImage.getRGB(arg0, arg1);
}
public int getWidth() {
return bufferedImage.getWidth();
}
}
二维码工具类,直接调用里面的方法可以直接生成不带logo的二维码和带logo的二维码,请看代码详细注释
package com.accp.utils;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.data.QRCodeImage;
import com.swetake.util.Qrcode;
public class QrCodeUtil {
/**
* 产生不带logo的二维码
* @param os 输出流,即验证码图片的目的地
* @param qrData 二维码中包含的信息(即扫描出来的结果)
* @param size 二维码大小 7,8,9等
* @throws IOException
*/
public static void createQrCode(OutputStream os, String qrData, int size)
throws IOException {
// 创建一个生成二维码对象
Qrcode code = new Qrcode();
// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),
// 排错率越高可存储的信息越少,但对二维码清晰度的要求越小
code.setQrcodeErrorCorrect('M');
// N代表数字,A代表a-Z,B代表其它字符
code.setQrcodeEncodeMode('B');
// 设置设置二维码版本,取值范围1-40,值越大尺寸越大,可存储的信息越大
code.setQrcodeVersion(size);
// 二维码图片的宽和高
int width = 67 + 12 * (size - 1);
int height = 67 + 12 * (size - 1);
// 定义一个图片对象
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bufferedImage.createGraphics();
// 设置画笔
gs.setBackground(Color.WHITE);
gs.setColor(Color.BLACK);
gs.clearRect(0, 0, width, height);
int pixoff = 2;// 偏移量
byte[] d = qrData.getBytes("utf-8");
if (d.length > 0 && d.length < 120) {
boolean[][] s = code.calQrcode(d);
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < s.length; j++) {
if (s[j][i]) {
// 往画板中填充内容
gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
}
}
}
}
gs.dispose();
bufferedImage.flush();
ImageIO.write(bufferedImage, "png", os);
}
/**
* 创建带logo的二维码
*/
public static void createLogoCode(String imgPath, String logoPath,
String qrData, int size) throws IOException {
// 创建一个生成二维码对象
Qrcode code = new Qrcode();
// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),
// 排错率越高可存储的信息越少,但对二维码清晰度的要求越小
code.setQrcodeErrorCorrect('M');
// N代表数字,A代表a-Z,B代表其它字符
code.setQrcodeEncodeMode('B');
// 设置设置二维码版本,取值范围1-40,值越大尺寸越大,可存储的信息越大
code.setQrcodeVersion(size);
// 二维码图片的宽和高
int width = 67 + 12 * (size - 1);
int height = 67 + 12 * (size - 1);
// 定义一个图片对象
BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bufferedImage.createGraphics();
// 设置画笔
gs.setBackground(Color.WHITE);
gs.setColor(Color.BLACK);
gs.clearRect(0, 0, width, height);
int pixoff = 2;// 偏移量
byte[] d = qrData.getBytes("utf-8");
if (d.length > 0 && d.length < 120) {
boolean[][] s = code.calQrcode(d);
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < s.length; j++) {
if (s[j][i]) {
// 往画板中填充内容
gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
}
}
}
}
//实例化一个Image对象。
Image img = ImageIO.read(new File(logoPath));
//定义二维码的宽和高,一般设置为版本的3倍
int logoWidth=size*3;
int logoHeight=size*3;
//把logo画到二维码的中心上去
gs.drawImage(img, width/2-logoWidth/2,
height/2-logoHeight/2, logoWidth, logoHeight, null);
gs.dispose();
bufferedImage.flush();
File imgFile = new File(imgPath);
ImageIO.write(bufferedImage, "png", imgFile);
}
/**
* 读取二维码
*
* @param imgPath
* 二维码路径
* @return 二维码包含信息
* @throws Exception
*/
public static String readQrCode(String imgPath) throws Exception {
File file = new File(imgPath);
BufferedImage bufferedImage = ImageIO.read(file);
QRCodeDecoder codeDecoder = new QRCodeDecoder();
QRCodeImage codeImg = new MyQrCodeImage(bufferedImage);
String result = new String(codeDecoder.decode(codeImg), "utf-8");
return result;
}
}
===============================
编写测试类,生成纯二维码
package com.accp.utils;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestReadCode {
public static void main(String[] args) {
FileOutputStream fos=null;
//验证码中包含的信息
String qrData = "http://wap.baidu.com/";
try {
fos=new FileOutputStream("c:\\temp\\qrcode.png");
//生成二维码
QrCodeUtil.createQrCode(fos,qrData,15);
String path="c:\\temp\\qrcode.png";
//解析二维码中包含的数据
String result=QrCodeUtil.readQrCode(path);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
结果如下
手机扫描后直接打开百度页面
======================================
编写测试类,生成带logo的二维码
package com.accp.utils;
import java.io.IOException;
public class TestLogoCode {
public static void main(String[] args) {
//最后生成的图片地址
String qrCodePath = "C:\\temp\\LogoCode.png";
//加入的logo照片
String logoPath = "C:\\temp\\aa.png";
String content = "http://wap.baidu.com/";
try {
QrCodeUtil.createLogoCode(qrCodePath, logoPath, content, 15);
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果如图
手机扫描后的结果和上一相同
=========================================
三 用jquery生成二维码
请自行下载jquery的二维码开发包jquery.qrcode.min.js,引入到工程中,如图:
UnicodeToUtf8.js是自己编写的一个解决中文乱码的js库,代码如下:
/* 把unicode字符转换为utf8格式 */
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for(i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
具体代码如下:
<%@ page language="java" import="java.util.* " pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="path" value="${pageContext.request.contextPath}"></c:set>
<c:set var="scheme" value="${pageContext.request.scheme}"></c:set>
<c:set var="serverName" value="${pageContext.request.serverName}"></c:set>
<c:set var="serverPort" value="${pageContext.request.serverPort}"></c:set>
<c:set var="basePath" value="${scheme}://${serverName }:${serverPort }${path }/"></c:set>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="${basePath }">
<title>js生成二维码</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.qrcode.min.js"></script>
<script type="text/javascript" src="js/UnicodeToUtf8.js"></script>
<script type="text/javascript">
$(document).ready(function(e){
$("#qrcode").hide();
$("#myCode").click(function(e){
var content=$("[name=content]").val();
content=$.trim(content);
if(content==""){
window.alert("请输入二维码中存储的信息,输入网址扫描后可自动跳转");
return;
}
$("#qrcode").html("");
$("#qrcode").show();
//生成二维码
$("#qrcode").qrcode({
width: 256, //设置宽度
height: 256, //设置高度
render:'canvas', //设置渲染方式
text:utf16to8(content) //设置内容
});
});
});
</script>
</head>
<body>
<h2><input type="text" name="content"/>
<input type="button" value="生成验证码" id="myCode"/></h2>
<div align="center" id="qrcode"
style="border: 2px solid red; width:600px;" ></div>
</body>
</html>
运行结果如下:
手机扫描后的结果