效果图
1.引入pom
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
2.工具类
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @description :ZxingUtils
* @author :liu
* @since :2021/12/1 16:40
*/
public class ZxingUtils {
public static BufferedImage enQRCode(String contents, int width, int height) throws WriterException {
//定义二维码参数
final Map<EncodeHintType, Object> hints = new HashMap(8) {
{
//编码
put(EncodeHintType.CHARACTER_SET, "UTF-8");
//容错级别
put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//边距
put(EncodeHintType.MARGIN, 0);
}
};
return enQRCode(contents, width, height, hints);
}
/**
* 生成二维码
* @param contents 二维码内容
* @param width 图片宽度
* @param height 图片高度
* @param hints 二维码相关参数
* @return BufferedImage对象
* @throws WriterException 编码时出错
* @throws IOException 写入文件出错
*/
public static BufferedImage enQRCode(String contents, int width, int height, Map hints) throws WriterException {
// String uuid = UUID.randomUUID().toString().replace("-", "");
//本地完整路径
// String pathname = path + "/" + uuid + "." + format;
//生成二维码
BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
// Path file = new File(pathname).toPath();
//将二维码保存到路径下
// MatrixToImageWriter.writeToPa(bitMatrix, format, file);
// return pathname;
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
/**
* 将图片绘制在背景图上
*
* @param backgroundPath 背景图路径
* @param zxingImage 图片
* @param x 图片在背景图上绘制的x轴起点
* @param y 图片在背景图上绘制的y轴起点
* @return
*/
public static BufferedImage drawImage(String backgroundPath, BufferedImage zxingImage, int x, int y) throws IOException {
//读取背景图的图片流
BufferedImage backgroundImage;
//Try-with-resources 资源自动关闭,会自动调用close()方法关闭资源,只限于实现Closeable或AutoCloseable接口的类
try (InputStream imagein = new FileInputStream(backgroundPath)) {
backgroundImage = ImageIO.read(imagein);
}
return drawImage(backgroundImage, zxingImage, x, y);
}
/**
* 将图片绘制在背景图上
*
* @param backgroundImage 背景图
* @param zxingImage 图片
* @param x 图片在背景图上绘制的x轴起点
* @param y 图片在背景图上绘制的y轴起点
* @return
* @throws IOException
*/
public static BufferedImage drawImage(BufferedImage backgroundImage, BufferedImage zxingImage, int x, int y) throws IOException {
Objects.requireNonNull(backgroundImage, ">>>>>背景图不可为空");
Objects.requireNonNull(zxingImage, ">>>>>二维码不可为空");
//二维码宽度+x不可以超过背景图的宽度,长度同理
if ((zxingImage.getWidth() + x) > backgroundImage.getWidth() || (zxingImage.getHeight() + y) > backgroundImage.getHeight()) {
throw new IOException(">>>>>二维码宽度+x不可以超过背景图的宽度,长度同理");
}
//合并图片
Graphics2D g = backgroundImage.createGraphics();
g.drawImage(zxingImage, x, y,
zxingImage.getWidth(), zxingImage.getHeight(), null);
return backgroundImage;
}
public static InputStream bufferedImageToInputStream(BufferedImage backgroundImage) throws IOException {
return bufferedImageToInputStream(backgroundImage, "png");
}
/**
* backgroundImage 转换为输出流
*
* @param backgroundImage
* @param format
* @return
* @throws IOException
*/
public static InputStream bufferedImageToInputStream(BufferedImage backgroundImage, String format) throws IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
try (
ImageOutputStream
imOut = ImageIO.createImageOutputStream(bs)) {
ImageIO.write(backgroundImage, format, imOut);
InputStream is = new ByteArrayInputStream(bs.toByteArray());
return is;
}
}
/**
* 保存为文件
*
* @param is
* @param fileName
* @throws IOException
*/
public static void saveFile(InputStream is, String fileName) throws IOException {
try (BufferedInputStream in = new BufferedInputStream(is);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileName))) {
int len;
byte[] b = new byte[1024];
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
}
}
public static void main(String[] args) {
//二维码宽度
int width = 230;
//二维码高度
int height = 177;
//二维码内容
String contcent = "XXXXXXXXXXXXXXXXXXXXxxx;";
BufferedImage zxingImage = null;
try {
//二维码图片流
zxingImage = ZxingUtils.enQRCode(contcent, width, height);
} catch (WriterException e) {
e.printStackTrace();
}
//背景图片地址
String backgroundPath = "C:/Users/pc/Desktop/baseProve.png";
InputStream inputStream = null;
try {
//合成二维码和背景图
BufferedImage image = ZxingUtils.drawImage(backgroundPath, zxingImage, 548, 0);
//绘制文字
Font font = new Font("微软雅黑", Font.PLAIN, 20);
String text = "xxxxxxxxxxxx";
image = ZxingUtils.drawString(image, text, 185, 195,font,new Color(0,0,0));
//绘制文字
Font font2 = new Font("微软雅黑", Font.PLAIN, 20);
String text2 = "2017";
image = ZxingUtils.drawString(image, text2, 245, 252,font2,new Color(0,0,0));
//绘制文字
Font font3 = new Font("微软雅黑", Font.PLAIN, 20);
String text3 = "2017-10-04 19:07:27";
image = ZxingUtils.drawString(image, text3, 450, 402,font3,new Color(0,0,0));
//添加水印
Font font4 = new Font("微软雅黑", Font.PLAIN, 60); //水印字体
Color color=new Color(0,0,0,15);
String waterMarkContent="http://www.gdstcloud.com"; //水印内容//水印图片色彩以及透明度50, 270,
image=ZxingUtils.addWaterMarkIO(image, waterMarkContent,50, 270, font4, color);
ByteArrayOutputStream out = new ByteArrayOutputStream();
//转换成png格式的IO流
ImageIO.write(image, "png", out);
byte[] bytes = out.toByteArray();
// 2、将字节数组转为二进制
BASE64Encoder encoder = new BASE64Encoder();
String binary = encoder.encodeBuffer(bytes).trim();
//图片转inputStream
inputStream = ZxingUtils.bufferedImageToInputStream(image);
} catch (IOException e) {
e.printStackTrace();
}
//保存的图片路径
String originalFileName= "E:/asd/99.png";
try {
//保存为本地图片
ZxingUtils.saveFile(inputStream, originalFileName);
System.out.println("成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 将文字绘制在背景图上
*
* @param backgroundImage 背景图
* @param x 文字在背景图上绘制的x轴起点
* @param y 文字在背景图上绘制的y轴起点
* @return
* @throws IOException
*/
public static BufferedImage drawString(BufferedImage backgroundImage, String text, int x, int y,Font font,Color color) {
//绘制文字
Graphics2D g = backgroundImage.createGraphics();
//设置颜色
g.setColor(color);
//消除锯齿状
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
//设置字体
g.setFont(font);
//绘制文字
g.drawString(text, x, y);
return backgroundImage;
}
/**
* 将水印绘制在背景图上
* @param backgroundImage 背景图
* @param waterMarkContent 内容
* @param x 文字在背景图上绘制的x轴起点
* @param y 文字在背景图上绘制的y轴起点
* @param font 设置字体
* @param color 图片的背景设置水印颜色
* @return
*/
public static BufferedImage addWaterMarkIO(BufferedImage backgroundImage, String waterMarkContent,int x,int y,Font font,Color color) {
int srcImgWidth = backgroundImage.getWidth(null);//获取图片的宽
int srcImgHeight = backgroundImage.getHeight(null);//获取图片的高
// 加水印
Graphics2D g = backgroundImage.createGraphics();
g.drawImage(backgroundImage, 0, 0, srcImgWidth, srcImgHeight, null);
g.setColor(color); //根据图片的背景设置水印颜色
g.setFont(font); //设置字体
//设置水印的坐标
//int x = srcImgWidth - getWatermarkLengths(waterMarkContent, g);
//int y = srcImgHeight - getWatermarkLengths(waterMarkContent, g);
/* int x = 50;
int y = 270; */
// 设置水印旋转
g.rotate(Math.toRadians(20),backgroundImage.getWidth() / 2, (double) backgroundImage
.getHeight() / 2);
g.drawString(waterMarkContent, x, y); //画出水印
g.dispose();
return backgroundImage;
}
/**
* 计算随意坐标
* @param waterMarkContent
* @param g
* @return
*/
public static int getWatermarkLengths(String waterMarkContent, Graphics2D g) {
return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
}
/**
* @param srcImgPath 源图片路径
* @param tarImgPath 保存的图片路径
* @param waterMarkContent 水印内容
* @param markContentColor 水印颜色
* @param font 水印字体
*/
public void addWaterMark(String srcImgPath, String tarImgPath, String waterMarkContent,Color markContentColor,Font font) {
try {
// 读取原图片信息
File srcImgFile = new File(srcImgPath);//得到文件
Image srcImg = ImageIO.read(srcImgFile);//文件转化为图片
int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
int srcImgHeight = srcImg.getHeight(null);//获取图片的高
// 加水印
BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufImg.createGraphics();
g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
g.setColor(markContentColor); //根据图片的背景设置水印颜色
g.setFont(font); //设置字体
//设置水印的坐标
/* int x = srcImgWidth - getWatermarkLength(waterMarkContent, g);
int y = srcImgHeight - getWatermarkLength(waterMarkContent, g); */
int x = 50;
int y = 270;
// 设置水印旋转
g.rotate(Math.toRadians(20),bufImg.getWidth() / 2, (double) bufImg
.getHeight() / 2);
g.drawString(waterMarkContent, x, y); //画出水印
g.dispose();
// 输出图片
FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
ImageIO.write(bufImg, "jpg", outImgStream);
System.out.println("添加水印完成");
outImgStream.flush();
outImgStream.close();
} catch (Exception e) {
// TODO: handle exception
}
}
public int getWatermarkLength(String waterMarkContent, Graphics2D g) {
return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
}
public static void main1(String[] args) {
Font font = new Font("微软雅黑", Font.PLAIN, 60); //水印字体
String srcImgPath="E:/99999.png"; //源图片地址
String tarImgPath="E:/999998.png"; //待存储的地址
String waterMarkContent="http://www.baidu.com"; //水印内容
Color color=new Color(0,0,0,15); //水印图片色彩以及透明度
new ZxingUtils().addWaterMark(srcImgPath, tarImgPath, waterMarkContent, color,font);
}
}
3.controller类下载二维码
/**
* 下载
*/
@RequestMapping(value="/downLoadBaseProve")
public void downLoadBaseProve(HttpServletResponse response, HttpServletRequest request) throws Exception{
/**
省略
*/
BASE64Decoder decoder = new BASE64Decoder();
String images=getbaseProveIo();
byte[] bytes1 = decoder.decodeBuffer(images);
String name= "xxx-停车场"+ System.currentTimeMillis()+".png";
// byte[] bytes = Files.readAllBytes(file.toPath());
//
// String name = file.getName();
name = URLEncoder.encode(name, "UTF-8");
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"" + name + "\"");
response.addHeader("Content-Length", "" + bytes1.length);
response.setContentType("application/octet-stream;charset=UTF-8");
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
outputStream.write(bytes1);
outputStream.flush();
outputStream.close();
response.flushBuffer();
}
方法:
private String getbaseProveIo() throws IOException {
// int num="55";
String binary=null;
//背景图片地址
File f = new ClassPathResource("qrTpl/wx_pay_tpl.png").getFile();
String imagein = f.getAbsolutePath();
//InputStream imageins = new FileInputStream(imagein);
System.out.println(imagein);
//二维码宽度
int width = 669;
//二维码高度
int height = 681;
//二维码内容
String contcent = "?parkId=16&channelNo=2";
BufferedImage zxingImage = null;
try {
//二维码图片流
zxingImage = ZxingUtils.enQRCode(contcent, width, height);
} catch (WriterException e) {
e.printStackTrace();
}
try {
//合成二维码和背景图
BufferedImage image = ZxingUtils.drawImage(imagein, zxingImage, 313, 569);
//绘制文字
// Font font = new Font("微软雅黑", Font.PLAIN, 20);
// String text = "中国";
// image = ZxingUtils.drawString(image, text, 185, 195,font,new Color(0,0,0));
//绘制文字
// Font font2 = new Font("微软雅黑", Font.PLAIN, 20);
// String text2 = DateUtil.today();
// image = ZxingUtils.drawString(image, text2, 245, 252,font2,new Color(0,0,0));
//绘制文字
Font font3 = new Font("微软雅黑", Font.PLAIN, 72);
String text3 = "xxx-停车场";
image = ZxingUtils.drawString(image, text3, 81, 101,font3,new Color(255,255,255));
//添加水印
Font font4 = new Font("微软雅黑", Font.PLAIN, 60); //水印字体
Color color=new Color(0,0,0,15);
String waterMarkContent="深圳xxx科技有限公司"; //水印内容//水印图片色彩以及透明度50, 270,
image=ZxingUtils.addWaterMarkIO(image, waterMarkContent,215, 183, font4, color);
//图片以字节数据在页面显示
ByteArrayOutputStream out = new ByteArrayOutputStream();
//转换成png格式的IO流
ImageIO.write(image, "png", out);
byte[] bytes = out.toByteArray();
// 2、将字节数组转为二进制
BASE64Encoder encoder = new BASE64Encoder();
binary = encoder.encodeBuffer(bytes).trim();
//图片转inputStream
//inputStream = ZxingUtils.bufferedImageToInputStream(image);
} catch (IOException e) {
e.printStackTrace();
}
return binary;
}
之后就可以在页面下载合成后的二维码
参考:java 生成二维码,并跟其他图合成新图 图片添加水印_冰夜翎博客-CSDN博客