Android生成自定義二維碼

   前面說過兩種二維碼掃描方式,如今說如何生成自定義酷炫二維碼。二維碼生成須要使用Google開源庫Zxing,Zxing的項目地址:https://github.com/ZBar/ZBar,咱們只須要裏面的jar包:core:x.x.x.jar,建議用core:3.3.0。git

劃重點:github

  • 通常二維碼
  • 彩色二維碼
  • 帶logo二維碼或帶logo的彩色二維碼
  • 黑色色塊用圖片代替的二維碼 

1.引入jar包
  • app build.gradle中加入依賴
    dependencies {
        ...
        implementation 'com.google.zxing:core:3.3.0'
    }
  • 若是依賴同步失敗,下載jar包導入libs下,並在app build.gradle中加入以下代碼並Sync Now
    implementation fileTree(dir: 'libs', include: ['*.jar'])

 

2.How ?

  先看簡單的二維碼生成canvas

/**
 * 生成簡單二維碼
 *
 * @param content                字符串內容
 * @param width                  二維碼寬度
 * @param height                 二維碼高度
 * @param character_set          編碼方式(通常使用UTF-8)
 * @param error_correction_level 容錯率 L:7% M:15% Q:25% H:35%
 * @param margin                 空白邊距(二維碼與邊框的空白區域)
 * @param color_black            黑色色塊
 * @param color_white            白色色塊
 * @return BitMap
 */
public static Bitmap createQRCodeBitmap(String content, int width,int height,
                                        String character_set,String error_correction_level,
                                        String margin,int color_black, int color_white) {
    // 字符串內容判空
    if (TextUtils.isEmpty(content)) {
        return null;
    }
    // 寬和高>=0
    if (width < 0 || height < 0) {
        return null;
    }
    try {
        /** 1.設置二維碼相關配置 */
        Hashtable<EncodeHintType, String> hints = new Hashtable<>();
        // 字符轉碼格式設置
        if (!TextUtils.isEmpty(character_set)) {
            hints.put(EncodeHintType.CHARACTER_SET, character_set);
        }
        // 容錯率設置
        if (!TextUtils.isEmpty(error_correction_level)) {
                hints.put(EncodeHintType.ERROR_CORRECTION, error_correction_level);
            }
        // 空白邊距設置
        if (!TextUtils.isEmpty(margin)) {
            hints.put(EncodeHintType.MARGIN, margin);
        }
        /** 2.將配置參數傳入到QRCodeWriter的encode方法生成BitMatrix(位矩陣)對象 */
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

        /** 3.建立像素數組,並根據BitMatrix(位矩陣)對象爲數組元素賦顏色值 */
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //bitMatrix.get(x,y)方法返回true是黑色色塊,false是白色色塊
                if (bitMatrix.get(x, y)) {
                    pixels[y * width + x] = color_black;//黑色色塊像素設置
                } else {
                    pixels[y * width + x] = color_white;// 白色色塊像素設置
                }
            }
        }
        /** 4.建立Bitmap對象,根據像素數組設置Bitmap每一個像素點的顏色值,並返回Bitmap對象 */
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    } catch (WriterException e) {
        e.printStackTrace();
        return null;
    }
 }

 

主要步驟:數組

  • 設置二維碼相關配置,包括傳入的二維碼長寬、容錯率和空白邊距大小。
  • 將配置參數傳入到QRCodeWriter的encode方法並生成BitMatrix(位矩陣)對象。
  • 位矩陣對象中bitMatrix.get(x, y)方法可判斷是黑色色塊仍是白色色塊,根據不一樣色塊給數組元素賦咱們傳入的顏色值
  • 根據像素數組每一個像素點的顏色值建立Bitmap對象並返回,即二維碼

主要參數介紹:app

  • character_set 
    字符集/字符轉碼格式,一般使用UTF-8,格式不對可能致使亂碼。傳null時,默認使用 「ISO-8859-1」工具

  • error_correction_level 
    容錯率,也就是糾錯水平,二維碼破損一部分也能掃碼就歸功於容錯率,容錯率可分爲L、 M、 Q、 H四個等級,其分別佔比爲:L:7% M:15% Q:25% H:35%。傳null時,默認使用 「L」 
    固然容錯率越高,二維碼能存儲的內容也隨之變小。gradle

  • margin 
    二維碼和邊框的空白區域寬度ui

  • color_black、color_white 
    黑色色塊和白素色塊,咱們常見的二維碼通常是黑白兩色的,也就是這兩個色塊,能夠本身傳入兩個顏色,so,彩色二維碼不就實現了。google

 

 調用生成:編碼

createQRCodeBitmap(content, 800, 800,"UTF-8","H", "1", Color.BLACK, Color.WHITE);

        

 黑色色塊用綠色(Color.GREEN)、藍色(Color.BLUE)、黃色(Color.YELLOW)…:

createQRCodeBitmap(content, 800, 800,"UTF-8","H", "1", Color.GREEN, Color.WHITE);
...

           

 

    二維碼生成固然少不了添加logo了,添加logo就是圖片合成,將logo圖片以必定比例合成在原二維碼圖片上。 
    直接看代碼

/**
 * 向二維碼中間添加logo圖片(圖片合成)
 *
 * @param srcBitmap 原圖片(生成的簡單二維碼圖片)
 * @param logoBitmap logo圖片
 * @param logoPercent 百分比 (用於調整logo圖片在原圖片中的顯示大小, 取值範圍[0,1] )                    
 * @return
 */
 private static Bitmap addLogo(Bitmap srcBitmap,  Bitmap logoBitmap, float logoPercent){
    if(srcBitmap == null){
        return null;
    }
    if(logoBitmap == null){
        return srcBitmap;
    }
    //傳值不合法時使用0.2F
    if(logoPercent < 0F || logoPercent > 1F){
        logoPercent = 0.2F;
    }

    /** 1. 獲取原圖片和Logo圖片各自的寬、高值 */
    int srcWidth = srcBitmap.getWidth();
    int srcHeight = srcBitmap.getHeight();
    int logoWidth = logoBitmap.getWidth();
    int logoHeight = logoBitmap.getHeight();

    /** 2. 計算畫布縮放的寬高比 */
    float scaleWidth = srcWidth * logoPercent / logoWidth;
    float scaleHeight = srcHeight * logoPercent / logoHeight;

    /** 3. 使用Canvas繪製,合成圖片 */
    Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawBitmap(srcBitmap, 0, 0, null);
    canvas.scale(scaleWidth, scaleHeight, srcWidth/2, srcHeight/2);
    canvas.drawBitmap(logoBitmap, srcWidth/2 - logoWidth/2, srcHeight/2 - logoHeight/2, null);

    return bitmap;
}

參數說明:

  • srcBitmap:以前生成的簡單二維碼圖片
  • logoBitmap:logo圖片
  • logoPercent :logo圖片所佔的百分比,建議使用0.2F,百分比過大可能致使二維碼掃描失敗。

    這裏就是一個簡單的圖片合成,首先獲取原圖片和logo圖片各自的寬高,經過咱們傳入的百分比計算畫布縮放的寬高比,而後使用Canvas繪製,合成最終帶logo的二維碼。

    爲了方便,咱們在最開始生成簡單二維碼的方法中傳入logo圖片和百分比,在生成Bitmap時添加logo,以下:

/**
 *
 * @param content                字符串內容
 * @param width                  二維碼寬度
 * @param height                 二維碼高度
 * @param character_set          編碼方式(通常使用UTF-8)
 * @param error_correction_level 容錯率 L:7% M:15% Q:25% H:35%
 * @param margin                 空白邊距(二維碼與邊框的空白區域)
 * @param color_black            黑色色塊
 * @param color_white            白色色塊
 * @param logoBitmap             logo圖片
 * @param logoPercent            logo所佔百分比
 * @return
 */
 public static Bitmap createQRCodeBitmap(String content, int width, int height, String character_set, 
                                         String error_correction_level,String margin, int color_black, 
                                         int color_white,Bitmap logoBitmap, float logoPercent) {
    // 字符串內容判空
    if (TextUtils.isEmpty(content)) {
        return null;
    }
    // 寬和高>=0
    if (width < 0 || height < 0) {
        return null;
    }
    try {
        /** 1.設置二維碼相關配置,生成BitMatrix(位矩陣)對象 */
        Hashtable<EncodeHintType, String> hints = new Hashtable<>();
        // 字符轉碼格式設置
        if (!TextUtils.isEmpty(character_set)) {
            hints.put(EncodeHintType.CHARACTER_SET, character_set);
        }
        // 容錯率設置
        if (!TextUtils.isEmpty(error_correction_level)) {
            hints.put(EncodeHintType.ERROR_CORRECTION, error_correction_level);
        }
        // 空白邊距設置
        if (!TextUtils.isEmpty(margin)) {
            hints.put(EncodeHintType.MARGIN, margin);
        }
        /** 2.將配置參數傳入到QRCodeWriter的encode方法生成BitMatrix(位矩陣)對象 */
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

        /** 3.建立像素數組,並根據BitMatrix(位矩陣)對象爲數組元素賦顏色值 */
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //bitMatrix.get(x,y)方法返回true是黑色色塊,false是白色色塊
                if (bitMatrix.get(x, y)) {
                    pixels[y * width + x] = color_black;//黑色色塊像素設置
                } else {
                    pixels[y * width + x] = color_white;// 白色色塊像素設置
                }
            }
        }

        /** 4.建立Bitmap對象,根據像素數組設置Bitmap每一個像素點的顏色值,並返回Bitmap對象 */
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

        /** 5.爲二維碼添加logo圖標 */
        if(logoBitmap != null){
            return addLogo(bitmap, logoBitmap, logoPercent);
        }
        return bitmap;
    } catch (WriterException e) {
        e.printStackTrace();
        return null;
    }
}

調用:

createQRCodeBitmap(content, 800, 800,"UTF-8","H", "1", Color.BLACK, Color.WHITE,logoBitmap,0.2F);

 

logo圖片須要轉爲Bitmap格式傳入,將項目資源下的圖片轉爲Bitmap可以使用以下方法

Resources res = getResources();
Bitmap logoBitmap= BitmapFactory.decodeResource(res,R.mipmap.logo);

 

效果圖: 

            

 

4.使用圖片代替黑色色塊

    什麼意思呢,看圖

           

 

    就是將二維碼的黑色色塊使用圖片代替,視覺效果就是你的圖片在黑色色塊部分被顯示。 
實現方法: 
    首先經過Bitmap的createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)方法從當前位圖,按必定的比例建立一個新的位圖,該方法須要傳入四個參數,第一個參數就是當前圖片,第二個和第三個參數是新位圖長寬(這裏傳入二維碼的長寬,保證圖的大小同樣),最後一個參數直接傳false。

Bitmap bitmap_black = Bitmap.createScaledBitmap(bitmap_black, width, height, false);

 

 建立好新位圖後,在根據BitMatrix(位矩陣)對象爲數組元素賦顏色值時,將黑色色塊換爲新位圖的像素。

if (bitMatrix.get(x, y)) {// 黑色色塊像素設置
    if(bitmap_black != null) {//圖片不爲null,則將黑色色塊換爲新位圖的像素。
       pixels[y * width + x] = bitmap_black.getPixel(x, y);
    } else {
       pixels[y * width + x] = color_black;
    }
} else {
     pixels[y * width + x] = color_white;// 白色色塊像素設置
}

 注:儘可能選用深色圖片,不然影響掃描精度。

 

 代碼以下:

/**
 *  生成自定義二維碼
 *
 * @param content                字符串內容
 * @param width                  二維碼寬度
 * @param height                 二維碼高度
 * @param character_set          編碼方式(通常使用UTF-8)
 * @param error_correction_level 容錯率 L:7% M:15% Q:25% H:35%
 * @param margin                 空白邊距(二維碼與邊框的空白區域)
 * @param color_black            黑色色塊
 * @param color_white            白色色塊
 * @param logoBitmap             logo圖片(傳null時不添加logo)
 * @param logoPercent            logo所佔百分比
 * @param bitmap_black           用來代替黑色色塊的圖片(傳null時不代替)
 * @return
 */
public static Bitmap createQRCodeBitmap(String content, int width, int height, String character_set, String error_correction_level,
                                            String margin, int color_black, int color_white, Bitmap logoBitmap, float logoPercent, Bitmap bitmap_black) {
    // 字符串內容判空
    if (TextUtils.isEmpty(content)) {
        return null;
    }
    // 寬和高>=0
    if (width < 0 || height < 0) {
        return null;
    }
    try {
        /** 1.設置二維碼相關配置,生成BitMatrix(位矩陣)對象 */
        Hashtable<EncodeHintType, String> hints = new Hashtable<>();
        // 字符轉碼格式設置
        if (!TextUtils.isEmpty(character_set)) {
            hints.put(EncodeHintType.CHARACTER_SET, character_set);
        }
        // 容錯率設置
        if (!TextUtils.isEmpty(error_correction_level)) {
                hints.put(EncodeHintType.ERROR_CORRECTION, error_correction_level);
        }
        // 空白邊距設置
        if (!TextUtils.isEmpty(margin)) {
            hints.put(EncodeHintType.MARGIN, margin);
        }
        /** 2.將配置參數傳入到QRCodeWriter的encode方法生成BitMatrix(位矩陣)對象 */
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);

        /** 3.建立像素數組,並根據BitMatrix(位矩陣)對象爲數組元素賦顏色值 */
        if (bitmap_black != null) {
            //從當前位圖按必定的比例建立一個新的位圖
            bitmap_black = Bitmap.createScaledBitmap(bitmap_black, width, height, false);
        }
        int[] pixels = new int[width * height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //bitMatrix.get(x,y)方法返回true是黑色色塊,false是白色色塊
                if (bitMatrix.get(x, y)) {// 黑色色塊像素設置
                    if (bitmap_black != null) {//圖片不爲null,則將黑色色塊換爲新位圖的像素。
                        pixels[y * width + x] = bitmap_black.getPixel(x, y);
                    } else {
                        pixels[y * width + x] = color_black;
                    }
                } else {
                    pixels[y * width + x] = color_white;// 白色色塊像素設置
                }
            }
        }

        /** 4.建立Bitmap對象,根據像素數組設置Bitmap每一個像素點的顏色值,並返回Bitmap對象 */
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);

        /** 5.爲二維碼添加logo圖標 */
        if (logoBitmap != null) {
            return addLogo(bitmap, logoBitmap, logoPercent);
        }
        return bitmap;
    } catch (WriterException e) {
        e.printStackTrace();
        return null;
    }
}

 

 源碼已上傳至GitHub:https://github.com/yangxch/GenerateQRCode 

 生成二維碼方法我放到了一個工具類,調用時若是不須要logo或不須要用圖片代替黑色色塊,傳nulll 便可。 
 固然圖片不能直接寫死,能夠拍照或相冊選擇,生成二維碼還可保存至手機或分享給他人,實現方式後續更新,敬請關注。 

          

 

 


更多技術乾貨,歡迎關注個人公衆號:ChaoYoung 

相關文章
相關標籤/搜索