Java生成二维码

1.导入maven依赖如下:

<!-- Java工具类包 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-http</artifactId>
    <version>4.0.10</version>
</dependency>

<!-- 生成二维码 -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.2</version>
</dependency>

hutool是一个工具类包,封装了大量java开发常用的工具类.

2.工具类:

package com.baidu.Util;

import cn.hutool.core.util.ImageUtil;
import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;

public class QrCodeUtil {
    private static final int BLACK = -16777216;
    private static final int WHITE = -1;

    public QrCodeUtil() {
    }

    public static byte[] generatePng(String content, int width, int height) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        generate(content, width, height, "png", out);
        return out.toByteArray();
    }

    public static File generate(String content, int width, int height, File targetFile) {
        BufferedImage image = generate(content, width, height);
        ImageUtil.write(image, targetFile);
        return targetFile;
    }

    public static void generate(String content, int width, int height, String imageType, OutputStream out) {
        BufferedImage image = generate(content, width, height);
        ImageUtil.write(image, imageType, out);
    }

    public static BufferedImage generate(String content, int width, int height) {
        BitMatrix bitMatrix = encode(content, width, height);
        return toImage(bitMatrix);
    }

    public static BitMatrix encode(String content, int width, int height) {
        return encode(content, BarcodeFormat.QR_CODE, width, height);
    }

    public static BitMatrix encode(String content, BarcodeFormat format, int width, int height) {
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        HashMap<EncodeHintType, Object> hints = new HashMap();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        try {
            BitMatrix bitMatrix = multiFormatWriter.encode(content, format, width, height, hints);
            return bitMatrix;
        } catch (WriterException var7) {
            throw new QrCodeException(var7);
        }
    }

    public static String decode(InputStream qrCodeInputstream) {
        return decode((Image)ImageUtil.read(qrCodeInputstream));
    }

    public static String decode(File qrCodeFile) {
        return decode((Image)ImageUtil.read(qrCodeFile));
    }

    public static String decode(Image image) {
        MultiFormatReader formatReader = new MultiFormatReader();
        LuminanceSource source = new BufferedImageLuminanceSource(ImageUtil.toBufferedImage(image));
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        HashMap<DecodeHintType, Object> hints = new HashMap();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");

        Result result;
        try {
            result = formatReader.decode(binaryBitmap, hints);
        } catch (NotFoundException var8) {
            throw new QrCodeException(var8);
        }

        return result.getText();
    }

    public static BufferedImage toImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, 1);

        for(int x = 0; x < width; ++x) {
            for(int y = 0; y < height; ++y) {
                image.setRGB(x, y, matrix.get(x, y)?-16777216:-1);
            }
        }

        return image;
    }
}
package com.baidu.Util;

import com.google.zxing.LuminanceSource;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;

public final class BufferedImageLuminanceSource extends LuminanceSource {
    private final BufferedImage image;
    private final int left;
    private final int top;

    public BufferedImageLuminanceSource(BufferedImage image) {
        this(image, 0, 0, image.getWidth(), image.getHeight());
    }

    public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {
        super(width, height);
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        if(left + width <= sourceWidth && top + height <= sourceHeight) {
            for(int y = top; y < top + height; ++y) {
                for(int x = left; x < left + width; ++x) {
                    if((image.getRGB(x, y) & -16777216) == 0) {
                        image.setRGB(x, y, -1);
                    }
                }
            }

            this.image = new BufferedImage(sourceWidth, sourceHeight, 10);
            this.image.getGraphics().drawImage(image, 0, 0, (ImageObserver)null);
            this.left = left;
            this.top = top;
        } else {
            throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
        }
    }

    public byte[] getRow(int y, byte[] row) {
        if(y >= 0 && y < this.getHeight()) {
            int width = this.getWidth();
            if(row == null || row.length < width) {
                row = new byte[width];
            }

            this.image.getRaster().getDataElements(this.left, this.top + y, width, 1, row);
            return row;
        } else {
            throw new IllegalArgumentException("Requested row is outside the image: " + y);
        }
    }

    public byte[] getMatrix() {
        int width = this.getWidth();
        int height = this.getHeight();
        int area = width * height;
        byte[] matrix = new byte[area];
        this.image.getRaster().getDataElements(this.left, this.top, width, height, matrix);
        return matrix;
    }

    public boolean isCropSupported() {
        return true;
    }

    public LuminanceSource crop(int left, int top, int width, int height) {
        return new BufferedImageLuminanceSource(this.image, this.left + left, this.top + top, width, height);
    }

    public boolean isRotateSupported() {
        return true;
    }

    public LuminanceSource rotateCounterClockwise() {
        int sourceWidth = this.image.getWidth();
        int sourceHeight = this.image.getHeight();
        AffineTransform transform = new AffineTransform(0.0D, -1.0D, 1.0D, 0.0D, 0.0D, (double)sourceWidth);
        BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, 10);
        Graphics2D g = rotatedImage.createGraphics();
        g.drawImage(this.image, transform, (ImageObserver)null);
        g.dispose();
        int width = this.getWidth();
        return new BufferedImageLuminanceSource(rotatedImage, this.top, sourceWidth - (this.left + width), this.getHeight(), width);
    }
}
package com.baidu.Util;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;

public class QrCodeException extends RuntimeException {
    private static final long serialVersionUID = 469027218631691847L;

    public QrCodeException(Throwable e) {
        super(ExceptionUtil.getMessage(e), e);
    }

    public QrCodeException(String message) {
        super(message);
    }

    public QrCodeException(String messageTemplate, Object... params) {
        super(StrUtil.format(messageTemplate, params));
    }

    public QrCodeException(String message, Throwable throwable) {
        super(message, throwable);
    }

    public QrCodeException(Throwable throwable, String messageTemplate, Object... params) {
        super(StrUtil.format(messageTemplate, params), throwable);
    }
}
package com.baidu.Util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.regex.Pattern;

public final strictfp class MathUtil {
   private MathUtil() {
   }

   // 默认运算精度
   private static int DEF_SCALE = 10;

   /**
    * 提供数据类型转换为BigDecimal
    * 
    * @param object 原始数据
    * @return BigDecimal
    */
   public static final BigDecimal bigDecimal(Object object) {
      if (object == null) {
         throw new NullPointerException();
      }
      BigDecimal result;
      try {
         result = new BigDecimal(String.valueOf(object).replaceAll(",", ""));
      } catch (NumberFormatException e) {
         throw new NumberFormatException("Please give me a numeral.Not " + object);
      }
      return result;
   }

   /**
    * 提供(相对)精确的加法运算。
    * 
    * @param num1 被加数
    * @param num2 加数
    * @return 两个参数的和
    */
   public static final Double add(Object num1, Object num2) {
      BigDecimal result = bigDecimal(num1).add(bigDecimal(num2));
      return result.setScale(DEF_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
   }

   /**
    * 提供(相对)精确的减法运算。
    * 
    * @param num1 被减数
    * @param num2 减数
    * @return 两个参数的差
    */
   public static final Double subtract(Object num1, Object num2) {
      BigDecimal result = bigDecimal(num1).subtract(bigDecimal(num2));
      return result.setScale(DEF_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
   }

   /**
    * 提供(相对)精确的乘法运算。
    * 
    * @param num1 被乘数
    * @param num2 乘数
    * @return 两个参数的积
    */
   public static final Double multiply(Object num1, Object num2) {
      BigDecimal result = bigDecimal(num1).multiply(bigDecimal(num2));
      return result.setScale(DEF_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
   }

   /**
    * 提供(相对)精确的除法运算,当发生除不尽的情况时,精度为10位,以后的数字四舍五入。
    * 
    * @param num1 被除数
    * @param num2 除数
    * @return 两个参数的商
    */
   public static final Double divide(Object num1, Object num2) {
      return divide(num1, num2, DEF_SCALE);
   }

   /**
    * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
    * 
    * @param num1 被除数
    * @param num2 除数
    * @param scale 表示表示需要精确到小数点以后几位。
    * @return 两个参数的商
    */
   public static final Double divide(Object num1, Object num2, Integer scale) {
      if (scale == null) {
         scale = DEF_SCALE;
      }
      num2 = num2 == null || Math.abs(new Double(num2.toString())) == 0 ? 1 : num2;
      if (scale < 0) {
         throw new IllegalArgumentException("The scale must be a positive integer or zero");
      }
      BigDecimal result = bigDecimal(num1).divide(bigDecimal(num2), scale, BigDecimal.ROUND_HALF_UP);
      return result.doubleValue();
   }

   /**
    * 提供精确的小数位四舍五入处理。
    * 
    * @param num 需要四舍五入的数字
    * @param scale 小数点后保留几位
    * @return 四舍五入后的结果
    */
   public static final Double round(Object num, int scale) {
      if (scale < 0) {
         throw new IllegalArgumentException("The scale must be a positive integer or zero");
      }
      BigDecimal result = bigDecimal(num).divide(bigDecimal("1"), scale, BigDecimal.ROUND_HALF_UP);
      return result.doubleValue();
   }

   /**
    * 获取startend区间的随机数,不包含start+end
    * 
    * @param start
    * @param end
    * @return
    */
   public static final BigDecimal getRandom(int start, int end) {
      return new BigDecimal(start + Math.random() * end);
   }

   /**
    * 格式化
    * 
    * @param obj
    * @param pattern
    * @return
    */
   public static final String format(Object obj, String pattern) {
      if (obj == null) {
         return null;
      }
      if (pattern == null || "".equals(pattern)) {
         pattern = "#";
      }
      DecimalFormat format = new DecimalFormat(pattern);
      return format.format(bigDecimal(obj));
   }

   /** 是否数字 */
   public static final boolean isNumber(Object object) {
      Pattern pattern = Pattern.compile("\\d+(.\\d+)?$");
      return pattern.matcher(object.toString()).matches();
   }

   public static final void main(String[] args) {
      System.out.println(add(1.000001, 2.10));
   }
 
 

QrCodeUtil是生成二维码的核心工具类,需要引入QrCodeException异常类和BufferedImageLuminanceSource资源类;MathUtil是封装的一些简单计算的工具类,主要是用来计算二维码在照片上的宽高和位置

3.代码部分:

package com.baidu.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ImageUtil;
import cn.hutool.core.util.URLUtil;
import com.baidu.Util.MathUtil;
import com.baidu.Util.QrCodeUtil;
import com.baidu.entity.User;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;

/**
 * Created by dangsl on 2018/4/21.
 */
@RequestMapping("image")
@Controller
public class QrCodeController {

    @RequestMapping(value = "getImage",method = RequestMethod.GET)
    public ResponseEntity<byte[]> getImage(){
        //要转化二维码的链接
        User user = new User();
        user.setId("960832482708553728");
        user.setNickName("祭司");
        String url = "http://xxxxxxxxxx/user/login.html?recommendId=" + user.getId();
        //微信昵称
        String userName = user.getNickName();
        //最终图片宽高
        int w = 520,h = 853;
        //二维码高度
        int codeW = MathUtil.divide(w,3).intValue();
        //生成二维码
        BufferedImage generateCode = QrCodeUtil.generate(url, codeW, codeW);
        //获取背景图片
        BufferedImage backgroundImage = ImageUtil.read(URLUtil.url("http://XXXXXXXXXXX/976295506168774656"));
        //将二维码当作图片水印放置在背景图片上
        BufferedImage pressImage = ImageUtil.pressImage(backgroundImage, generateCode, 0, codeW-40, 0.9f);
        //我是和微信昵称当作文字水印放置在背景图片上
        BufferedImage pressText = ImageUtil.pressText(pressImage, "我是 "+userName, Color.BLACK, new Font("宋体", 0, 27), 0, codeW+112, 0.9f);
        //输出结果
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageUtil.write(pressText, FileUtil.file("E:\\weixin"+"/qrcode.png")); // 保存到本地指定目录
        ImageUtil.writeJpg(pressText,os);
        byte[] bytes = os.toByteArray();
        // 输出到前台展示
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_PNG);
        return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40074764/article/details/80031856