java后端生成二维码图片用来下载

本文介绍了如何在Java后端生成二维码图片,并将其合成到一张背景图片上,同时添加文字。文中强调了在SpringBoot项目中,由于在Linux环境下部署,必须以流方式读取图片,避免'file not found'错误,还提到Linux系统缺少宋体字体库,需要额外下载以避免文字乱码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应公司需求,要求生成二维码图片,并且将二维码放进一张底层图片上,并赋予文字。

    1.首先我们要想办法生成二维码,二维码是黑白双色,中间不用添加商户logo,这里我们采用的google的jar包生成二维码

导入maven依赖:

<dependency>
   <groupId>com.google.zxing</groupId>
   <artifactId>core</artifactId>
   <version>3.3.3</version>
</dependency>

用到的是自己写的工具类:

package com.example.demo;/**
 * Created by 谈政扬 on 2018/6/15.
 */

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 谈政扬
 * @create 2018-06-15 15:55
 * @desc
 **/
public class Qrcode {

    /**
     * 黑色
     */
    private static final int BLACK = 0xFF000000;
    /**
     * 白色
     */
    private static final int WHITE = 0xFFFFFFFF;
    /**
     * 二维码的     */
    private static final int WIDTH = 360;
    /**
     * 二维码的     */
    private static final int HEIGHT = 360;

    /**
     * 二维码传图片为正方形
     *
     * @param matrix
     * @return
     */
    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        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,WHITE);
            }
        }
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    /**
     * 生成二维码,生成的是二维码图片
     * @author 谈政扬
     * @date 2018/6/13 11:31
     * @param [content]
     * @return java.awt.image.BufferedImage
     */
    @SuppressWarnings("unchecked")
    public static BufferedImage createQrCode(String content) throws Exception {

        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        @SuppressWarnings("rawtypes")
        Map hints = new HashMap();
        // 设置UTF-8, 防止中文乱码
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 设置二维码四周白色区域的大小
        hints.put(EncodeHintType.MARGIN, 1);
        // 设置二维码的容错性
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 画二维码
        BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
        BufferedImage image = toBufferedImage(bitMatrix);
        return image;
    }

    /**
     * 把二维码图片添加到背景图
     *
     * @param barCodeImage
     * @param logoPic
     */
    public static BufferedImage addLogo_QRCode(BufferedImage erweima, InputStream bgp)throws Exception {
        
     //读取二维码图片,并构建绘图对象360*360
        //保持二维码是正方形的
     int widtherweima = erweima.getWidth();
        int heighterweima = erweima.getHeight();
        /**
         * 读取背景图片600*900
         */
        BufferedImage bgpi = ImageIO.read(bgp);
        int widthbgpi = bgpi.getWidth();
        int heightbgpi = bgpi.getHeight();
        // 计算图片放置位置
     int x = 120;
        int y = 236;
        //构建背景的图片
     Graphics2D bgpiGraphics = bgpi.createGraphics();
        bgpiGraphics.drawImage(erweima, x, y, widtherweima, heighterweima, null);
        bgpiGraphics.dispose();
        return bgpi;
    }

    /**
         * 将文字写入背景图片中, 生成的图片以流的行式返回
     *
        * @param qrcFile 路径
     * @param qrCodeContent 二维码内容
     * @param pressText 增加的文字
     * @throws Exception
     */
    public static BufferedImage generateQrCode(BufferedImage image, String qrCodeContent, String pressText) throws Exception {

        Graphics g = image.getGraphics();
        ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        //设置字体,下面商户名称
        Font font=new Font("宋体", Font.PLAIN, 40);
        g.setFont(font);
        g.setColor(Color.white);
        FontMetrics metrics = g.getFontMetrics(font);
        // 文字在图片中的坐标 这里设置在中间
     int startX = (600 - metrics.stringWidth(pressText)) / 2;
        int startY=650;
        g.drawString(pressText, startX, startY);
        g.dispose();
        return image;
    }

}

在接口中调用方法启动:

    

@GetMapping(value = "/QrcodeDown/{mchId}")
public void QrcodeDown(@PathVariable("mchId")String mchId, HttpServletResponse response){
    Map resultMap = new HashMap<String,Object>(5);
    try {
        //二维码内容,这里的路径根据自己的业务需求填写
        String qrCodeContent="http://www.baidu.com"+"&mch="+mchId;
        //商户名称
     // Map<String, Object> map1 = paymentService.selectmchInfoByMchId(mchId);
        //String name = map1.get("name").toString();
             String name ="**科技";
        //springboot读取文件为流对象
        InputStream stream = getClass().getClassLoader().getResourceAsStream("img/original.jpg");
        //生成二维码
        BufferedImage erweima = Qrcode.createQrCode(qrCodeContent);
        //将二维码放在背景图上
        BufferedImage image = Qrcode.addLogo_QRCode(erweima, stream);
        //给图片添加文字并且输出
       BufferedImage bufferedImage = Qrcode.generateQrCode(image, qrCodeContent, name);
              name=name+".jpg";
              response.setHeader("content-disposition", "attachment;filename=" + new String(name.getBytes("utf-8") , "ISO_8859_1"));
              response.setContentType("application/octet-stream");
              ServletOutputStream sos = response.getOutputStream();
              ImageIO.write(bufferedImage,"jpg",sos);
             sos.close();
    }catch (Exception e){
        e.printStackTrace();
        resultMap.put("msg","服务器异常");
    }

}

在最后提醒大家一句:

    因为公司主要用springboot框架进行开发,在读取背景图片时不能以文件行式读取,只能以流的行式读取。不然在linux下部署项目时不能读取到文件,会一直报file is not found错。我在这里就耽误了很多时间,一直认为是自己的路径没找到,没成想是不能以文件行式读取,最好以输入流的行式读取。最后还有一个问题就是,在linux系统下并没有宋体的字体库,所以还得去下载宋体字体库,不然添加的文字显示时是乱码。

    效果图:

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毛毛的毛毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值