1.工具類 package com.test.test.utils; import com.google.zxing.*; 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; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.font.FontDesignMetrics; import sun.misc.BASE64Encoder; import javax.imageio.ImageIO; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.OutputStream; import java.util.Hashtable; public class QRCodeUtilEx { private static Logger logger = LoggerFactory.getLogger(QRCodeUtilEx.class); private static final String CHARSET = "utf-8"; private static final String FORMAT_NAME = "JPG"; // 二維碼尺寸 private static final int QRCODE_SIZE = 300; // LOGO寬度 private static final int WIDTH = 60; // LOGO高度 private static final int HEIGHT = 60; // 字體大小 private static final int FONT_SIZE = 18; private static BufferedImage createImage(String content, String bottomDes, String imgPath, boolean needCompress) throws Exception { Hashtable hints = new Hashtable(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints.put(EncodeHintType.CHARACTER_SET, CHARSET); hints.put(EncodeHintType.MARGIN, 1); BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints); int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); int tempHeight = height; boolean needDescription = (null != bottomDes && !"".equals(bottomDes)); if (needDescription) { tempHeight += 30; } BufferedImage image = new BufferedImage(width, tempHeight, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } // 插入圖片 if (imgPath != null && !"".equals(imgPath)) { QRCodeUtilEx.insertImage(image, imgPath, needCompress); } //添加底部文字 if (needDescription) { QRCodeUtilEx.addFontImage(image, bottomDes); } return image; } /** * 添加 底部圖片文字 * * @param source 圖片源 * @param declareText 文字本文 */ private static void addFontImage(BufferedImage source, String declareText) { BufferedImage textImage = strToImage(declareText, QRCODE_SIZE, 50); Graphics2D graph = source.createGraphics(); //開啓文字抗鋸齒 graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); int width = textImage.getWidth(null); int height = textImage.getHeight(null); Image src = textImage; graph.drawImage(src, 0, QRCODE_SIZE - 20, width, height, null); graph.dispose(); } private static BufferedImage strToImage(String str, int width, int height) { BufferedImage textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D)textImage.getGraphics(); //開啓文字抗鋸齒 g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2.setBackground(Color.WHITE); g2.clearRect(0, 0, width, height); g2.setPaint(Color.BLACK); FontRenderContext context = g2.getFontRenderContext(); Font font = new Font("微軟雅黑", Font.BOLD, FONT_SIZE); g2.setFont(font); LineMetrics lineMetrics = font.getLineMetrics(str, context); FontMetrics fontMetrics = FontDesignMetrics.getMetrics(font); float offset = (width - fontMetrics.stringWidth(str)) / 2; float y = (height + lineMetrics.getAscent() - lineMetrics.getDescent() - lineMetrics.getLeading()) / 2; g2.drawString(str, (int)offset, (int)y); return textImage; } private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception { File file = new File(imgPath); if (!file.exists()) { System.err.println("" + imgPath + " 該文件不存在!"); return; } Image src = ImageIO.read(new File(imgPath)); int width = src.getWidth(null); int height = src.getHeight(null); if (needCompress) { // 壓縮LOGO if (width > WIDTH) { width = WIDTH; } if (height > HEIGHT) { height = HEIGHT; } Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH); BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); g.drawImage(image, 0, 0, null); // 繪製縮小後的圖 g.dispose(); src = image; } // 插入LOGO Graphics2D graph = source.createGraphics(); int x = (QRCODE_SIZE - width) / 2; int y = (QRCODE_SIZE - height) / 2; graph.drawImage(src, x, y, width, height, null); Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6); graph.setStroke(new BasicStroke(3f)); graph.draw(shape); graph.dispose(); } public static void encode(String content, String bottomDes, String imgPath, String destPath, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtilEx.createImage(content, bottomDes, imgPath, needCompress); mkdirs(destPath); // String file = new Random().nextInt(99999999)+".jpg"; // ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file)); ImageIO.write(image, FORMAT_NAME, new File(destPath)); } //獲取二維碼base64數據 public static String encodeStr(String content, String bottomDes) throws Exception{ BufferedImage image = QRCodeUtilEx.createImage(content, bottomDes, null, false); ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流 ImageIO.write(image, FORMAT_NAME,baos);//寫入流中 byte[] bytes = baos.toByteArray();//轉換成字節 BASE64Encoder encoder = new BASE64Encoder(); String jpg_base64 = encoder.encodeBuffer(bytes).trim();//轉換成base64串 jpg_base64 = jpg_base64.replaceAll("\n", "").replaceAll("\r", "");//刪除 \r\n //System.out.println("值爲:"+"data:image/jpg;base64,"+png_base64); return jpg_base64; } public static BufferedImage encode(String content, String bottomDes, String imgPath, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtilEx.createImage(content, bottomDes, imgPath, needCompress); return image; } public static void mkdirs(String destPath) { File file = new File(destPath); // 當文件夾不存在時,mkdirs會自動創建多層目錄,區別於mkdir.(mkdir如果父目錄不存在則會拋出異常) if (!file.exists() && !file.isDirectory()) { file.mkdirs(); } } public static void encode(String content, String bottomDes, String imgPath, String destPath) throws Exception { QRCodeUtilEx.encode(content, bottomDes, imgPath, destPath, false); } // 被註釋的方法 /* * public static void encode(String content, String destPath, boolean * needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath, * needCompress); } */ public static void encode(String content, String bottomDes, String destPath) throws Exception { QRCodeUtilEx.encode(content, bottomDes, null, destPath, false); } public static void encode(String content, String bottomDes, String imgPath, OutputStream output, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtilEx.createImage(content, bottomDes, imgPath, needCompress); ImageIO.write(image, FORMAT_NAME, output); } public static void encode(String content, String bottomDes, OutputStream output) throws Exception { QRCodeUtilEx.encode(content, bottomDes, null, output, false); } public static String decode(File file) throws Exception { BufferedImage image; image = ImageIO.read(file); if (image == null) { return null; } BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Result result; Hashtable hints = new Hashtable(); hints.put(DecodeHintType.CHARACTER_SET, CHARSET); result = new MultiFormatReader().decode(bitmap, hints); String resultStr = result.getText(); return resultStr; } public static String decode(String path) throws Exception { return QRCodeUtilEx.decode(new File(path)); } }
2.調用
package com.test.test.controller; import com.test.test.utils.QRCodeUtilEx; public class QrcodeTest { public static void main(String args[]) { try { String str= QRCodeUtilEx.encodeStr("1233444","測試"); System.out.println(str); } catch (Exception e) { e.printStackTrace(); } } }
參考:
https://blog.csdn.net/qq_36020545/article/details/58653926