1. 程式人生 > >【java】google的zxing架包生成二維碼和讀取二維碼【可帶文字和logo】

【java】google的zxing架包生成二維碼和讀取二維碼【可帶文字和logo】

oms cga dispose framework 增加 span 記錄 ora obj

承接RC4生成不重復字符串的需求之後,因為優惠碼要方便用戶使用的緣故,所以思來想去,覺得還是直接生成二維碼給用戶直接掃比較實用,也不用用戶專門記錄冗長的優惠碼編號。

========================================================

所以這一章,就先把java生成二維碼【可帶logo和文字】做一記錄,使用google的工具包zxing

========================================================

1.maven依賴

<!-- google提供二維碼生成和解析https://mvnrepository.com/artifact/com.google.zxing/core 
--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.2</version> </dependency>

2.完整代碼

技術分享圖片
package testExample;

import java.awt.Color;
import java.awt.Font;
import
java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.*; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.*; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.QRCodeReader; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import org.springframework.util.StringUtils; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /** * 二維碼工具類 * @author SXD * @Date 2018.2.1 * */ public class QR_Code { private static int BLACK = 0x000000; private static int WHITE = 0xFFFFFF; /** * 內部類,設置二維碼相關參數 */ @Data(staticConstructor = "of") @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class CodeModel { /** * 正文 */ private String contents; /** * 二維碼寬度 */ private int width = 400; /** * 二維碼高度 */ private int height = 400; /** * 圖片格式 */ private String format = "png"; /** * 編碼方式 */ private String character_set = "utf-8"; /** * 字體大小 */ private int fontSize = 12; /** * logo */ private File logoFile; /** * logo所占二維碼比例 */ private float logoRatio = 0.20f; /** * 二維碼下文字 */ private String desc; private int whiteWidth;//白邊的寬度 private int[] bottomStart;//二維碼最下邊的開始坐標 private int[] bottomEnd;//二維碼最下邊的結束坐標 } /** * 1.創建最原始的二維碼圖片 * @param info * @return */ private BufferedImage createCodeImage(CodeModel info){ String contents = StringUtils.isEmpty(info.getContents()) ? "暫無內容" : info.getContents();//獲取正文 int width = info.getWidth();//寬度 int height = info.getHeight();//高度 Map<EncodeHintType, Object> hint = new HashMap<>(); hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//設置二維碼的糾錯級別【級別分別為M L H Q ,H糾錯能力級別最高,約可糾錯30%的數據碼字】 hint.put(EncodeHintType.CHARACTER_SET, info.getCharacter_set());//設置二維碼編碼方式【UTF-8】 hint.put(EncodeHintType.MARGIN, 0); MultiFormatWriter writer = new MultiFormatWriter(); BufferedImage img = null; try { //構建二維碼圖片 //QR_CODE 一種矩陣二維碼 BitMatrix bm = writer.encode(contents, BarcodeFormat.QR_CODE, width, height, hint); int[] locationTopLeft = bm.getTopLeftOnBit(); int[] locationBottomRight = bm.getBottomRightOnBit(); info.setBottomStart(new int[]{locationTopLeft[0], locationBottomRight[1]}); info.setBottomEnd(locationBottomRight); int w = bm.getWidth(); int h = bm.getHeight(); img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); for(int x=0;x<w;x++){ for(int y=0;y<h;y++){ img.setRGB(x, y, bm.get(x, y) ? BLACK : WHITE); } } } catch (WriterException e) { e.printStackTrace(); } return img; } /** * 2.為二維碼增加logo和二維碼下文字 * logo--可以為null * 文字--可以為null或者空字符串"" * @param info * @param output */ private void dealLogoAndDesc(CodeModel info, OutputStream output){ //獲取原始二維碼圖片 BufferedImage bm = createCodeImage(info); //獲取Logo圖片 File logoFile = info.getLogoFile(); int width = bm.getWidth(); int height = bm.getHeight(); Graphics g = bm.getGraphics(); //處理logo if(logoFile!=null && logoFile.exists()){ try{ BufferedImage logoImg = ImageIO.read(logoFile); int logoWidth = logoImg.getWidth(); int logoHeight = logoImg.getHeight(); float ratio = info.getLogoRatio();//獲取Logo所占二維碼比例大小 if(ratio>0){ logoWidth = logoWidth>width*ratio ? (int)(width*ratio) : logoWidth; logoHeight = logoHeight>height*ratio ? (int)(height*ratio) : logoHeight; } int x = (width-logoWidth)/2; int y = (height-logoHeight)/2; //根據logo 起始位置 和 寬高 在二維碼圖片上畫出logo g.drawImage(logoImg, x, y, logoWidth, logoHeight, null); }catch(Exception e){ e.printStackTrace(); } } //處理二維碼下文字 String desc = info.getDesc(); if(!StringUtils.isEmpty(desc)){ try{ //設置文字字體 int whiteWidth = info.getHeight()-info.getBottomEnd()[1]; Font font = new Font("黑體", Font.BOLD, info.getFontSize()); int fontHeight = g.getFontMetrics(font).getHeight(); //計算需要多少行 int lineNum = 1; int currentLineLen = 0; for(int i=0;i<desc.length();i++){ char c = desc.charAt(i); int charWidth = g.getFontMetrics(font).charWidth(c); if(currentLineLen+charWidth>width){ lineNum++; currentLineLen = 0; continue; } currentLineLen += charWidth; } int totalFontHeight = fontHeight*lineNum; int wordTopMargin = 4; BufferedImage bm1 = new BufferedImage(width, height+totalFontHeight+wordTopMargin-whiteWidth, BufferedImage.TYPE_INT_RGB); Graphics g1 = bm1.getGraphics(); if(totalFontHeight+wordTopMargin-whiteWidth>0){ g1.setColor(Color.WHITE); g1.fillRect(0, height, width, totalFontHeight+wordTopMargin-whiteWidth); } g1.setColor(new Color(BLACK)); g1.setFont(font); g1.drawImage(bm, 0, 0, null); width = info.getBottomEnd()[0]-info.getBottomStart()[0]; height = info.getBottomEnd()[1]+1; currentLineLen = 0; int currentLineIndex = 0; int baseLo = g1.getFontMetrics().getAscent(); for(int i=0;i<desc.length();i++){ String c = desc.substring(i, i+1); int charWidth = g.getFontMetrics(font).stringWidth(c); if(currentLineLen+charWidth>width){ currentLineIndex++; currentLineLen = 0; g1.drawString(c, currentLineLen + whiteWidth, height+baseLo+fontHeight*(currentLineIndex)+wordTopMargin); currentLineLen = charWidth; continue; } g1.drawString(c, currentLineLen+whiteWidth, height+baseLo+fontHeight*(currentLineIndex) + wordTopMargin); currentLineLen += charWidth; } g1.dispose(); bm = bm1; }catch(Exception e){ e.printStackTrace(); } } try{ ImageIO.write(bm, StringUtils.isEmpty(info.getFormat()) ? info.getFormat() : info.getFormat(), output); }catch(Exception e){ e.printStackTrace(); } } /** * 3.創建 帶logo和文字的二維碼 * @param info * @param file */ public void createCodeImage(CodeModel info, File file){ File parent = file.getParentFile(); if(!parent.exists())parent.mkdirs(); OutputStream output = null; try{ output = new BufferedOutputStream(new FileOutputStream(file)); dealLogoAndDesc(info, output); output.flush(); }catch(Exception e){ e.printStackTrace(); }finally{ try { output.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 3.創建 帶logo和文字的二維碼 * @param info * @param filePath */ public void createCodeImage(CodeModel info, String filePath){ createCodeImage(info, new File(filePath)); } /** * 4.創建 帶logo和文字的二維碼 * @param filePath */ public void createCodeImage(String contents,String filePath){ CodeModel codeModel = new CodeModel(); codeModel.setContents(contents); createCodeImage(codeModel, new File(filePath)); } /** * 5.讀取 二維碼 獲取二維碼中正文 * @param input * @return */ public String decode(InputStream input){ Map<DecodeHintType, Object> hint = new HashMap<DecodeHintType, Object>(); hint.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE); String result = ""; try{ BufferedImage img = ImageIO.read(input); int[] pixels = img.getRGB(0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth()); LuminanceSource source = new RGBLuminanceSource(img.getWidth(), img.getHeight(), pixels); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); QRCodeReader reader = new QRCodeReader(); Result r = reader.decode(bitmap, hint); result = r.getText(); }catch(Exception e){ result="讀取錯誤"; } return result; } }
View Code

3.測試一下

技術分享圖片
    @Test
    public void getUUid(){
        String ss = RC4.RC4();
        System.out.println(ss);

        QR_Code code = new QR_Code();
//        Code.CodeModel codeModel = code.new CodeModel();
//        codeModel.setContents(ss);
//        codeModel.setWidth(400);
//        codeModel.setHeight(400);
//        codeModel.setFontSize(15);
//        codeModel.setLogoFile(new File("G:/ACODE/29936672.jpg"));
//        codeModel.setDesc("國大金象大藥房優惠碼");

        code.createCodeImage(ss,"G:/ACODE/國大金象大藥房.jpg");
    }
View Code

=======================================================

方法 選取哪個生成都可以 大同小異 大同小異 沒有區別

======================================================

最後,如果想封裝成jar包供別人調用,參考步驟如下:http://www.cnblogs.com/sxdcgaq8080/p/8126770.html

【java】google的zxing架包生成二維碼和讀取二維碼【可帶文字和logo】