生成自定義文字的二維碼
阿新 • • 發佈:2019-02-15
程式碼是生產上一直在用的,裡面有main方法,方便大家自己測試;對於引數設定,可根據自身需要進行調整。
pom檔案
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
package com.image; /** * Created by Liuxd on 2018-09-07. */ import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import javax.imageio.ImageIO; import javax.imageio.stream.FileImageOutputStream; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.HashMap; import java.util.Map; /** * 二維碼 */ public class GenerateQrCode { private static final int QRCOLOR = 0xFF000000; //預設是黑色 private static final int BGWHITE = 0xFFFFFFFF; //背景顏色 public static void main(String[] args) { byte[] bytes = GenerateQrCode.getLogoQRCode("https://blog.csdn.net/jiahao1186", "部落格"); //生成一個圖片物件。 byte2image(bytes, "D:/1.jpg"); } public static void byte2image(byte[] data, String path) { if (data.length < 3 || path.equals("")) return; try { FileImageOutputStream imageOutput = new FileImageOutputStream(new File(path)); imageOutput.write(data, 0, data.length); imageOutput.close(); System.out.println("圖片已生成,請按如下地址,查詢圖片:" + path); } catch (Exception ex) { System.out.println("Exception: " + ex); ex.printStackTrace(); } } /** * 生成帶logo的二維碼圖片 */ public static byte[] getLogoQRCode(String qrUrl, String License) { String content = qrUrl; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); FontImage.getImage(License, 65, 65, bos); GenerateQrCode zp = new GenerateQrCode(); BufferedImage bim = zp.getQR_CODEBufferedImage(content, BarcodeFormat.QR_CODE, 258, 258, zp.getDecodeHintType()); return zp.addLogo_QRCode(bim, bos.toByteArray(), new LogoConfig()); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 給二維碼圖片新增Logo * * @param logoPic */ public byte[] addLogo_QRCode(BufferedImage bim, byte[] logoPic, LogoConfig logoConfig) { try { /** * 讀取二維碼圖片,並構建繪圖物件 */ BufferedImage image = bim; Graphics2D g = image.createGraphics(); /** * 讀取Logo圖片 */ ByteArrayInputStream in = new ByteArrayInputStream(logoPic); BufferedImage logo = ImageIO.read(in); /** * 設定logo的大小,本人設定為二維碼圖片的20%,因為過大會蓋掉二維碼 */ int widthLogo = logo.getWidth(null) > image.getWidth() * 3 / 10 ? (image.getWidth() * 3 / 10) : logo.getWidth(null); int heightLogo = logo.getHeight(null) > image.getHeight() * 3 / 10 ? (image.getHeight() * 3 / 10) : logo.getWidth(null); /** * logo放在中心 */ int x = (image.getWidth() - widthLogo) / 2; int y = (image.getHeight() - heightLogo) / 2; /** * logo放在右下角 * int x = (image.getWidth() - widthLogo); * int y = (image.getHeight() - heightLogo); */ //開始繪製圖片 g.drawImage(logo, x, y, widthLogo, heightLogo, null); g.dispose(); logo.flush(); image.flush(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.flush(); ImageIO.write(image, "png", baos); //二維碼生成的路徑,但是實際專案中,我們是把這生成的二維碼顯示到介面上的,因此下面的折行程式碼可以註釋掉 //可以看到這個方法最終返回的是這個二維碼的imageBase64字串 //前端用 <img src="data:image/png;base64,${imageBase64QRCode}"/> 其中${imageBase64QRCode}對應二維碼的imageBase64字串 // ImageIO.write(image, "png", new File("/Users/zhanglei/Downloads/" + new Date().getTime() + "test.png")); //TODO // // String imageBase64QRCode = Base64.encodeBase64URLSafeString(baos.toByteArray()); // baos.close(); return baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 構建初始化二維碼 * * @param bm * @return */ public BufferedImage fileToBufferedImage(BitMatrix bm) { BufferedImage image = null; try { int w = bm.getWidth(), h = bm.getHeight(); image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { image.setRGB(x, y, bm.get(x, y) ? 0xFF000000 : 0xFFCCDDEE); } } } catch (Exception e) { e.printStackTrace(); } return image; } /** * 生成二維碼bufferedImage圖片 * * @param content 編碼內容 * @param barcodeFormat 編碼型別 * @param width 圖片寬度 * @param height 圖片高度 * @param hints 設定引數 * @return */ public BufferedImage getQR_CODEBufferedImage(String content, BarcodeFormat barcodeFormat, int width, int height, Map<EncodeHintType, ?> hints) { MultiFormatWriter multiFormatWriter = null; BitMatrix bm = null; BufferedImage image = null; try { multiFormatWriter = new MultiFormatWriter(); // 引數順序分別為:編碼內容,編碼型別,生成圖片寬度,生成圖片高度,設定引數 bm = multiFormatWriter.encode(content, barcodeFormat, width, height, hints); int w = bm.getWidth(); int h = bm.getHeight(); image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); // 開始利用二維碼資料建立Bitmap圖片,分別設為黑(0xFFFFFFFF)白(0xFF000000)兩色 for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE); } } } catch (WriterException e) { e.printStackTrace(); } return image; } /** * 設定二維碼的格式引數 * * @return */ public Map<EncodeHintType, Object> getDecodeHintType() { // 用於設定QR二維碼引數 Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(); // 設定QR二維碼的糾錯級別(H為最高級別)具體級別資訊 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 設定編碼方式 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.MARGIN, 0); hints.put(EncodeHintType.MAX_SIZE, 350); hints.put(EncodeHintType.MIN_SIZE, 100); return hints; } }
package com.image; import javax.imageio.ImageIO; import java.awt.*; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.UUID; /** * 建立文字圖片 * */ public class FontImage { // 預設格式 private static final String FORMAT_NAME = "JPG"; // 預設 寬度 private static final int WIDTH = 100; // 預設 高度 private static final int HEIGHT = 100; /** * 建立圖片 * * @param content 內容 * @param font 字型 * @param width 寬 * @param height 高 * @return */ private static BufferedImage createImage(String content, Font font, Integer width, Integer height) { BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D) bi.getGraphics(); g2.setBackground(Color.WHITE); g2.clearRect(0, 0, width, height); g2.setPaint(Color.BLACK); FontRenderContext context = g2.getFontRenderContext(); Rectangle2D bounds = font.getStringBounds(content, context); double x = (width - bounds.getWidth()) / 2; double y = (height - bounds.getHeight()) / 2; double ascent = -bounds.getY(); double baseY = y + ascent; g2.drawString(content, (int) x, (int) baseY); return bi; } /** * 獲取 圖片 * * @param content 內容 * @param font 字型 * @param width 寬 * @param height 高 * @return */ public static BufferedImage getImage(String content, Font font, Integer width, Integer height) { width = width == null ? WIDTH : width; height = height == null ? HEIGHT : height; if (null == font) font = new Font("宋體", Font.BOLD, 13); return createImage(content, font, width, height); } /** * 獲取 圖片 * * @param content 內容 * @param width 寬 * @param height 高 * @return */ public static BufferedImage getImage(String content, Integer width, Integer height) { return getImage(content, null, width, height); } /** * 獲取圖片 * * @param content 內容 * @return */ public static BufferedImage getImage(String content) { return getImage(content, null, null); } /** * 獲取圖片 * * @param content 內容 * @param font 字型 * @param width 寬 * @param height 高 * @param destPath 輸出路徑 * @throws IOException */ public static void getImage(String content, Font font, Integer width, Integer height, String destPath) throws IOException { mkdirs(destPath); String file = UUID.randomUUID().toString() + ".jpg"; ImageIO.write(getImage(content, font, width, height), FORMAT_NAME, new File(destPath + "/" + file)); } /** * 獲取圖片 * * @param content 內容 * @param font 字型 * @param width 寬 * @param height 高 * @param output 輸出流 * @throws IOException */ public static void getImage(String content, Font font, Integer width, Integer height, OutputStream output) throws IOException { ImageIO.write(getImage(content, font, width, height), FORMAT_NAME, output); } /** * 獲取圖片 * * @param content 內容 * @param width 寬 * @param height 高 * @param destPath 輸出路徑 * @throws IOException */ public static void getImage(String content, Integer width, Integer height, String destPath) throws IOException { getImage(content, null, width, height, destPath); } /** * 獲取圖片 * * @param content 內容 * @param width 寬 * @param height 高 * @param output 輸出流 * @throws IOException */ public static void getImage(String content, Integer width, Integer height, OutputStream output) throws IOException { getImage(content, null, width, height, output); } /** * 建立 目錄 * * @param destPath */ public static void mkdirs(String destPath) { File file = new File(destPath); //當資料夾不存在時,mkdirs會自動建立多層目錄,區別於mkdir.(mkdir如果父目錄不存在則會丟擲異常) if (!file.exists() && !file.isDirectory()) { file.mkdirs(); } } public static void main(String[] args) throws Exception { getImage("川A***V", 100, 100, "D:/"); } }
package com.image; import java.awt.*; /** * Created by Liuxd on 2018-09-07. */ public class LogoConfig { // logo預設邊框顏色 public static final Color DEFAULT_BORDERCOLOR = Color.WHITE; // logo預設邊框寬度 public static final int DEFAULT_BORDER = 2; // logo大小預設為照片的1/5 public static final int DEFAULT_LOGOPART = 5; private final int border = DEFAULT_BORDER; private final Color borderColor; private final int logoPart; /** * Creates a default config with on color and off color * generating normal black-on-white barcodes. */ public LogoConfig() { this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART); } public LogoConfig(Color borderColor, int logoPart) { this.borderColor = borderColor; this.logoPart = logoPart; } public Color getBorderColor() { return borderColor; } public int getBorder() { return border; } public int getLogoPart() { return logoPart; } }