可以生成带logo或者不带logo的二维码
一、准备(导入jar包)
方法一:如果是用maven:则在pom.xml文件中添加如下配置
<!--二维码依赖包-->
<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>
方法二:如果是普通的web项目,则在WEB-INF/lib下添加如下jar包
csdn下载链接:https://download.youkuaiyun.com/download/qq_16758997/11978559
可以自行到maven仓库下载更新版本,搜索zxing(见下图)
方法三:普通的java项目则直接将方法二中下载的jar包放入项目中并添加classpath路径(不是系统环境变量)
二、实现代码
import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
/**
* 二维码生成类
*/
public class QRcodeService {
private static final String CHARSET = "utf-8";
// 二维码尺寸
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(List<String> code, String content, String imgPath, boolean needCompress) throws Exception {
Map<EncodeHintType, Object> 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);
}
}
//在二维码下方增加文字显示
BufferedImage bi = new BufferedImage(width, height+20*code.size(), BufferedImage.TYPE_INT_RGB);//将高度增加20,在二维码下方增加一个区域显示文字
Graphics2D g2 = bi.createGraphics();
g2.setBackground(new Color(0xFF,0xFF,0xFF));
g2.clearRect(0, 0, width, height);
g2.drawImage(image, 0, 20*code.size(), width, height, null); //x,y为image图片的位置
//设置生成图片的文字样式
Font font = new Font("黑体", Font.BOLD, 17);
g2.setFont(font);
g2.setPaint(new Color(0x0,0x0,0x0));
// 设置字体在图片中的位置 在这里是居中
for(int i=0;i<code.size();){
// 防止生成的文字带有锯齿
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// 在图片上生成文字
g2.drawString(code.get(i), 5, 20*++i); //x,y为文字的位置
}
image=bi;
if (imgPath == null || "".equals(imgPath))
return image;
// 插入图片
QRcodeService.insertImage(image, imgPath, needCompress, code);
return image;
}
/**
* 插入logo图标
* @param source 二维码Image对象
* @param imgPath logo路径
* @param needCompress 是否需要缩小logo图标
* @param code
* @throws Exception
*/
private static void insertImage(BufferedImage source, String imgPath, boolean needCompress, List<String> code) 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;
}
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.drawImage(src, 0, 0, width, height, null); // 绘制图
// 画边框
g.setColor(Color.BLACK);
g.drawRect(4, 4, width - 8, height - 8);
g.drawRect(5, 5, width - 10, height - 10);
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+code.size()*20, width, height, null);//logo的位置可能需要调整
Shape shape = new RoundRectangle2D.Float(x, y+code.size()*20, width, width, 6, 6);//阴影的位置可能需要调整
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
/**
* 生成包含logo的二维码
* @param code 需要显示在二维码上方的list文字集合
* @param content 二维码中包含的内容
* @param imgPath logo图像地址
* @param needCompress 是否需要缩小logo图标
* @param fileUtil 保存文件的类对象
* @return 保存后的文件路径
* @throws Exception
*/
public static String encode(List<String> code, String content, String imgPath, boolean needCompress, FileUtil fileUtil) throws Exception {
BufferedImage image = QRcodeService.createImage(code, content, imgPath, needCompress);
//获取当前时间并格式化
String path=new SimpleDateFormat("yyyy/MM/dd hh:mm:ss").format(new Date());
path=path.substring(0,10);
//保存文件到磁盘
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return fileUtil.writeFile(input, "D:/qrcode/"+path, path+".png");
}
/**
* 不包含logo的二维码
* @param code 需要显示在二维码上方的list字符串集合
* @param content 二维码中的内容
* @param fileUtil 保存文件的工具类
* @return 保存成功之后的路径地址
* @throws Exception
*/
public static String encode(List<String> code, String content, FileUtil fileUtil) throws Exception {
return QRcodeService.encode(code, content, null, false, fileUtil);
}
}
import java.io.*;
/**
* 保存文件工具类
*/
public class FileUtil {
/**
* 保存文件对象
* @param is 文件InputStream对象
* @param target 文件目标
* @throws IOException
*/
public String writeFile(InputStream input, String path, String fileName) throws IOException {
fileName=System.currentTimeMillis()+fileName.substring(fileName.indexOf("."));
String filePath = verifyFolderExist(null, path, fileName);
if (filePath == null) return filePath;
writeFile(input, new File(filePath));
return path + File.separator + fileName;
}
/**
* 校验文件夹path文件夹是否存在
* @param file
* @param path
* @param fileName
* @return
*/
public String verifyFolderExist(File file, String path, String fileName) {
String folder_path = path;
String filePath = folder_path + File.separator + fileName;
if (file != null && file.getAbsolutePath().equals(filePath)) {
return null;
}
File folder = new File(folder_path);
if (!folder.exists()) {
folder.mkdirs();
}
return filePath;
}
/**
* 写入文件
* @param is
* @param target
* @throws IOException
*/
public void writeFile(InputStream is, File target) throws IOException {
OutputStream os = new FileOutputStream(target);
byte[] bytes = new byte[1024 * 1024];
int len = 0;
while ((len = is.read(bytes, 0, bytes.length)) > 0) {
os.write(bytes, 0, len);
}
is.close();
os.close();
}
}
三、测试代码
import java.util.*;
public class Test {
public static void main(String[] args) throws Exception {
List<String> showContent = new ArrayList<>();
//二维码上没有显示内容则传递空的list集合即可
showContent.add("名称:这是显示在二维码上的文字");
showContent.add("编码:这是显示在二维码上的文字");
//无logo的二维码
String path = new QRcodeService().encode(showContent, "这是二维码中的内容", new FileUtil());
System.out.println("无logo的二维码 "+path);
//有logo的二维码
path = new QRcodeService().encode(showContent,"这是二维码中的内容", "/C:/Users/yuye/Desktop/logo.png",true, new FileUtil());
System.out.println("有logo的二维码 "+path);
}
}
效果
完美
欢迎加群:517413713 讨论