Java与JS生成二维码与条形码
一般常见的是二维码和条形码,二维码常见类型是qrcode,二维码就是code128.扫码枪可以识别二维码,也可以识别条形码。扫码枪扫码其实是识别码中的内容并按下回车键。所以经常用条形码实现搜索等功能。二维码识别之后如果是URL地址一般会自动跳转,如果是普通的字符串会显示内容。
1.二维码概念
二维码/二维条码是用某种特定的集合图形按一定规律在平面上(二维方向上)分布的黑白相间的图形记录数据符号信息的图片。
黑线是二进制的1,空白的地方是二进制的0,通过1、0这种数据组合用于存储数据。
2.二维码分类:
二维码有不同的码制,就码制的编码原理而言,通常分为三类:
1.线性堆叠式二维码
2.矩阵式二维码(常用) 黑线、点是二进制的1,空白的地方是二进制的0,通过1、0这种数据组合用于存储数据。
3.邮政码.一般用于邮件编码
三、QRCode简介:
qrcode是日本公司研发的一套标准,市面流行的也是qrcode。
1.JSP生成QRCode的两种方式:
(1)借助第三方jar,如zxing,qrcode.jar
(2)javascript,例如:jquery.qrcode.js
四、zxing实现生成和解析二维码
1.下载源码并达成jar包。
源码下载地址 https://github.com/zxing/zxing
2.打成ajr包(将cor和javase目录下的文件打包)
也可以直接到这里下载我导好的jar包:http://qiaoliqiang.cn/fileDown/zxing.jar
3.导入项目开始生成二维码(可以将二维码生成到本地,也可以生成到输入流在网页中访问)
生成二维码的代码:
package zxing; import java.io.File; import java.nio.file.Path; import java.util.HashMap; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /** * 生成二维码图片 * @author: qlq * @date : 2018年6月1日下午6:00:57 */ public class CreateQRCode { public static void main(String[] args) { int height = 300;//设置高度 int width = 300;//设置宽度 String format = "png"; String content = "这里是二维码的内容"; //设置二维码的参数 HashMap hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//设置编码格式 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//一般M够用 hints.put(EncodeHintType.MARGIN, 2);//设置边距 try { //编码 BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height ,hints); //设置生成的路径 Path path = new File("E:/zxing.png").toPath(); //导出二维码(可以以流的形式在网页访问,也可以导出到本地) // MatrixToImageWriter.writeToStream(matrix, format, stream); MatrixToImageWriter.writeToPath(bitMatrix, format, path); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
结果,E盘下生成二维码,扫描结果: 这里是二维码的内容
补充:关于条形码和二维码
QR_CODE是条形码
CODE_128是二维码。
4.zxing解析二维码内容
代码:
package zxing; import java.awt.event.MouseWheelEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.HashMap; import javax.imageio.ImageIO; import com.google.zxing.Binarizer; import com.google.zxing.BinaryBitmap; import com.google.zxing.EncodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.MultiFormatWriter; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.BitArray; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; /** * 读取二维码 * @author: qlq * @date : 2018年6月1日下午6:01:55 */ public class ReadQRCode { public static void main(String[] args) throws IOException, NotFoundException { MultiFormatReader multiFormatReader = new MultiFormatReader(); File file = new File("E:/zxing.png"); BufferedImage bufferedImage = ImageIO.read(file); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage))); //设置二维码的参数 HashMap hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//设置编码格式 //读取二维码图片 Result result = multiFormatReader.decode(binaryBitmap, hints); System.out.println("解析结果:"+result.toString()); System.out.println("二维码格式类型:"+result.getBarcodeFormat()); System.out.println("二维码文本内容:"+result.getText()); } }
结果:
解析结果:这里是二维码的内容
二维码格式类型:QR_CODE
二维码文本内容:这里是二维码的内容
五、qrcode实现生成和解析二维码(支持中间嵌入图片)
1.qrcode生成二维码
需要的jar包下载地址: http://qiaoliqiang.cn/fileDown/qrcode/Qrcode_create.jar
生成二维码的代码:
package qrcode; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import com.swetake.util.Qrcode; /** * 生成二维码的图片 * @author: qlq * @date : 2018年6月1日下午6:43:16 */ public class createQrcode { public static void main(String[] args) throws Exception { Qrcode qrcode = new Qrcode(); qrcode.setQrcodeErrorCorrect('M');//纠错等级 qrcode.setQrcodeEncodeMode('B');//N代表数字A代表a-Z,B代表其他字符 qrcode.setQrcodeVersion(7);//版本号 String content = "这是qrcode生成的二维码"; // int height = 300; //宽高要根据公式设置。67*12*(版本号-1) int height = 67 + 12 * (7 - 1); int width = 67 + 12 * (7 - 1); int pixoffset = 2;//偏移量,需要加偏移量,否则会报错 BufferedImage bufferedImage =new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics2D graphics2d = bufferedImage.createGraphics(); graphics2d.setBackground(Color.WHITE); graphics2d.setColor(Color.black); graphics2d.clearRect(0, 0, width, height); byte[] bytes = content.getBytes(); if(bytes.length > 0 && bytes.length < 120){ boolean [][] s = qrcode.calQrcode(bytes); for(int i=0;i<s.length;i++){ for(int j=0;j<s.length;j++){ if(s[i][j]){ graphics2d.fillRect(j*3, i*3, 3, 3); } } } } graphics2d.dispose(); bufferedImage.flush(); ImageIO.write(bufferedImage, "png", new File("E:/qrcode.png")); } }
结果生成二维码,扫描结果是: 这是qrcode生成的二维码
qrcode生成带图片的二维码:
package qrcode; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import com.swetake.util.Qrcode; /** * 生成带图片的二维码 * * @author: qlq * @date : 2018年6月3日上午9:40:38 */ public class createImageQRCode { public static void main(String[] args) { createImageQRCode.QRCodeCreate("http://qiaoliqiang.cn","E:/qrImageCode.png",8,"C:/Users/liqiang/Desktop/文件/图片库/平时有用的图片/right.jpg"); } /** * QRCode 方式生成带图片二维码 * * @param content * 二维码内容 * @param imgPath * 二维码生成路径 * @param version * 二维码版本 * @param logoPath * 是否生成Logo图片 为NULL不生成 */ public static void QRCodeCreate(String content, String imgPath, int version, String logoPath) { try { Qrcode qrcodeHandler = new Qrcode(); // 设置二维码排错率,可选L(7%) M(15%) Q(25%) H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小 qrcodeHandler.setQrcodeErrorCorrect('M'); // N代表数字,A代表字符a-Z,B代表其他字符 qrcodeHandler.setQrcodeEncodeMode('B'); // 版本1为21*21矩阵,版本每增1,二维码的两个边长都增4;所以版本7为45*45的矩阵;最高版本为是40,是177*177的矩阵 qrcodeHandler.setQrcodeVersion(version); // 根据版本计算尺寸 int imgSize = 67 + 12 * (version - 1); byte[] contentBytes = content.getBytes("gb2312"); BufferedImage bufImg = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB); Graphics2D gs = bufImg.createGraphics(); gs.setBackground(Color.WHITE); gs.clearRect(0, 0, imgSize, imgSize); // 设定图像颜色 > BLACK gs.setColor(Color.BLACK); // 设置偏移量 不设置可能导致解析出错 int pixoff = 2; // 输出内容 > 二维码 if (contentBytes.length > 0 && contentBytes.length < 130) { boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes); for (int i = 0; i < codeOut.length; i++) { for (int j = 0; j < codeOut.length; j++) { if (codeOut[j][i]) { gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3); } } } } else { System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,130 ]. "); } /* 判断是否需要添加logo图片 */ if (logoPath != null) { File icon = new File(logoPath); if (icon.exists()) { int width_4 = imgSize / 4; int width_8 = width_4 / 2; int height_4 = imgSize / 4; int height_8 = height_4 / 2; Image img = ImageIO.read(icon); gs.drawImage(img, width_4 + width_8, height_4 + height_8, width_4, height_4, null); gs.dispose(); bufImg.flush(); } else { System.out.println("Error: login图片不存在!"); } } gs.dispose(); bufImg.flush(); // 创建二维码文件 File imgFile = new File(imgPath); if (!imgFile.exists()) imgFile.createNewFile(); // 根据生成图片获取图片 String imgType = imgPath.substring(imgPath.lastIndexOf(".") + 1, imgPath.length()); // 生成二维码QRCode图片 ImageIO.write(bufImg, imgType, imgFile); } catch (Exception e) { e.printStackTrace(); } } }
结果:
2.qrcode读取二维码图片 (有点问题,建议使用zxing读取二维码,上面的读取方式)
下载读取的jar包: http://qiaoliqiang.cn/fileDown/qrcode/qrcode_read.jar
代码:
1.定义类实现QRCodeImage接口
package qrcode; import java.awt.image.BufferedImage; import jp.sourceforge.qrcode.data.QRCodeImage; /** * 自定义读取qrcode的类 * @author: qlq * @date : 2018年6月1日下午7:04:27 */ public class MyQrcodeImage implements QRCodeImage{ private BufferedImage bufferedImage; public MyQrcodeImage(BufferedImage bufferedImage){ this.bufferedImage = bufferedImage; } @Override public int getHeight() { // TODO Auto-generated method stub return bufferedImage.getHeight(); } @Override public int getPixel(int arg0, int arg1) { // TODO Auto-generated method stub return bufferedImage.getRGB(arg0, arg1); } @Override public int getWidth() { // TODO Auto-generated method stub return bufferedImage.getWidth(); } }
2.读取二维码的代码
package qrcode; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import jp.sourceforge.qrcode.QRCodeDecoder; /** * qrcode读取二维码 * * @author: qlq * @date : 2018年6月1日下午7:07:00 */ public class QrcodeReadQRCode { public static void main(String[] args) throws IOException { File file = new File("E:/qrcode.png"); BufferedImage bufferedImage = ImageIO.read(file); QRCodeDecoder decoder = new QRCodeDecoder(); String result = new String(decoder.decode(new MyQrcodeImage(bufferedImage)),"utf-8"); System.out.println(result); } }
六、JS生成二维码(简单)
原理也是生成一张图片,可以将图片保存到本地。可以生成带logo的二维码,内容可以设置中文。
jquery-qrcode: https://github.com/jeromeetienne/jquery-qrcode
前提需要引入jQuery,也可以到我的下载链接直接下载对应的jQuery和qrcode的JS。http://qiaoliqiang.cn/fileDown/qrcode.js.zip
生成二维码的例子如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>生成二维码</title> <script type="text/javascript" src="./JS/jquery.min.js"></script> <script type="text/javascript" src="./JS/jquery.qrcode.min.js"></script> </head> <body> 生成的二维码如下: <div id="qrcode"></div> <br/> 生成的指定宽度二维码如下: <div id="qrcode1"></div> <br/> 生成的带logo的二维码如下: <div id="qrcode2"></div> <script> /*生成二维码,注意jQuery的Q要大写*/ jQuery('#qrcode').qrcode("http://qiaoliqiang.cn"); /*生成指定高度和宽度的二维码*/ jQuery('#qrcode1').qrcode({width: 64,height: 64,text: "http://qiaoliqiang.cn"}); /*生成指定高度和宽度和带logo的二维码,且文字内容是中文*/ jQuery('#qrcode2').qrcode({width: 64,height: 64,src:'./image/left.jpg',text: toUtf8("欢迎你")}); </script> </body> </html>
注意:
生成带logo的二维码的需要下载支持logo的qrcode.js,在我的下载地址的js是支持的。
生成二维码的时候jQuery的Q要大写
结果:
七、二维码扩展:
1.为什么我们扫描出来的是文本而不是连接?
如果我们的url中没有协议,默认作为文本处理,如果路径加了协议会作为URL,扫描之后会跳转。
qiaoliqiang.cn 改为 http://qiaoliqiang.cn
2.如何实现扫描二维码之后安装软件?
例如:安卓手机的下载地址: http://xxxx.com/mobile/appdown/xxx.apk (安卓手机的安装包后缀是apk)
如果我们用浏览器或者其他自带的扫描是可以下载,但是微信不行,因为腾讯只有自己域名下的apk才可以通过扫一扫下载。
3.如何实现二维码扫描名片?(重要)
简单的话自己可以做一个网页实现,扫描的时候跳转到自己的网页即可。另外一种高大上的方式是VCard, Vcard是标准通信薄基本格式。
VCard地址:https://en.wikipedia.org/wiki/VCard
属性参考:https://blog.csdn.net/xfyangle/article/details/58601585
内容遵从VCard规范,参考上面网站可以生成许多属性,建议使用zxing的方式在后台生成名片:
String content = "BEGIN:VCARD"+"\n" +"VERSION:4.0"+"\n" +"N:乔;利强"+"\n" +"FN:乔利强"+"\n" +"EMAIL:qiao_liqiang@163.com"+"\n" +"KIND:individual"+"\n" +"LOGO;MEDIATYPE=image/png:http://qiaoliqiang.cn/fileDown/qlq.png"+"\n" +"BDAY:1995-02-03"+"\n" +"NOTE:我是一个好孩子!"+"\n" +"NICKNAME:QiaoZhi"+"\n" +"TEL;TYPE=cell:18434391711"+"\n" +"URL:http://qiaoliqiang.cn"+"\n" +"ORG:公司名称"+"\n" +"TITLE:职位"+"\n" +"x-qq:21588891"+"\n" // +"HOBBY;LEVEL=high:knitting"+"\n" // +"INTEREST;LEVEL=high:baseball"+"\n" +"ADR;TYPE=home:;;123 Main St.;Springfield;IL;12345;USA"+"\n" +"PHOTO;MEDIATYPE=image/jpeg:http://qiaoliqiang.cn/fileDown/qlq.jpeg"+"\n" +"END:VCARD";
扫描结果会变成一张名片: