Zxing二維碼技術工具類

package com.swft.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/** 
 * @ClassName: QRcodeObject
 * @description: 
 * @author: JTJ
 * @Date: 2019年2月17日 下午1:52:32
 */

public class QRcodeObject {

	public static int width = 600;
	public static int height = 600;
	public static String format = "png";
	
	public static String contents = "默認內容";
	
	public static String defaultFilePath = "";
	
	public static String[] checkList = new String[] {"png","jpg","gif","jepg"};
	
	/**
	 * @Title: createLogoAndCode 
	 * @Desc: 創建二維碼
	 * @param logo contents path
	 * @return
	 */
	public static String createLogoAndCode(File logo, String contents, String path) {
		String result = "success";
		if (!$.stringObj.isEmpty(contents)) {
			QRcodeObject.contents = contents;
		}
		if(!checkFormat(logo)) {
			return "logo文件出錯!";
		}
		// 生成二維碼
		try {	
			BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height,
					setCodeParams());
			if(!$.stringObj.isEmpty(path)) {
				//生成文件路徑
				Path filePath = new File(savePalce(path)).toPath();
				MatrixToImageWriter.writeToPath(bitMatrix, format, filePath);
			}	
			MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
			/* 添加logo圖片
			  *  問題:生成二維碼正常,生成帶logo的二維碼logo變成黑白
                          *  原因:MatrixToImageConfig默認黑白,需要設置BLACK、WHITE
                          *  解決:https://ququjioulai.iteye.com/blog/2254382
			 */
			//判斷是否需要logo
			if(logo!=null) {
				BufferedImage bufferedImage = groupImage(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig),logo);
			    //生成圖片文件
				ImageIO.write(bufferedImage, format, new File(defaultFilePath));
			}else {
				ImageIO.write(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), format, new File(defaultFilePath));
			}
		} catch (Exception e) {
			result = "生成二維碼出錯!"+e.toString();
		}
		return result;
	}
	
	/**
	 * 繪製logo圖片
	 * @param matrixImage
	 * @param logoFile
	 * @return 
	 * @throws IOException
	 */
	public static BufferedImage groupImage(BufferedImage matrixImage, File logoFile) throws IOException {
	    	//先讀取二維碼圖片
	    	
			Graphics2D g = matrixImage.createGraphics();
			
			//再讀取logo圖片
			BufferedImage logoImage = ImageIO.read(logoFile);
			
			//設置logo大小,太大,會覆蓋二維碼,此處20%  
            int logoWidth = logoImage.getWidth() > matrixImage.getWidth()*2 /10 ? (matrixImage.getWidth()*2 /10) : logoImage.getWidth();  
            int logoHeight = logoImage.getHeight() > matrixImage.getHeight()*2 /10 ? (matrixImage.getHeight()*2 /10) : logoImage.getHeight();  
    
            //設置logo圖片放置位置  放在中心  
            int x = (matrixImage.getWidth() - logoWidth) / 2;  
            int y = (matrixImage.getHeight() - logoHeight) / 2;  
           
            //開始合併繪製圖片  
            g.drawImage(logoImage, x, y, logoWidth, logoHeight, null);  
            g.drawRoundRect(x, y, logoWidth, logoHeight, 15 ,15);  
            //線條設置
            BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);   
            g.setStroke(stroke);  
    
            //logo邊框顏色  
            g.setColor(Color.WHITE);  
            g.drawRect(x, y, logoWidth, logoHeight);
            //釋放對象
            g.dispose();  
            logoImage.flush();  
            matrixImage.flush();
            return matrixImage;
	}
	
	/**
	 * @Title: setCodeParams 
	 * @Desc: 設置二維碼參數
	 * @param
	 * @return
	 */
	public static HashMap<EncodeHintType, Object> setCodeParams() {
		// 封裝二維碼的參數
		HashMap<EncodeHintType, Object> hashMap = new HashMap<>();
		hashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 字符集
		hashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); // 糾錯等級
		hashMap.put(EncodeHintType.MARGIN, 2); // 邊距
		return hashMap;
	}

	/**
	 * @Title: savePalce 
	 * @Desc: 二維碼保存地址
	 * @param
	 * @return
	 */
	public static String savePalce(String path) {
		String codeName = UUID.randomUUID().toString() + $.dateObj.Format("YYYY-MM-DD",new Date()).replace("-", "s");
		defaultFilePath = path + codeName.trim() + "." + format;
		return defaultFilePath;
	}
	
	/**
	 * @Title: readCode 
	 * @Desc: 讀取二維碼信息
	 * @param file
	 * @return
	 */
	public static String readCode(File file) {
		String result = "";
		try {
			MultiFormatReader formatReader = new MultiFormatReader();

			BufferedImage image = ImageIO.read(file);

			BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));

			Map<DecodeHintType, Object> hints = new HashMap<>();
			hints.put(DecodeHintType.CHARACTER_SET, "utf-8");// 字符集
			Result decodeResult = formatReader.decode(binaryBitmap, hints);

			result = "解析之後的結果:" + decodeResult.toString() + "\n" + "二維碼格式類型:" + decodeResult.getBarcodeFormat() + "\n"
					+ "二維碼文本內容:" + decodeResult.getText() + "!";
		} catch (Exception e) {
			result = "解析錯誤";
			return result;
		}
		return result;
	}

	/**
	 * @Title: checkFormat 
	 * @Desc: 驗證文件後綴格式
	 * @param logoFile
	 * @return
	 */
	public static boolean checkFormat(File logoFile) {
		//文件是否爲空
		if(null==logoFile) {
			System.out.println("logo文件爲空!");
			return true;
		}
		
		String fileName = logoFile.getName();
		String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
		
		for(String s : checkList) {
			if(s.equalsIgnoreCase(suffix)) {
				return true;
			}
		}
		return false;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章