|
@@ -0,0 +1,467 @@
|
|
|
+package com.hcloud.microserver.commoncore.util;
|
|
|
+
|
|
|
+import com.google.zxing.*;
|
|
|
+import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
|
|
+import com.google.zxing.client.j2se.MatrixToImageConfig;
|
|
|
+import com.google.zxing.client.j2se.MatrixToImageWriter;
|
|
|
+import com.google.zxing.common.BitMatrix;
|
|
|
+import com.google.zxing.common.HybridBinarizer;
|
|
|
+import com.google.zxing.qrcode.QRCodeReader;
|
|
|
+import com.google.zxing.qrcode.QRCodeWriter;
|
|
|
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+import java.awt.*;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.*;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.Hashtable;
|
|
|
+
|
|
|
+
|
|
|
+ * 二维码生成和读的工具类 使用google 开发的 zxing
|
|
|
+ * 参数介绍:
|
|
|
+ * ZXing采用Hashtable方式来保存设置参数:纠错能力为 L 级别,设置编码类型为UTF-8
|
|
|
+ * 位矩阵二维码数据 BitMatrix
|
|
|
+ *
|
|
|
+ * @author xiezt 2019/01/13
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+public class QrCodeUtil {
|
|
|
+ private String content;
|
|
|
+ private String qrCodeUrl;
|
|
|
+ private String filePath;
|
|
|
+ private String fileName;
|
|
|
+ private String imageFormat;
|
|
|
+ private String logoPath;
|
|
|
+ private Integer width = 300;
|
|
|
+ private Integer height = 300;
|
|
|
+ private Integer onColor = 0xFF000000;
|
|
|
+ private Integer bgColor = 0xFFFFFFFF;
|
|
|
+ private Integer margin = 2;
|
|
|
+ private ErrorCorrectionLevel level = ErrorCorrectionLevel.M;
|
|
|
+
|
|
|
+
|
|
|
+ * 生成二维码 属性:content、fileName、filePath不得为空
|
|
|
+ *
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public void createQRCode() throws Exception {
|
|
|
+ String imgPath = this.getFilePath();
|
|
|
+ String imgName = this.getFileName();
|
|
|
+ String content = this.getContent();
|
|
|
+ String imageFormat = this.getImageFormat();
|
|
|
+ if (imageFormat == null || imgPath == null || content == null) {
|
|
|
+ throw new Exception("参数错误");
|
|
|
+ }
|
|
|
+ boolean flag;
|
|
|
+ String[] arr = filePath.split("\\.");
|
|
|
+ if (arr.length == 1) {
|
|
|
+ flag = true;
|
|
|
+ } else if (arr.length == 2) {
|
|
|
+ flag = false;
|
|
|
+ } else {
|
|
|
+ throw new Exception("判断路径类型错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flag) {
|
|
|
+ if (this.getLogoPath() != null && !"".equals(this.getLogoPath().trim())) {
|
|
|
+ generateQRCodeWithLogo(content, this.getLogoPath(), imgPath, imgName, imageFormat);
|
|
|
+ } else {
|
|
|
+ generateQRCode(content, imgPath, imgName, imageFormat);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if (this.getLogoPath() != null && !"".equals(this.getLogoPath().trim())) {
|
|
|
+ generateQRCodeWithLogo(content, this.getLogoPath(), imgPath, imageFormat);
|
|
|
+ } else {
|
|
|
+ generateQRCode(content, imgPath, imageFormat);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成二维码
|
|
|
+ *
|
|
|
+ * @param content
|
|
|
+ * @param imgPath
|
|
|
+ * @param imgName
|
|
|
+ * @param suffix
|
|
|
+ */
|
|
|
+ public void generateQRCode(String content, String imgPath, String imgName, String suffix) throws Exception {
|
|
|
+ File filePath = new File(imgPath);
|
|
|
+ if (!filePath.exists()) {
|
|
|
+ log.info("文件路径不存在,开始创建文件路径。");
|
|
|
+ filePath.mkdirs();
|
|
|
+ }
|
|
|
+ File imageFile = new File(imgPath, imgName);
|
|
|
+ Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.ERROR_CORRECTION, level);
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.MARGIN, this.getMargin());
|
|
|
+ MatrixToImageConfig config = new MatrixToImageConfig(this.getOnColor(), this.getBgColor());
|
|
|
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, this.getWidth(), this
|
|
|
+ .getHeight(), hints);
|
|
|
+
|
|
|
+ MatrixToImageWriter.writeToPath(bitMatrix, suffix, imageFile.toPath(), config);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成二维码
|
|
|
+ *
|
|
|
+ * @param content
|
|
|
+ * @param path
|
|
|
+ * @param suffix
|
|
|
+ */
|
|
|
+ public void generateQRCode(String content, String path, String suffix) throws Exception {
|
|
|
+ File imageFile = new File(path);
|
|
|
+ if (!imageFile.getParentFile().exists()) {
|
|
|
+ imageFile.getParentFile().mkdirs();
|
|
|
+ }
|
|
|
+ Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.ERROR_CORRECTION, level);
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.MARGIN, this.getMargin());
|
|
|
+ MatrixToImageConfig config = new MatrixToImageConfig(this.getOnColor(), this.getBgColor());
|
|
|
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, this.getWidth(), this
|
|
|
+ .getHeight(), hints);
|
|
|
+ MatrixToImageWriter.writeToPath(bitMatrix, suffix, imageFile.toPath(), config);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成二维码,返回二维码路径
|
|
|
+ *
|
|
|
+ * @param content
|
|
|
+ * @param path
|
|
|
+ * @param suffix
|
|
|
+ */
|
|
|
+ public String generateQRCodeUrl(String content, String path, String suffix) throws Exception {
|
|
|
+ String nowfile = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
|
|
|
+ String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + "." + suffix;
|
|
|
+ path = path + nowfile + "/" + fileName;
|
|
|
+ File imageFile = new File(path);
|
|
|
+ if (!imageFile.getParentFile().exists()) {
|
|
|
+ imageFile.getParentFile().mkdirs();
|
|
|
+ }
|
|
|
+ Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.ERROR_CORRECTION, level);
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.MARGIN, this.getMargin());
|
|
|
+ MatrixToImageConfig config = new MatrixToImageConfig(this.getOnColor(), this.getBgColor());
|
|
|
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, this.getWidth(), this
|
|
|
+ .getHeight(), hints);
|
|
|
+ MatrixToImageWriter.writeToPath(bitMatrix, suffix, imageFile.toPath(), config);
|
|
|
+
|
|
|
+ return "/qrcode/" + nowfile + "/" + fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成带logo的二维码图片
|
|
|
+ *
|
|
|
+ * @param content
|
|
|
+ * @param logoPath
|
|
|
+ * @param imgPath
|
|
|
+ * @param imgName
|
|
|
+ * @param suffix
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public void generateQRCodeWithLogo(String content, String logoPath, String imgPath, String imgName, String
|
|
|
+ suffix) throws Exception {
|
|
|
+ File filePath = new File(imgPath);
|
|
|
+ if (!filePath.exists()) {
|
|
|
+ filePath.mkdirs();
|
|
|
+ }
|
|
|
+ if (imgPath.endsWith("/")) {
|
|
|
+ imgPath += imgName;
|
|
|
+ } else {
|
|
|
+ imgPath += "/" + imgName;
|
|
|
+ }
|
|
|
+ Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
|
|
+ hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
|
|
|
+ hints.put(EncodeHintType.ERROR_CORRECTION, this.getLevel());
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.MARGIN, this.getMargin());
|
|
|
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, this.getWidth(), this
|
|
|
+ .getHeight(), hints);
|
|
|
+ File qrcodeFile = new File(imgPath);
|
|
|
+ writeToFile(toBufferedImage(bitMatrix), suffix, qrcodeFile, logoPath);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成带logo的二维码图片
|
|
|
+ *
|
|
|
+ * @param content
|
|
|
+ * @param logoPath
|
|
|
+ * @param path
|
|
|
+ * @param suffix
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ public void generateQRCodeWithLogo(String content, String logoPath, String path, String suffix) throws Exception {
|
|
|
+ Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
|
|
|
+ hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
|
|
|
+ hints.put(EncodeHintType.ERROR_CORRECTION, this.getLevel());
|
|
|
+
|
|
|
+ hints.put(EncodeHintType.MARGIN, this.getMargin());
|
|
|
+ BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, this.getWidth(), this
|
|
|
+ .getHeight(), hints);
|
|
|
+ File qrcodeFile = new File(path);
|
|
|
+ writeToFile(toBufferedImage(bitMatrix), suffix, qrcodeFile, logoPath);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * @param image 二维码矩阵相关
|
|
|
+ * @param format 二维码图片格式
|
|
|
+ * @param file 二维码图片文件
|
|
|
+ * @param logoPath logo路径
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public void writeToFile(BufferedImage image, String format, File file, String logoPath) throws Exception {
|
|
|
+
|
|
|
+ Graphics2D gs = image.createGraphics();
|
|
|
+ int ratioWidth = image.getWidth() * 2 / 10;
|
|
|
+ int ratioHeight = image.getHeight() * 2 / 10;
|
|
|
+
|
|
|
+ Image img = ImageIO.read(new File(logoPath));
|
|
|
+
|
|
|
+ int logoWidth = img.getWidth(null) > ratioWidth ? ratioWidth : img.getWidth(null);
|
|
|
+ int logoHeight = img.getHeight(null) > ratioHeight ? ratioHeight : img.getHeight(null);
|
|
|
+
|
|
|
+ int x = (image.getWidth() - logoWidth) / 2;
|
|
|
+ int y = (image.getHeight() - logoHeight) / 2;
|
|
|
+ gs.drawImage(img, x, y, logoWidth, logoHeight, null);
|
|
|
+
|
|
|
+ gs.setStroke(new BasicStroke(1));
|
|
|
+
|
|
|
+
|
|
|
+ gs.setBackground(Color.WHITE);
|
|
|
+
|
|
|
+ gs.dispose();
|
|
|
+ img.flush();
|
|
|
+ if (!ImageIO.write(image, format, file)) {
|
|
|
+ throw new Exception("不能把图片" + file + "转成" + format + " 格式 ");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public 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, matrix.get(x, y) ? this.getOnColor() : this.getBgColor());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return image;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 读二维码并输出携带的信息
|
|
|
+ */
|
|
|
+ public String readQrCode() throws Exception {
|
|
|
+ File filePath = new File(this.getFilePath());
|
|
|
+ if (!filePath.exists()) {
|
|
|
+ throw new Exception("文件不存在");
|
|
|
+ }
|
|
|
+ InputStream inputStream = new FileInputStream(filePath);
|
|
|
+
|
|
|
+ BufferedImage image = ImageIO.read(inputStream);
|
|
|
+
|
|
|
+ LuminanceSource source = new BufferedImageLuminanceSource(image);
|
|
|
+ BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
|
+ QRCodeReader reader = new QRCodeReader();
|
|
|
+ Result result = reader.decode(bitmap);
|
|
|
+ return result.getText();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 生成包含字符串信息的二维码图片
|
|
|
+ *
|
|
|
+ * @param saveImgPath 文件输出流路径
|
|
|
+ * @param content 二维码携带信息
|
|
|
+ * @param qrCodeWidth 二维码图片宽度
|
|
|
+ * @param qrCodeHeight 二维码图片高度
|
|
|
+ * @param imageFormat 二维码的格式
|
|
|
+ * @throws WriterException
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ public static boolean createQrCode(String saveImgPath, String content, int qrCodeWidth, int qrCodeHeight, String
|
|
|
+ imageFormat) throws Exception {
|
|
|
+ File filePath = new File(saveImgPath);
|
|
|
+ OutputStream outputStream = new FileOutputStream(filePath);
|
|
|
+ Hashtable<EncodeHintType, Object> hashtable = new Hashtable<>();
|
|
|
+
|
|
|
+ hashtable.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
|
|
|
+
|
|
|
+ hashtable.put(EncodeHintType.CHARACTER_SET, "utf-8");
|
|
|
+
|
|
|
+ hashtable.put(EncodeHintType.MARGIN, 1);
|
|
|
+ QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
|
|
+
|
|
|
+ BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeWidth, qrCodeHeight, hashtable);
|
|
|
+
|
|
|
+ int matrixWidth = bitMatrix.getWidth();
|
|
|
+ BufferedImage image = new BufferedImage(matrixWidth - 200, matrixWidth - 200, BufferedImage.TYPE_INT_RGB);
|
|
|
+ image.createGraphics();
|
|
|
+ Graphics2D graphics = (Graphics2D) image.getGraphics();
|
|
|
+ graphics.setColor(Color.WHITE);
|
|
|
+ graphics.fillRect(0, 0, matrixWidth, matrixWidth);
|
|
|
+ graphics.setColor(Color.BLACK);
|
|
|
+
|
|
|
+ for (int i = 0; i < matrixWidth; i++) {
|
|
|
+ for (int j = 0; j < matrixWidth; j++) {
|
|
|
+ if (bitMatrix.get(i, j)) {
|
|
|
+ graphics.fillRect(i - 100, j - 100, 1, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ImageIO.write(image, imageFormat, outputStream);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 读二维码并输出携带的信息
|
|
|
+ */
|
|
|
+ public static String readQrCode(String imgPath) throws Exception {
|
|
|
+ File filePath = new File(imgPath);
|
|
|
+ if (!filePath.exists()) {
|
|
|
+ throw new Exception("文件不存在");
|
|
|
+ }
|
|
|
+ InputStream inputStream = new FileInputStream(filePath);
|
|
|
+
|
|
|
+ BufferedImage image = ImageIO.read(inputStream);
|
|
|
+
|
|
|
+ LuminanceSource source = new BufferedImageLuminanceSource(image);
|
|
|
+ BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
|
+ QRCodeReader reader = new QRCodeReader();
|
|
|
+ Result result = reader.decode(bitmap);
|
|
|
+ return result.getText();
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getContent() {
|
|
|
+ return content;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setContent(String content) {
|
|
|
+ this.content = content;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getQrCodeUrl() {
|
|
|
+ return qrCodeUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setQrCodeUrl(String qrCodeUrl) {
|
|
|
+ this.qrCodeUrl = qrCodeUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getFilePath() {
|
|
|
+ return filePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setFilePath(String filePath) {
|
|
|
+ this.filePath = filePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getFileName() {
|
|
|
+ return fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setFileName(String fileName) {
|
|
|
+ this.fileName = fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getLogoPath() {
|
|
|
+ return logoPath;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setLogoPath(String logoPath) {
|
|
|
+ this.logoPath = logoPath;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getWidth() {
|
|
|
+ return width;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setWidth(Integer width) {
|
|
|
+ this.width = width;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getHeight() {
|
|
|
+ return height;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setHeight(Integer height) {
|
|
|
+ this.height = height;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getOnColor() {
|
|
|
+ return onColor;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setOnColor(Integer onColor) {
|
|
|
+ this.onColor = onColor;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getBgColor() {
|
|
|
+ return bgColor;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setBgColor(Integer bgColor) {
|
|
|
+ this.bgColor = bgColor;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer getMargin() {
|
|
|
+ return margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setMargin(Integer margin) {
|
|
|
+ this.margin = margin;
|
|
|
+ }
|
|
|
+
|
|
|
+ public ErrorCorrectionLevel getLevel() {
|
|
|
+ return level;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setLevel(ErrorCorrectionLevel level) {
|
|
|
+ this.level = level;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getImageFormat() {
|
|
|
+ return imageFormat;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setImageFormat(String imageFormat) {
|
|
|
+ this.imageFormat = imageFormat;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 测试代码
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|