兩種JAVA生成帶logo二維碼的方法
阿新 • • 發佈:2018-12-02
一、方法一
只使用一個zxing.jar生成二維碼,下載地址http://central.maven.org/maven2/com/google/zxing/core/
專案目錄
QRCodeUtil.java(用於生成二維碼的工具類)
import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Shape; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.OutputStream; import java.util.Hashtable; import java.util.Random; 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.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; public class QRCodeUtil { 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 BufferedImage createImage(String content, 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(); BufferedImage image = new BufferedImage(width, height, 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)) { return image; } // 插入圖片 QRCodeUtil.insertImage(image, imgPath, needCompress); return image; } 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 imgPath, String destPath, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); mkdirs(destPath); String file = new Random().nextInt(99999999)+".jpg"; ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file)); } 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 imgPath, String destPath) throws Exception { QRCodeUtil.encode(content, 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 destPath) throws Exception { QRCodeUtil.encode(content, null, destPath, false); } public static void encode(String content, String imgPath, OutputStream output, boolean needCompress) throws Exception { BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress); ImageIO.write(image, FORMAT_NAME, output); } public static void encode(String content, OutputStream output) throws Exception { QRCodeUtil.encode(content, 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 QRCodeUtil.decode(new File(path)); } }
2.CreateQRCodeTest.java(測試類)
public class CreateQRCodeTest { public static void main(String[] args) throws Exception { String url = "https://www.baidu.com/"; String picture = "E://test.jpg"; String qrcodePath = "E://temps"; QRCodeUtil.encode(url,picture, qrcodePath, true); } }
二、方法二
需要匯入三個jar包,但無需自己寫處理logo圖片的類,參考:https://blog.csdn.net/qq_22860341/article/details/80222591
專案目錄
CreateQRCode.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
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;
public class CreateQRCode {
private static final int QRCOLOR = 0xFF000000; // 預設是黑色
private static final int BGWHITE = 0xFFFFFFFF; // 背景顏色
private static final int WIDTH = 400; // 二維碼寬
private static final int HEIGHT = 400; // 二維碼高
// 設定QR二維碼引數
private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
private static final long serialVersionUID = 1L;
{
// 設定QR二維碼的糾錯級別(H為最高級別)具體級別資訊
/*L 水平 7%的字碼可被修正
M 水平 15%的字碼可被修正
Q 水平 25%的字碼可被修正
H 水平 30%的字碼可被修正*/
put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
put(EncodeHintType.CHARACTER_SET, "utf-8");// 設定編碼方式
}
};
// 生成帶logo的二維碼圖片
public static void drawLogoQRCode(File logoFile, File codeFile, String qrUrl, String note) {
try {
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
// 引數順序分別為:編碼內容,編碼型別,生成圖片寬度,生成圖片高度,設定引數
BitMatrix bm = multiFormatWriter.encode(qrUrl, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 開始利用二維碼資料建立Bitmap圖片,分別設為黑(0xFFFFFFFF)白(0xFF000000)兩色
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
}
}
int width = image.getWidth();
int height = image.getHeight();
if (Objects.nonNull(logoFile) && logoFile.exists()) {
// 構建繪圖物件
Graphics2D g = image.createGraphics();
// 讀取Logo圖片
BufferedImage logo = ImageIO.read(logoFile);
// 開始繪製logo圖片
g.drawImage(logo, width * 2 / 5, height * 2 / 5, width * 2 / 10, height * 2 / 10, null);
g.dispose();
logo.flush();
}
// 自定義文字描述
if (StringUtils.isNotEmpty(note)) {
// 新的圖片,把帶logo的二維碼下面加上文字
BufferedImage outImage = new BufferedImage(400, 445, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D outg = outImage.createGraphics();
// 畫二維碼到新的面板
outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
// 畫文字到新的面板
outg.setColor(Color.BLACK);
outg.setFont(new Font("楷體", Font.BOLD, 30)); // 字型、字型、字號
int strWidth = outg.getFontMetrics().stringWidth(note);
if (strWidth > 399) {
// //長度過長就擷取前面部分
// 長度過長就換行
String note1 = note.substring(0, note.length() / 2);
String note2 = note.substring(note.length() / 2, note.length());
int strWidth1 = outg.getFontMetrics().stringWidth(note1);
int strWidth2 = outg.getFontMetrics().stringWidth(note2);
outg.drawString(note1, 200 - strWidth1 / 2, height + (outImage.getHeight() - height) / 2 + 12);
BufferedImage outImage2 = new BufferedImage(400, 485, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D outg2 = outImage2.createGraphics();
outg2.drawImage(outImage, 0, 0, outImage.getWidth(), outImage.getHeight(), null);
outg2.setColor(Color.BLACK);
outg2.setFont(new Font("宋體", Font.BOLD, 30)); // 字型、字型、字號
outg2.drawString(note2, 200 - strWidth2 / 2,outImage.getHeight() + (outImage2.getHeight() - outImage.getHeight()) / 2 + 5);
outg2.dispose();
outImage2.flush();
outImage = outImage2;
} else {
outg.drawString(note, 200 - strWidth / 2, height + (outImage.getHeight() - height) / 2 + 12); // 畫文字
}
outg.dispose();
outImage.flush();
image = outImage;
}
image.flush();
ImageIO.write(image, "png", codeFile); // TODO
} catch (Exception e) {
e.printStackTrace();
}
}
}
CreateQRCodeTest.java
import java.io.File;
import com.google.zxing.WriterException;
public class CreateQRCodeTest {
public static void main(String[] args) throws WriterException {
File logoFile = new File("E://test.jpg"); //logo
File QrCodeFile = new File("E://temps//qrcode.jpg"); //二維碼生成地址以及名稱格式
String url = "https://www.baidu.com/"; // 掃描二維碼進入網址
String note = "標題"; //標題
CreateQRCode.drawLogoQRCode(logoFile, QrCodeFile, url, note);
}
}