springBoot二維碼生成案例
阿新 • • 發佈:2018-12-19
1.首先引入谷歌開源專案依賴:
<!-- 二維碼支援包 --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>net.glxn</groupId> <artifactId>qrgen</artifactId> <version>1.4</version> </dependency>
2.二維碼生成解析工具類:
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.util.*; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.Binarizer; import com.google.zxing.BinaryBitmap; 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.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; /** * 二維碼生成解析工具類 * * @data 2018-11-2 10:23:14 */ public class QRCodeUtil { // 二維碼顏色==黑色 private static final int BLACK = 0xFF000000; // 二維碼顏色==白色 private static final int WHITE = 0xFFFFFFFF; // 二維碼圖片格式==jpg和png兩種 private static final List<String> IMAGE_TYPE = new ArrayList<>(); static { IMAGE_TYPE.add("jpg"); IMAGE_TYPE.add("png"); } /** * zxing方式生成二維碼 * 注意: * 1,文字生成二維碼的方法獨立出來,返回image流的形式,可以輸出到頁面 * 2,設定容錯率為最高,一般容錯率越高,圖片越不清晰, 但是隻有將容錯率設定高一點才能相容logo圖片 * 3,logo圖片預設佔二維碼圖片的20%,設定太大會導致無法解析 * * @param content 二維碼包含的內容,文字或網址 * @param path 生成的二維碼圖片存放位置 * @param size 生成的二維碼圖片尺寸 可以自定義或者預設(250) * @param logoPath logo的存放位置 */ public static boolean zxingCodeCreate(String content, String path, Integer size, String logoPath) { try { //圖片型別 String imageType = "jpg"; //獲取二維碼流的形式,寫入到目錄檔案中 BufferedImage image = getBufferedImage(content, size, logoPath); //獲得隨機數 Random random = new Random(); //生成二維碼存放檔案 File file = new File(path+random.nextInt(1000)+".jpg"); if (!file.exists()) { file.mkdirs(); } ImageIO.write(image, imageType, file); return true; } catch (IOException e) { e.printStackTrace(); return false; } } /** * 二維碼流的形式,包含文字內容 * * @param content 二維碼文字內容 * @param size 二維碼尺寸 * @param logoPath logo的存放位置 * @return */ public static BufferedImage getBufferedImage(String content, Integer size, String logoPath) { if (size == null || size <= 0) { size = 250; } BufferedImage image = null; try { // 設定編碼字符集 Map<EncodeHintType, Object> hints = new HashMap<>(); //設定編碼 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //設定容錯率最高 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints.put(EncodeHintType.MARGIN, 1); // 1、生成二維碼 MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints); // 2、獲取二維碼寬高 int codeWidth = bitMatrix.getWidth(); int codeHeight = bitMatrix.getHeight(); // 3、將二維碼放入緩衝流 image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB); for (int i = 0; i < codeWidth; i++) { for (int j = 0; j < codeHeight; j++) { // 4、迴圈將二維碼內容定入圖片 image.setRGB(i, j, bitMatrix.get(i, j) ? BLACK : WHITE); } } //判斷是否寫入logo圖片 if (logoPath != null && !"".equals(logoPath)) { File logoPic = new File(logoPath); if (logoPic.exists()) { Graphics2D g = image.createGraphics(); BufferedImage logo = ImageIO.read(logoPic); int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10) : logo.getWidth(null); int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10) : logo.getHeight(null); int x = (image.getWidth() - widthLogo) / 2; int y = (image.getHeight() - heightLogo) / 2; // 開始繪製圖片 g.drawImage(logo, x, y, widthLogo, heightLogo, null); g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15); //邊框寬度 g.setStroke(new BasicStroke(2)); //邊框顏色 g.setColor(Color.WHITE); g.drawRect(x, y, widthLogo, heightLogo); g.dispose(); logo.flush(); image.flush(); } } } catch (WriterException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return image; } /** * 給二維碼圖片新增Logo * * @param qrPic 二維碼圖片 * @param logoPic logo圖片 * @param path 合成後的圖片儲存目錄 */ public static boolean zxingCodeCreate(File qrPic, File logoPic, String path) { try { String imageType = path.substring(path.lastIndexOf(".") + 1).toLowerCase(); if (!IMAGE_TYPE.contains(imageType)) { return false; } if (!qrPic.isFile() && !logoPic.isFile()) { return false; } //讀取二維碼圖片,並構建繪圖物件 BufferedImage image = ImageIO.read(qrPic); Graphics2D g = image.createGraphics(); //讀取Logo圖片 BufferedImage logo = ImageIO.read(logoPic); //設定logo的大小,最多20%0 int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10) : logo.getWidth(null); int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10) : logo.getHeight(null); // 計算圖片放置位置,預設在中間 int x = (image.getWidth() - widthLogo) / 2; int y = (image.getHeight() - heightLogo) / 2; // 開始繪製圖片 g.drawImage(logo, x, y, widthLogo, heightLogo, null); g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15); //邊框寬度 g.setStroke(new BasicStroke(2)); //邊框顏色 g.setColor(Color.WHITE); g.drawRect(x, y, widthLogo, heightLogo); g.dispose(); logo.flush(); image.flush(); File newFile = new File(path); if (!newFile.exists()) { newFile.mkdirs(); } ImageIO.write(image, imageType, newFile); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * 二維碼的解析方法 * * @param path 二維碼圖片目錄 * @return */ public static Result zxingCodeAnalyze(String path) { try { MultiFormatReader formatReader = new MultiFormatReader(); File file = new File(path); if (file.exists()) { BufferedImage image = ImageIO.read(file); LuminanceSource source = new BufferedImageLuminanceSource(image); Binarizer binarizer = new HybridBinarizer(source); BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); Result result = formatReader.decode(binaryBitmap, hints); return result; } } catch (IOException e) { e.printStackTrace(); } catch (NotFoundException e) { e.printStackTrace(); } return null; } }
3.前端控制器呼叫測試:
import com.google.zxing.Result; import com.zenithink.demo.utils.QRCodeUtil; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 二維碼呼叫前端控制器 */ @RequestMapping("/Qrcode") @RestController public class QrcodeController { /** * 生成二維碼 */ @GetMapping public void productcode() { QRCodeUtil.zxingCodeCreate("http://www.baidu.com", "D:/voice/picture/2018/",500,"D:/voice/picture/2018/5.jpg"); } /** * 解析二維碼 */ @GetMapping("/test") public void analysiscode() { Result result = QRCodeUtil.zxingCodeAnalyze("D:/voice/picture/2018/759.jpg"); System.err.println("二維碼解析內容:"+result.toString()); } }
4.預覽生成結果(若是網址,直接可以掃碼訪問):