编程语言
首页 > 编程语言> > java生成二维码并与另一张图片合成,添加文字

java生成二维码并与另一张图片合成,添加文字

作者:互联网

效果图

 

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博客

标签:java,String,int,param,二维码,添加,backgroundImage,new,Font
来源: https://blog.csdn.net/weixin_44259233/article/details/121695171