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";

 

扫描结果会变成一张名片:

 

posted @ 2018-06-01 18:26  QiaoZhi  阅读(1413)  评论(0编辑  收藏  举报