zxing生成解析二維碼以及二維碼生成解析的一個Android應用程序

二維碼技術不是什麼新技術了,可是這幾天工做用到,而後才現學習現使用,使用的是Google的ZXing,使用起來很簡單,java

我練習的兩種方式,一種的簡單的javase工程,一種是Android客戶端生成解析二維碼的demo,線面逐個介紹。android

1、JavaSE生成解析二維碼,就是創建一個JavaProject,而後導入jar包,我用的是maven,因此創建了一個簡單的maven工程。git


一、第一種形式,生成一箇中間沒有logo的二維碼,並解析,寫好以後,直接說哪一個junit測試,就能生成解析二維碼了github

package com.wang.qr.code;  
  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.IOException;  
import java.nio.file.FileSystems;  
import java.nio.file.Path;  
import java.util.HashMap;  
import java.util.Map;  
  
import javax.imageio.ImageIO;  
  
import org.junit.Test;  
  
import com.alibaba.fastjson.JSONObject;  
import com.google.zxing.BarcodeFormat;  
import com.google.zxing.Binarizer;  
import com.google.zxing.BinaryBitmap;  
import com.google.zxing.DecodeHintType;  
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.WriterException;  
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;  
import com.google.zxing.client.j2se.MatrixToImageWriter;  
import com.google.zxing.common.BitMatrix;  
import com.google.zxing.common.HybridBinarizer;  
  
/** 
 * 生成沒有logo的二維碼</br> 有多個信息json 
 *  
 * @author wang 
 *  
 */  
public class QRCodeTest1 {  
  
    /** 
     * 生成二維碼</br> 
     *  
     * 二維碼中的內容是json數據 
     *  
     * @throws WriterException 
     * @throws IOException 
     */  
    @Test  
    public void testEncode() throws WriterException, IOException {  
  
        /* 
         * 把生成的二維碼放到此目錄下 
         */  
        String filePath = "E://";  
  
        /* 
         * 生成的二維碼名稱 
         */  
        String fileName = "zxing.png";  
  
        JSONObject json = new JSONObject();  
        json.put("zxing", "https://github.com/zxing/zxing/tree/zxing-3.0.0/javase/src/main/java/com/google/zxing");  
        json.put("author", "shihy");  
  
        /* 
         * 二維碼中的內容 
         */  
        String content = json.toJSONString();// 內容  
  
        int width = 200; // 圖像寬度  
        int height = 200; // 圖像高度  
        String format = "png";// 圖像類型  
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();  
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);// 生成矩陣  
        Path path = FileSystems.getDefault().getPath(filePath, fileName);  
        MatrixToImageWriter.writeToPath(bitMatrix, format, path);// 輸出圖像  
        System.out.println("輸出成功.");  
    }  
  
    /** 
     * 解析二維碼</br> 二維碼中的內容是json數據 
     */  
    @Test  
    public void testDecode() {  
  
        /* 
         * 要解析的二維碼 
         */  
        String filePath = "E://zxing.png";  
  
        BufferedImage image;  
        try {  
            image = ImageIO.read(new File(filePath));  
            LuminanceSource source = new BufferedImageLuminanceSource(image);  
            Binarizer binarizer = new HybridBinarizer(source);  
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);  
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();  
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");  
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 對圖像進行解碼  
              
            /* 
             * 獲得二維碼中的字符串內容 
             */  
            //String context = result.getText();  
              
            JSONObject content = JSONObject.parseObject(result.getText());  
            System.out.println("圖片中內容:  ");  
            System.out.println("author: " + content.getString("author"));  
            System.out.println("zxing:  " + content.getString("zxing"));  
            System.out.println("圖片中格式:  ");  
            System.out.println("encode: " + result.getBarcodeFormat());  
        } catch (IOException e) {  
            e.printStackTrace();  
        } catch (NotFoundException e) {  
            e.printStackTrace();  
        }  
    }  
}

二、第二種形式,生成有logo的二維碼,工具類以下apache

package com.wang.qr.code.utils;  
  
import java.awt.Graphics2D;  
import java.awt.Image;  
import java.awt.image.BufferedImage;  
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
import java.util.Hashtable;  
  
import javax.imageio.ImageIO;  
  
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;  
  
/** 
 * 生成普通二維碼和生成帶logo的二維碼 
 *  
 * @author wang 
 *  
 */  
public class QRCodeTestUtil3 {  
  
    private static final int BLACK = 0xFF000000;  
    private static final int WHITE = 0xFFFFFFFF;  
  
    /** 
     * 生成普通沒有logo的二維碼 
     *  
     * @param filePath 
     *            文本文件路徑,該文件中的內容是生成二維碼圖片中的內容(文本需以UTF-8) 
     * @param imgFormate 
     *            指定生成的二維碼圖片的後綴名 
     * @param width 
     *            指定生成的二維碼圖片的寬度 
     * @param height 
     *            指定生成的二維碼圖片的高度 
     */  
    public static void createTwoDimensionalCode(String filePath, String imgFormate, int width, int height) {  
        File file = new File(filePath);  
        StringBuffer contents = new StringBuffer("");  
        // 讀取文本文件內容到 contents  
        try {  
            InputStream is = new FileInputStream(file);  
            InputStreamReader isr = new InputStreamReader(is);  
            BufferedReader br = new BufferedReader(isr);  
            try {  
                String temp = br.readLine();  
                while (temp != null) {  
                    contents.append(temp + "\r\n");  
                    temp = br.readLine();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        }  
        // 獲得圖片該存放路徑  
        String imgPath = file.getParent();  
        // 獲得文件該設置的名字  
        String imgName = file.getName();  
        int endIndex = imgName.lastIndexOf(".");  
        imgName = imgName.substring(0, endIndex);  
  
        File imageFile = new File(imgPath, imgName + "." + imgFormate);  
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();  
        // 指定糾錯等級  
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);  
        // 指定編碼格式  
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
        try {  
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents.toString(), BarcodeFormat.QR_CODE, width,  
                    height, hints);  
            MatrixToImageWriter.writeToPath(bitMatrix, imgFormate, imageFile.toPath());  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 生成帶logo的二維碼圖片 
     *  
     * @param url 
     *            要生成二維碼的url 
     * @param imgPath 
     *            二維碼生成的絕對路徑 
     * @param logoPath 
     *            二維碼中間logo絕對地址 
     * @throws Exception 
     */  
    public static void get2CodeImage(String url, String imgPath, String logoPath) throws Exception {  
        String format = "png";  
        Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();  
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");  
        BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 300, 300, hints);  
        File qrcodeFile = new File(imgPath);  
        writeToFile(bitMatrix, format, qrcodeFile, logoPath);  
    }  
  
    /** 
     *  
     * @param matrix 
     *            二維碼矩陣相關 
     * @param format 
     *            二維碼圖片格式 
     * @param file 
     *            二維碼圖片文件 
     * @param logoPath 
     *            logo路徑 
     * @throws IOException 
     */  
    private static void writeToFile(BitMatrix matrix, String format, File file, String logoPath) throws IOException {  
        BufferedImage image = toBufferedImage(matrix);  
        Graphics2D gs = image.createGraphics();  
  
        // 載入logo  
        Image img = ImageIO.read(new File(logoPath));  
        gs.drawImage(img, 125, 125, null);  
        gs.dispose();  
        img.flush();  
        if (!ImageIO.write(image, format, file)) {  
            throw new IOException("Could not write an image of format " + format + " to " + file);  
        }  
    }  
  
    private static BufferedImage toBufferedImage(BitMatrix matrix) {  
        int width = matrix.getWidth();  
        int height = matrix.getHeight();  
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  
        for (int x = 0; x < width; x++) {  
            for (int y = 0; y < height; y++) {  
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);  
            }  
        }  
        return image;  
    }  
}

測試類:json

package com.wang.qr.code;  
  
import org.junit.Test;  
  
import com.wang.qr.code.utils.QRCodeTestUtil3;  
  
/** 
 * @author wang 
 *  
 */  
public class QRCodeTest3 {  
  
    @Test  
    public void createNoLogoQRCode() {  
        QRCodeTestUtil3.createTwoDimensionalCode("E://test.txt", "png", 200, 200);  
    }  
  
    @Test  
    public void createHaveLogoQRCode() {  
        try {  
            QRCodeTestUtil3.get2CodeImage("https://shop100133013.taobao.com/shop/view_shop.htm?spm=a1z0k.7386009.1997989141.d4915209.abFEJh&shop_id=100133013", "E://havalogoQRCode.png", "E://logo.png");  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

效果圖:(一張有用的二維碼,不信能夠用微信掃掃哦。。。)canvas

在聯繫的時候,我是用的maven工程,附上maven工程的pom文件:微信

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    <modelVersion>4.0.0</modelVersion>  
  
    <groupId>QRCodeTest</groupId>  
    <artifactId>QRCodeTest</artifactId>  
    <version>0.0.1-SNAPSHOT</version>  
    <packaging>jar</packaging>  
  
    <name>QRCodeTest</name>  
    <url>http://maven.apache.org</url>  
  
    <properties>  
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
    </properties>  
  
    <dependencies>  
        <dependency>  
            <groupId>junit</groupId>  
            <artifactId>junit</artifactId>  
            <version>4.10</version>  
            <scope>test</scope>  
        </dependency>  
          
        <dependency>  
            <groupId>com.google.zxing</groupId>  
            <artifactId>core</artifactId>  
            <version>3.2.1</version>  
        </dependency>  
        <dependency>  
            <groupId>com.google.zxing</groupId>  
            <artifactId>javase</artifactId>  
            <version>3.2.1</version>  
        </dependency>  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>fastjson</artifactId>  
            <version>1.2.7</version>  
        </dependency>  
          
          
    </dependencies>  
</project>

2、第二個練習的是寫了一個Android的應用程序,可以根據填寫內容,和是否選擇二維碼logo,生成一個二維碼;可以像微信同樣掃描二維碼(在網上找到的demo代碼直接用的),app

Android上生成二維碼與javase生成二維碼的核心代碼原理同樣,都是zxing,可是有不同的地方,javase生成二維碼後,可以直 接在本地保存二維碼文件。Android應用程序這樣的話就不要友好了,咱們應該先將二維碼生成bitmap的形式,而後顯示在imageView上面, 由使用者選擇是否保存二維碼,就像下面的界面同樣,maven

這樣的話,生成二維碼的代碼就不同了。下面是在Android中生成二維碼bitmap的代碼:

package com.wang.qrcodecreateandscantool.util;  
  
import android.graphics.Bitmap;  
import android.graphics.Canvas;  
  
import com.google.zxing.BarcodeFormat;  
import com.google.zxing.EncodeHintType;  
import com.google.zxing.MultiFormatWriter;  
import com.google.zxing.common.BitMatrix;  
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;  
  
import java.util.Hashtable;  
  
/** 
 * 生成二維碼的工具類 
 * <p/> 
 * Created by wang on 2015/11/12. 
 */  
public class QRCodeCreateUtil {  
  
    /** 
     * 生成沒有logo的二維碼Bitmap 
     * 
     * @param context   二維碼內容 
     * @param widthPix  二維碼寬度 
     * @param heightPix 二維碼高度 
     * @return Bitmap 
     */  
    public static Bitmap createNoLogoQRCode(String context, int widthPix, int heightPix) {  
        Bitmap bitmap = null;  
        try {  
            Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();  
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);  
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
            BitMatrix bitMatrix = new MultiFormatWriter().encode(context, BarcodeFormat.QR_CODE, widthPix, heightPix, hints);  
            int[] pixels = new int[widthPix * heightPix];  
            for (int y = 0; y < heightPix; y++) {  
                for (int x = 0; x < widthPix; x++) {  
                    if (bitMatrix.get(x, y)) {  
                        pixels[y * widthPix + x] = 0xff000000;  
                    } else {  
                        pixels[y * widthPix + x] = 0xffffffff;  
                    }  
                }  
            }  
            bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);  
            bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return bitmap;  
    }  
  
    /** 
     * 生成有logo的二維碼Bitmap 
     * 
     * @param context   二維碼內容 
     * @param widthPix  二維碼寬度 
     * @param heightPix 二維碼高度 
     * @param logo      二維碼logo的bitmap 
     * @return Bitmap 
     */  
    public static Bitmap createHaveLogoQRCode(String context, int widthPix, int heightPix, Bitmap logo) {  
  
        Bitmap haveLogoQRCodeBitmap = null;  
        Bitmap noLogoQRCodeBitmap = createNoLogoQRCode(context, widthPix, heightPix);  
        haveLogoQRCodeBitmap = addLogo(noLogoQRCodeBitmap, logo);  
        return haveLogoQRCodeBitmap;  
    }  
  
  
    /** 
     * 向原來的bitmap上面添加一個bitmap 
     * 
     * @param src  原始Bitmap 
     * @param logo 添加的Bitmap 
     * @return Bitmap 
     */  
    private static Bitmap addLogo(Bitmap src, Bitmap logo) {  
        if (src == null) {  
            return null;  
        }  
        if (logo == null) {  
            return src;  
        }  
        int srcWidth = src.getWidth();  
        int srcHeight = src.getHeight();  
        int logoWidth = logo.getWidth();  
        int logoHeight = logo.getHeight();  
        if (srcWidth == 0 || srcHeight == 0) {  
            return null;  
        }  
        if (logoWidth == 0 || logoHeight == 0) {  
            return src;  
        }  
        float scaleFactor = srcWidth * 1.0f / 8 / logoWidth;  
        Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);  
        try {  
            Canvas canvas = new Canvas(bitmap);  
            canvas.drawBitmap(src, 0, 0, null);  
            canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);  
            canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);  
  
            canvas.save(Canvas.ALL_SAVE_FLAG);  
            canvas.restore();  
        } catch (Exception e) {  
            bitmap = null;  
            e.getStackTrace();  
        }  
        return bitmap;  
    }  
}

相信有點Android基礎的猿們都會使用上面的代碼了,就不給使用代碼了。

這個Android應用程序還可以像微信同樣掃描二維碼,就行下面同樣:


這個功能是抄的,在網上找的示例代碼,一點沒改直接用了。。。掃描以後,可以對二維碼的內容進行解析,顯示在一個界面上。

這個Android應用程序是用Android studio建立的。

相關文章
相關標籤/搜索