需要注意的點:
1、這是基於java8以上的代碼
2、默認生成的圖片是png的,不過測試Path路徑寫jpg的後綴也可以的
一、工具類
需要導入zxing的依賴
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${google.zxing.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${google.zxing.version}</version>
</dependency>
話不多說,直接上代碼。經過2個小時的重構和精簡,代碼如下:
1.QrcodeUtil類
package com.zgd.base.util.qrcode;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Path;
/**
* @author zzzgd
* @apiNote 使用zxing qrcode生成二維碼
* @date 2019年8月16日 14點33分
*/
@Slf4j
public class QrcodeUtil {
private final static String FILE_FORMAT = "png";
/**
* 輸出到指定路徑
* @author zgd
*/
public static void createQrCodeToPath(BitMatrix bitMatrix, Path path) throws IOException {
MatrixToImageWriter.writeToPath(bitMatrix, FILE_FORMAT, path);
log.info("createQrCodeToPath ok...");
}
/**
* 輸出到指定路徑
* @author zgd
*/
public static void createQrCodeToPath(BitMatrix bitMatrix, Path path, Color front,Color background) throws IOException {
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriter.writeToPath(bitMatrix, FILE_FORMAT, path,config);
log.info("createQrCodeToPath ok...");
}
/**
* 輸出到流
* @author zgd
* @date 2019/8/16 14:31
*/
public static void createQrCodeToStream(BitMatrix bitMatrix, OutputStream stream) throws IOException {
MatrixToImageWriter.writeToStream(bitMatrix, FILE_FORMAT, stream);
log.info("createQrCodeTo ok...");
}
/**
* 輸出到流
* @author zgd
* @date 2019/8/16 14:31
*/
public static void createQrCodeToStream(BitMatrix bitMatrix, OutputStream stream,Color front,Color background) throws IOException {
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriter.writeToStream(bitMatrix, FILE_FORMAT, stream,config);
log.info("createQrCodeTo ok...");
}
/**
* 創建附帶本地路徑的logo的二維碼,到指定路徑
* @throws IOException
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix,Path codePath,Path logoPath)throws IOException{
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoPath);
}
/**
* 創建附帶url路徑的logo的二維碼,到指定路徑
* @throws IOException
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix, Path codePath, URL logoUrl)throws IOException{
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoUrl);
}
/**
* 創建附帶本地路徑的logo的二維碼,到輸出流
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToStream(BitMatrix bitMatrix,OutputStream os,Path logoPath)throws IOException{
MatrixToImageWriterWithLogo.writeToStream(bitMatrix,FILE_FORMAT,os,logoPath);
}
/**
* 創建附帶本地路徑的logo的二維碼,到指定路徑
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix,Path codePath,Path logoPath,Color front,Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoPath,config);
}
/**
* 創建附帶url路徑的logo的二維碼,到指定路徑
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix, Path codePath, URL logoUrl, Color front, Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoUrl,config);
}
/**
* 創建附帶本地路徑的logo的二維碼,到輸出流
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToStream(BitMatrix bitMatrix,OutputStream os,Path logoPath,Color front,Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToStream(bitMatrix,FILE_FORMAT,os,logoPath,config);
}
}
2. BitMatrixBuilder類
package com.zgd.base.util.qrcode;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Path;
/**
* @author zzzgd
* @apiNote 使用zxing qrcode生成二維碼
* @date 2019年8月16日 14點33分
*/
@Slf4j
public class QrcodeUtil {
private final static String FILE_FORMAT = "png";
/**
* 輸出到指定路徑
* @author zgd
*/
public static void createQrCodeToPath(BitMatrix bitMatrix, Path path) throws IOException {
MatrixToImageWriter.writeToPath(bitMatrix, FILE_FORMAT, path);
log.info("createQrCodeToPath ok...");
}
/**
* 輸出到指定路徑
* @author zgd
*/
public static void createQrCodeToPath(BitMatrix bitMatrix, Path path, Color front,Color background) throws IOException {
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriter.writeToPath(bitMatrix, FILE_FORMAT, path,config);
log.info("createQrCodeToPath ok...");
}
/**
* 輸出到流
* @author zgd
* @date 2019/8/16 14:31
*/
public static void createQrCodeToStream(BitMatrix bitMatrix, OutputStream stream) throws IOException {
MatrixToImageWriter.writeToStream(bitMatrix, FILE_FORMAT, stream);
log.info("createQrCodeTo ok...");
}
/**
* 輸出到流
* @author zgd
* @date 2019/8/16 14:31
*/
public static void createQrCodeToStream(BitMatrix bitMatrix, OutputStream stream,Color front,Color background) throws IOException {
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriter.writeToStream(bitMatrix, FILE_FORMAT, stream,config);
log.info("createQrCodeTo ok...");
}
/**
* 創建附帶本地路徑的logo的二維碼,到指定路徑
* @throws IOException
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix,Path codePath,Path logoPath)throws IOException{
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoPath);
}
/**
* 創建附帶url路徑的logo的二維碼,到指定路徑
* @throws IOException
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix, Path codePath, URL logoUrl)throws IOException{
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoUrl);
}
/**
* 創建附帶本地路徑的logo的二維碼,到輸出流
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToStream(BitMatrix bitMatrix,OutputStream os,Path logoPath)throws IOException{
MatrixToImageWriterWithLogo.writeToStream(bitMatrix,FILE_FORMAT,os,logoPath);
}
/**
* 創建附帶本地路徑的logo的二維碼,到指定路徑
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix,Path codePath,Path logoPath,Color front,Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoPath,config);
}
/**
* 創建附帶url路徑的logo的二維碼,到指定路徑
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToPath(BitMatrix bitMatrix, Path codePath, URL logoUrl, Color front, Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToPath(bitMatrix,FILE_FORMAT,codePath,logoUrl,config);
}
/**
* 創建附帶本地路徑的logo的二維碼,到輸出流
* @author zgd
* @date 2019/8/16 15:35
* @return void
*/
public static void createLogoQrCodeToStream(BitMatrix bitMatrix,OutputStream os,Path logoPath,Color front,Color background)throws IOException{
MatrixToImageConfig config = new MatrixToImageConfig(front.getRGB(), background.getRGB());
MatrixToImageWriterWithLogo.writeToStream(bitMatrix,FILE_FORMAT,os,logoPath,config);
}
}
至此一個普通的二維碼所需要的類就是這兩個,如果需要生成帶logo的,還要下面的類
3. MatrixToImageWriterWithLogo
package com.zgd.base.util.qrcode;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.common.BitMatrix;
import com.zgd.base.util.qrcode.config.LogoConfig;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.nio.file.Path;
/**
* 模仿Google的MatrixToImageWriter自己編寫的類
* @author zgd
* @date 18/09/14 17:53
*/
public class MatrixToImageWriterWithLogo {
private static final MatrixToImageConfig config = new MatrixToImageConfig();
private MatrixToImageWriterWithLogo() {
}
public static BufferedImage toBufferedImage(BitMatrix matrix,MatrixToImageConfig config) {
int width = matrix.getWidth();
int height = matrix.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, (matrix.get(x, y) ? config.getPixelOnColor() : config.getPixelOffColor()));
}
}
return image;
}
public static void writeToPath(BitMatrix matrix, String format, Path path, Path logoPath) throws IOException {
OutputStream os = new FileOutputStream(path.toFile());
writeToStream(matrix,format,os,logoPath,config);
}
public static void writeToPath(BitMatrix matrix, String format, Path path, Path logoPath, MatrixToImageConfig config) throws IOException {
OutputStream os = new FileOutputStream(path.toFile());
writeToStream(matrix,format,os,logoPath,config);
}
public static void writeToPath(BitMatrix matrix, String format, Path path, URL logoUrl) throws IOException {
OutputStream os = new FileOutputStream(path.toFile());
writeToStream(matrix,format,os,logoUrl,config);
}
public static void writeToPath(BitMatrix matrix, String format, Path path, URL logoUrl,MatrixToImageConfig config) throws IOException {
OutputStream os = new FileOutputStream(path.toFile());
writeToStream(matrix,format,os,logoUrl,config);
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream, Path logoPath) throws IOException {
writeToStream(matrix, format, stream, logoPath,config);
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream, Path logoPath,MatrixToImageConfig config) throws IOException {
BufferedImage image = toBufferedImage(matrix,config);
//設置logo圖標
BufferedImage bi = ImageIO.read(logoPath.toFile());
image = logoMatrix(image,bi);
if (!ImageIO.write(image, format, stream)) {
throw new IOException("Could not write an image of format " + format);
}
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream, URL logoUrl) throws IOException {
writeToStream(matrix,format,stream,logoUrl,config);
}
public static void writeToStream(BitMatrix matrix, String format, OutputStream stream, URL logoUrl,MatrixToImageConfig config) throws IOException {
BufferedImage image = toBufferedImage(matrix,config);
//設置logo圖標
BufferedImage bi = ImageIO.read(logoUrl);
image = logoMatrix(image,bi);
if (!ImageIO.write(image, format, stream)) {
throw new IOException("Could not write an image of format " + format);
}
}
/**
* 設置 logo
* @param matrixImage 源二維碼圖片
* @return 返回帶有logo的二維碼圖片
* @author Administrator sangwenhao
* @author zgd
* @date 2019/8/16 14:44
*/
private static BufferedImage logoMatrix(BufferedImage matrixImage, BufferedImage logo) {
//讀取二維碼圖片,並構建繪圖對象
Graphics2D g2 = matrixImage.createGraphics();
int matrixWidth = matrixImage.getWidth();
int matrixHeigh = matrixImage.getHeight();
//繪製
g2.drawImage(logo, matrixWidth / 5 * 2, matrixHeigh / 5 * 2, matrixWidth / 5, matrixHeigh / 5, null);
BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// 設置筆畫對象
g2.setStroke(stroke);
//指定弧度的圓角矩形
RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth / 5 * 2, matrixHeigh / 5 * 2, matrixWidth / 5, matrixHeigh / 5, 20, 20);
g2.setColor(Color.white);
// 繪製圓弧矩形
g2.draw(round);
//設置logo 有一道灰色邊框
BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
// 設置筆畫對象
g2.setStroke(stroke2);
RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth / 5 * 2 + 2, matrixHeigh / 5 * 2 + 2, matrixWidth / 5 - 4, matrixHeigh / 5 - 4, 20, 20);
g2.setColor(new Color(128, 128, 128));
// 繪製圓弧矩形
g2.draw(round2);
g2.dispose();
matrixImage.flush();
return matrixImage;
}
}
二、測試
package com.zgd.demo.file.qrcode;
import com.google.zxing.common.BitMatrix;
import com.zgd.base.util.qrcode.QrcodeUtil;
import com.zgd.base.util.qrcode.config.BitMatrixBuilder;
import org.junit.Test;
import java.awt.*;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* QrcodeTest
*
* @author zgd
* @date 2019/8/16 12:00
*/
public class QrcodeTest {
//測試網絡logo圖片生成二維碼
@Test
public void fun01() throws IOException {
Path path = Paths.get("D:/a.png");
// URL url = new URL("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4142156350,2539270243&fm=26&gp=0.jpg");
URL url = new URL("logo的網絡地址");
BitMatrix matrix = BitMatrixBuilder.create().setContent("https://blog.csdn.net/zzzgd_666").build();
QrcodeUtil.createLogoQrCodeToPath(matrix,path,url);
System.out.println("ok");
}
//測試本地logo圖片生成二維碼
@Test
@Test
public void fun02() throws IOException {
Path path = Paths.get("D:/a2.png");
Path path2 = Paths.get("D:/logo.jpg");
BitMatrix matrix = BitMatrixBuilder.create().setContent("https://blog.csdn.net/zzzgd_666").build();
QrcodeUtil.createLogoQrCodeToPath(matrix,path,path2);
System.out.println("ok");
}
//測試修改背景色
@Test
public void fun03() throws IOException {
Path path = Paths.get("D:/a3.png");
Path path2 = Paths.get("D:/logo.jpg");
BitMatrix matrix = BitMatrixBuilder.create().setContent("https://blog.csdn.net/zzzgd_666").build();
QrcodeUtil.createLogoQrCodeToPath(matrix,path,path2, Color.GRAY,Color.ORANGE);
System.out.println("ok");
}
}