前面說過兩種二維碼掃描方式,如今說如何生成自定義酷炫二維碼。二維碼生成須要使用Google開源庫Zxing,Zxing的項目地址:https://github.com/ZBar/ZBar,咱們只須要裏面的jar包:core:x.x.x.jar,建議用core:3.3.0。git
劃重點:github
dependencies {
...
implementation 'com.google.zxing:core:3.3.0'
}
Sync Now
implementation fileTree(dir: 'libs', include: ['*.jar'])
先看簡單的二維碼生成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; } }
主要步驟:數組
主要參數介紹: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; }
參數說明:
這裏就是一個簡單的圖片合成,首先獲取原圖片和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);
效果圖:
什麼意思呢,看圖
就是將二維碼的黑色色塊使用圖片代替,視覺效果就是你的圖片在黑色色塊部分被顯示。
實現方法:
首先經過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