1. 程式人生 > >你不可錯過的二維碼生成與解析-java後臺與前端js都有

你不可錯過的二維碼生成與解析-java後臺與前端js都有

1.二維碼分類

  二維條碼也有許多不同的碼制,就碼制的編碼原理而言,通常分為三種類型。

  1. 線性堆疊式二維碼

編碼原理:
建立在一維條碼基礎之上,按需要堆積成兩行或多行。

圖示:
image

  1. 矩陣式二維碼

最常用編碼,原理:
在一個矩形空間通過黑白畫素在矩陣中的不同分佈進行編碼。在矩陣相應的位置上,用點(方點、圓點或其它形狀)的出現表示二進位制“1”,點的不出現表示二進位制的“0”

圖示:
image

  1. 郵政碼

    通過不同長度的條進行編碼,主要用於郵政編碼。

2.QR Code

  現在最常用的就是這種,咱們現在主要介紹的也是這種。為啥這種使用二維碼那麼受反應呢?主要QR Code這種二維碼有如下優點:

  1. 識讀速度快
  2. 資料密度大
  3. 佔用空間小

2.1 QR Code介紹

image

2.2 QR Code 結構

image
大家可以瞭解下二維碼的結構,知道大概就行了,如果想了解詳細資訊的話可以自行百度,國家有詳細的二維碼規範。

3.後臺JAVA程式碼實現二維碼(QR Code)生成

  這裡介紹如下兩種實現方式:

  1. Java 後臺實現,主要使用zxing和qrcodejar等第三方jar包。
  2. 前端javascript實現,主要使用jquery.qrcode.js

3.1 使用zxing生成二維碼

3.1.1 zxing相關網站

zxing的GitHub
zxing的Java文件

3.1.2 生成zxing jar包

由於github上沒有相關的jar包,所以需要我們自己生成一下,上面有好多關於android相關的,我們只需要選取核心包和javase這兩部分程式碼。既下圖矩形框內容:
image


生成方式我大致說下:首先在ecplise裡新建一個java專案zxing,將剛才畫框程式碼拷貝進去,然後匯出jar包即可。如果你不想生成也可以在我的github上自行下載。

3.1.3 生成二維碼程式碼

package cn.rivamed.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.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class CreateQRCode {
    public static void main(String[] args) {
        
        int width=300;
        int height=300;
        
        String format="png";
        //這裡如果你想自動跳轉的話,需要加上https://
        String content="https://github.com/hbbliyong/QRCode.git";
        
        HashMap hits=new HashMap();
        hits.put(EncodeHintType.CHARACTER_SET, "utf-8");//編碼
        //糾錯等級,糾錯等級越高儲存資訊越少
        hits.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        //邊距
        hits.put(EncodeHintType.MARGIN, 2);
        
        try {
            BitMatrix bitMatrix=new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hits);
            //如果做網頁版輸出可以用輸出到流
            //MatrixToImageWriter.writeToStream(matrix, format, stream);
            Path path=new File("D:/zxingQRCode.png").toPath();
            MatrixToImageWriter.writeToPath(bitMatrix, format, path);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("that is all");
    }
}

生成的結果如下:
image

由於程式碼都有詳細註釋,我就不一一講解了,有疑問可以留言,我們一塊探討。

3.1.4 解析二維碼程式碼

package cn.rivamed.zxing;

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;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class ReadQRCode {

    public static void main(String[] args) {
        try {
            MultiFormatReader formatReader=new MultiFormatReader();
            File file=new File("D:/zxingQRCode.png");
            BufferedImage image=ImageIO.read(file);
            BinaryBitmap binaryBitmap=new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));
            
            HashMap hints=new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//編碼
            
            Result result=formatReader.decode(binaryBitmap, hints);
            System.out.println("解析結果:"+result.toString());
            System.out.println("二維碼格式型別:"+result.getBarcodeFormat());
            System.out.println("二維碼文字"+result.getText());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

3.2 使用qrcode生成解析二維碼

3.2.1 生成二維碼

package cn.rivamed.qrcode;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.imageio.ImageIO;

import com.swetake.util.Qrcode;

public class CreateQRCode {

    public static void main(String[] args) throws IOException {

        Qrcode x=new Qrcode();
        int version=7;
        x.setQrcodeErrorCorrect('M');//糾錯等級
        x.setQrcodeEncodeMode('B');//N代表數字,A代表a-Z,B代表其它(中文等)
        
        x.setQrcodeVersion(version);//版本號
        String qrData="https://github.com/hbbliyong/QRCode.git";
        //int width=300;
        int width=67+12*(version-1);
        //int height=300;
        int height=67+12*(version-1);
        BufferedImage bufferedImage=new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        
        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("gb2312");
        //byte[] d=qrData.getBytes();
        if(d.length>0&&d.length<120){
            boolean[][] s=x.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", new File("D:/qrcode.png"));
    }

}

生成的結果如下:

image

這裡需要注意的是,二維碼長寬不能想zxing之直接定義,需要跟進這個公式生成67+12*(version-1)。比如我直接定義二維碼的長寬為300.就會變成如下樣子。
image這上面空白看的不是太清,你把圖片下載下載下來看就比較明顯了。

3.2.2 解析二維碼

package cn.rivamed.qrcode;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.data.QRCodeImage;

public class ReadQRCode {

    public static void main(String[] args) throws IOException {
        File file=new File("D:/qrcode.png");
        BufferedImage bufferedImage=ImageIO.read(file);
        QRCodeDecoder codeDecoder=new QRCodeDecoder();
        String result=new String(codeDecoder.decode(new QRCodeImage() {
            
            @Override
            public int getWidth() {
                // TODO Auto-generated method stub
                return bufferedImage.getWidth();
            }
            
            @Override
            public int getPixel(int arg0, int arg1) {
                // TODO Auto-generated method stub
                return bufferedImage.getRGB(arg0, arg1);
            }
            
            @Override
            public int getHeight() {
                // TODO Auto-generated method stub
                return bufferedImage.getHeight();
            }
        }),"gb2312");
        System.out.println(result);
    }

}

4.前臺程式碼jquery生成二維碼

4.1 jquery.qrcode.js 的 GitHub

4.2 相關程式碼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>二維碼生成</title>
<script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery.qrcode.min.js"></script>
</head>
<body>
生成的二維碼如下:<br>
<dir id="qrcode"></dir>
<script type="text/javascript">
jQuery('#qrcode').qrcode('https://github.com/hbbliyong/QRCode.git');
</script>
</body>
</html>

5.結束語

所有的程式碼我都上傳到了github上面,大家可以下載執行。這裡面介紹的都比較基礎的,但也包含了前端後臺多種方式,對於簡單的應用已經足夠了。至於一些擴充套件,如果加上logo啊,電子名品啊,大家可以自行摸索。感謝您的觀看,如果有什麼疑問可以留言。

ps:
一個線上生成二維碼的網站推薦:線上工具
這個工具也是使用的zxing