ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-12-03 12:00:48  阅读:178  来源: 互联网

标签:java String int param 二维码 添加 backgroundImage new Font


效果图

 

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有