笔者日常: 第一次用markdown写文章,有点手生~


声明: 此工具类由本人二次整理改造后分享给大家,原编写者未知,虽然本人重写了大部分逻辑代码,但是核心部分仍然是采用的原来的代码。若涉及侵权问题,请随时联系笔者。


工具类使用示例:

  • 生成二维码:

    • 方式一
      执行方法:
     /*** 生成二维码** @date 2019/9/10 10:39*/public static String test1() throws IOException, WriterException {return QrCodeUtil.encodeQrCode("蚂蚁牙~嘿嘿", 500, 500,"C:\\Users\\JustryDeng\\Desktop\\abc\\二维码(通过方式一生成).jpg");}
    

    生成效果如图:

    • 方式二
      执行方法:
       /*** 生成二维码** @date 2019/9/10 10:39*/public static String test2() throws IOException, WriterException {return QrCodeUtil.encodeQrCodeAnotherWay("蚂蚁~~~", 500, 500,"C:\\Users\\JustryDeng\\Desktop\\abc\\二维码(通过方式二生成).jpg");}
    

    生成效果如图:

  • 生成带图片的二维码:

    执行方法:

    /*** 生成带图片的二维码** @date 2019/9/10 10:39*/
    public static String test3() throws IOException, WriterException {return QrCodeUtil.encodeQrCodeWithEmbeddedImg("我是二维码代表的数据内容", 500, 500,"C:\\Users\\JustryDeng\\Desktop\\1.png","C:\\Users\\JustryDeng\\Desktop\\abc\\带图片的二维码.jpg");
    }
    

    生成效果如图:

  • 生成带文字、带图片的二维码:

    执行方法:

    /*** 生成带文字、带图片的二维码** @date 2019/9/10 10:39*/public static String test4() throws IOException, WriterException {QrImage para = QrImage.builder().qrCodeFileOutputPath("C:\\Users\\JustryDeng\\Desktop\\abc\\带文字带图片的二维码.jpg").qrCodeContent("http://www.baidu.com").qrCodeWidth(500).qrCodeHeight(500).embeddedImgFilePath("C:\\Users\\JustryDeng\\Desktop\\1.png").wordContent("我的二维码").wordSize(20).build();return QrCodeUtil.encodeQrCodeWithEmbeddedImgAndFonts(para);
    }
    

    生成效果如图:

  • 生成带文字、不带图片的二维码:

    执行方法:

     /*** 生成带文字、不带图片的二维码** @date 2019/9/10 10:39*/public static String test5() throws IOException, WriterException {QrImage para = QrImage.builder().qrCodeFileOutputPath("C:\\Users\\JustryDeng\\Desktop\\abc\\带文字不带图片的二维码.jpg").qrCodeContent("二维码代表的数据内容~").qrCodeWidth(500).qrCodeHeight(500).wordContent("我是文字").wordSize(20).build();return QrCodeUtil.encodeQrCodeWithEmbeddedImgAndFonts(para);}
    

    生成效果如图:

  • 识别二维码:

    main方法:

    被调用方法(两种方式均可):

        /*** 识别二维码** @date 2019/9/10 10:39*/public static String test6() throws IOException, NotFoundException {return QrCodeUtil.decodeQrCode(new File("C:\\Users\\JustryDeng\\Desktop\\abc\\二维码(通过方式一生成).jpg"));}/*** 识别二维码** @date 2019/9/10 10:39*/public static String test7() throws IOException, NotFoundException {return QrCodeUtil.decodeQrCode(new FileInputStream("C:\\Users\\JustryDeng\\Desktop\\abc\\带文字带图片的二维码.jpg"));}
    

    生成效果如图:

二维码工具类,使用示例完毕!


软硬件环境说明: Windows10、IntelliJ IDEA、SpringBoot 2.1.8.RELEASE。

生成二维码、识别二维码的工具类:

  • 相关核心依赖:

 <!-- https://mvnrepository.com/artifact/com.google.zxing/core --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.4.0</version></dependency><!-- https://mvnrepository.com/artifact/com.google.zxing/javase --><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.4.0</version></dependency>

注:除了上述依赖外,本人还引入了lombok,完整的pom.xml是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.szlaozicl</groupId><artifactId>zxing-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>zxing-demo</name><description>使用zxing生成、识别二维码</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- https://mvnrepository.com/artifact/com.google.zxing/core --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.4.0</version></dependency><!-- https://mvnrepository.com/artifact/com.google.zxing/javase --><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.4.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • 相关模型:

import lombok.*;/*** 二维码图片对象** @author JustryDeng* @date 2019/9/9 15:22*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class QrImage {/** 二维码的内容(非空) */private String qrCodeContent;/** 二维码的宽度(非空) */private Integer qrCodeWidth;/** 二维码的高度(非空) */private Integer qrCodeHeight;/** 二维码内嵌图片的文件路径(为空则表示:二维码中间不嵌套图片) */private String embeddedImgFilePath;/** 文字的大小(即:正方形文字的长度、宽度)(非空) */private Integer wordSize;/** 文字的内容(非空) */private String wordContent;/** 二维码文件的输出路径(非空) */private String qrCodeFileOutputPath;
}
  • 工具类:

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.szlaozicl.zxingdemo.model.QrImage;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;/*** 二维码  工具类* <p>* 注:此工具类, 是本人整理,但不是本人编写。* <p>* 说明: 二维码是一种编码形式,* 将内容encode,得到二维码;,* 将内容decode,得到数据内容。** @author JustryDeng* @date 2019/9/9 15:11*/
@Slf4j
@SuppressWarnings("unused")
public class QrCodeUtil {/*** 嵌入的图片(被程序处理后)的高度(px)* <p>* 注:内嵌图片不应占据遮挡二维码太多,否者可能导致生成的二维码无法识别。* 建议内嵌图片的尺寸设置为二维码尺寸的1/5 或 1/4*/private static int embeddedImgDefaultWidth;/** 嵌入的图片(被程序处理后)的高度(px) */private static int embeddedImgDefaultHeight;/** 嵌入的图片与二维码图片之间的框的宽度(px) */private static int frameWidth;/** 嵌入的图片与二维码图片之间的框的颜色. */private static int frameWidthColor;/** 二维码 码的颜色 */private static int qrCodeColor;/** 二维码 背景的颜色 */private static int qrCodeBackgroundColor;/** 图片缩小后,对那些"空"下的区域补色 */private static int fillColor;/** 二维码写码器 */private static MultiFormatWriter multiFormatWriter = new MultiFormatWriter();/** 初始化基本参数*/static {QrCodeUtil.embeddedImgDefaultWidth = 80;QrCodeUtil.embeddedImgDefaultHeight = 80;QrCodeUtil.frameWidth = 0;QrCodeUtil.frameWidthColor = Color.BLUE.getRGB();QrCodeUtil.qrCodeColor = Color.BLACK.getRGB();QrCodeUtil.qrCodeBackgroundColor = Color.WHITE.getRGB();QrCodeUtil.fillColor = Color.RED.getRGB();}/*** 设置修改基本参数的参数值** @param embeddedImgDefaultWidth*         嵌入的图片(被程序处理后)的高度(px)* @param embeddedImgDefaultHeight*         嵌入的图片(被程序处理后)的高度(px)* @param frameWidth*         嵌入的图片与二维码图片之间的框的宽度(px)* @param frameWidthColor*         嵌入的图片与二维码图片之间的框的颜色* @param qrCodeColor*         二维码 码的颜色* @param qrCodeBackgroundColor*         二维码 背景的颜色* @param fillColor*         图片缩小后,对那些"空"下的区域补色* @date 2019/9/9 22:47*/public static void modifyBasicParamsValues(Integer embeddedImgDefaultWidth,Integer embeddedImgDefaultHeight,Integer frameWidth,Color frameWidthColor,Color qrCodeColor,Color qrCodeBackgroundColor,Color fillColor) {if (embeddedImgDefaultWidth != null) {QrCodeUtil.embeddedImgDefaultWidth = embeddedImgDefaultWidth;}if (embeddedImgDefaultHeight != null) {QrCodeUtil.embeddedImgDefaultHeight = embeddedImgDefaultHeight;}if (frameWidth != null) {QrCodeUtil.frameWidth = frameWidth;}if (frameWidthColor != null) {QrCodeUtil.frameWidthColor = frameWidthColor.getRGB();}if (qrCodeColor != null) {QrCodeUtil.qrCodeColor = qrCodeColor.getRGB();}if (qrCodeBackgroundColor != null) {QrCodeUtil.qrCodeBackgroundColor = qrCodeBackgroundColor.getRGB();}if (fillColor != null) {QrCodeUtil.fillColor = fillColor.getRGB();}}/*** 生成二维码(到destImagePath指向的File) --- 方式一** @param content*         二维码的内容* @param width*         二维码的宽度(px)* @param height*         二维码的高度(px)* @param destImagePath*         生成二维码图片的地址** @return 生成的二维码文件path* @throws IOException IOException* @throws WriterException WriterException** @date 2019/9/9 16:43*/public static String encodeQrCode(String content, int width, int height, String destImagePath)throws IOException, WriterException {File dest = getFile(destImagePath);// 图像类型String format = "jpg";Map<EncodeHintType, Object> hints = new HashMap<>(4);hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");try (FileOutputStream output = new FileOutputStream(dest)) {// 生成矩阵BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE,width, height, hints);// 输出图像MatrixToImageWriter.writeToStream(bitMatrix, format, output);}return destImagePath;}/*** 生成二维码(到destImagePath指向的File) --- 方式二** @param content*         二维码的内容* @param width*         二维码的宽度(px)* @param height*         二维码的高度(px)* @param destImagePath*         生成二维码图片的地址** @return 生成的二维码文件path* @throws IOException IOException* @throws WriterException WriterException** @date 2019/9/9 16:43*/public static String encodeQrCodeAnotherWay(String content, int width, int height, String destImagePath)throws IOException, WriterException {boolean result = ImageIO.write(genBufferedImage(content, width, height), "jpg", getFile(destImagePath));log.info(" generate Qr code file {} {}", destImagePath, result ? "success" : "fail");return destImagePath;}/*** 生成带图片的二维码(到destImagePath指向的File)** @param content*         二维码的内容* @param width*         二维码的宽度(px)* @param height*         二维码的高度(px)* @param embeddedImgPath*         被镶嵌的图片的地址* @param destImagePath*         生成二维码图片的地址** @return 生成的二维码文件path* @throws IOException IOException* @throws WriterException WriterException** @date 2019/9/9 15:13*/public static String encodeQrCodeWithEmbeddedImg(String content, int width, int height,String embeddedImgPath, String destImagePath)throws IOException, WriterException {boolean result = ImageIO.write(genBufferedImageWithEmbeddedImg(content, width, height, embeddedImgPath),"jpg",getFile(destImagePath));log.info(" generate Qr code file {} {}", destImagePath, result ? "success" : "fail");return destImagePath;}/*** 生成带图片的二维码(到outputStream流)** @param content*         二维码的内容* @param width*         二维码的宽度(px)* @param height*         二维码的高度(px)* @param embeddedImgPath*         被镶嵌的图片的地址*         注:被镶嵌的图片,如果尺寸** @throws IOException IOException* @throws WriterException WriterException** @date 2019/9/9 16:43*/public static void encodeQrCodeWithEmbeddedImg(String content, int width, int height,String embeddedImgPath, OutputStream outputStream)throws IOException, WriterException {boolean result = ImageIO.write(genBufferedImageWithEmbeddedImg(content, width, height, embeddedImgPath),"jpg",outputStream);log.info(" generate Qr code file to OutputStream {}",  result ? "success" : "fail");}/*** 生成上方带内嵌图片、带文字的二维码* <p>* 注:若 嵌入的图片的参数值为null 或者为 空的字符,那么 只生成带文字的二维码** @param param*         参数模型** @return 生成的二维码文件path* @throws IOException IOException* @throws WriterException WriterException** @date 2019/9/10 0:11*/public static String encodeQrCodeWithEmbeddedImgAndFonts(QrImage param)throws IOException, WriterException {// 首先生成二维码图片BufferedImage qrImage;String embeddedImgFilePath = param.getEmbeddedImgFilePath();String qrCodeContent = param.getQrCodeContent();Integer qrCodeWidth = param.getQrCodeWidth();Integer qrCodeHeight = param.getQrCodeHeight();if (embeddedImgFilePath == null || embeddedImgFilePath.trim().length() == 0) {qrImage = genBufferedImage(qrCodeContent, qrCodeWidth, qrCodeHeight);} else {qrImage = genBufferedImageWithEmbeddedImg(qrCodeContent, qrCodeWidth,qrCodeHeight, embeddedImgFilePath);}int qrCodeImageWidth = qrImage.getWidth();int qrCodeImageHeight = qrImage.getHeight();String[] splitStrLines;splitStrLines = splitStrLines(param.getWordContent(), qrCodeImageWidth / param.getWordSize());// 文字图片的高度 = 文字行数 * 每行高度(文字高度) + 10px;// 为了防止 文字图片 下面部分显示不全, 特意在这里额外加10像素的高度。int fontsImageHeight = splitStrLines.length * param.getWordSize() + 10;// 创建顶部文字的图片BufferedImage imageWithFontsBufferedImage = new BufferedImage(qrCodeImageWidth,fontsImageHeight, BufferedImage.TYPE_4BYTE_ABGR);Graphics fontsImageGraphics = imageWithFontsBufferedImage.getGraphics();fontsImageGraphics.fillRect(0, 0, qrCodeImageWidth, fontsImageHeight);fontsImageGraphics.setColor(Color.black);fontsImageGraphics.setFont(new Font("宋体", Font.PLAIN, param.getWordSize()));// 文字长度大于一行的长度,进行分行// 每行限制的文字个数if (param.getWordContent().length() > qrCodeImageWidth / param.getWordSize()) {for (int i = 0; i < splitStrLines.length; i++) {fontsImageGraphics.drawString(splitStrLines[i], 0, param.getWordSize() * (i + 1));}} else {fontsImageGraphics.drawString(param.getWordContent(),// 总长度减去字长度除以2为向右偏移长度((qrCodeImageWidth / param.getWordSize() - param.getWordContent().length()) / 2) * param.getWordSize(),param.getWordSize());}// 从图片中读取RGBint[] imageArrayFonts = new int[qrCodeImageWidth * fontsImageHeight];imageArrayFonts = imageWithFontsBufferedImage.getRGB(0, 0, qrCodeImageWidth,fontsImageHeight, imageArrayFonts, 0, qrCodeImageWidth);int[] imageArrayQr = new int[qrCodeImageWidth * qrCodeImageHeight];imageArrayQr = qrImage.getRGB(0, 0, qrCodeImageWidth, qrCodeImageHeight,imageArrayQr, 0, qrCodeImageWidth);// 生成新图片(在setsetRGB时,通过控制图像的startX与startY, 可达到不同的拼接效果)BufferedImage newBufferedImage = new BufferedImage(qrCodeImageWidth,qrCodeImageHeight + fontsImageHeight, BufferedImage.TYPE_INT_RGB);// 图片在上, 文字在下// 设置上半部分的RGBnewBufferedImage.setRGB(0, 0, qrCodeImageWidth, qrCodeImageHeight,imageArrayQr, 0, qrCodeImageWidth);// 设置下半部分的RGBnewBufferedImage.setRGB(0, qrCodeImageHeight, qrCodeImageWidth,fontsImageHeight, imageArrayFonts, 0, qrCodeImageWidth);// 文字在上,图片在下//  // 设置上半部分的RGB///  newBufferedImage.setRGB(0, 0, qrCodeImageWidth, fontsImageHeight, imageArrayFonts, 0, qrCodeImageWidth);//  // 设置下半部分的RGB///  newBufferedImage.setRGB(0, fontsImageHeight, qrCodeImageWidth, qrCodeImageHeight, imageArrayQr, 0, qrCodeImageWidth);String qrCodeFileOutputPath = param.getQrCodeFileOutputPath();File outFile = getFile(qrCodeFileOutputPath);boolean result = ImageIO.write(newBufferedImage, "jpg", outFile);log.info(" generate Qr code file {} {}", qrCodeFileOutputPath, result ? "success" : "fail");return qrCodeFileOutputPath;}/*** 识别二维码内容信息** @param file 二维码图片文件** @return  二维码内容* @throws NotFoundException NotFoundException* @throws IOException IOException* @date 2019/9/10 1:59*/public static String decodeQrCode(File file) throws NotFoundException, IOException {BufferedImage image;image = ImageIO.read(file);if (image == null) {return null;}String data = decodeQrCode(image);log.info(" Qr code from [{}] data is -> {}", file.getAbsolutePath(), data);return data;}/*** 识别二维码内容信息** @param is 二维码图片文件流** @return  二维码内容* @throws NotFoundException NotFoundException* @throws IOException IOException* @date 2019/9/10 1:59*/public static String decodeQrCode(InputStream is) throws NotFoundException, IOException {BufferedImage image;image = ImageIO.read(is);if (image == null) {return null;}String data = decodeQrCode(image);log.info(" Qr code from InputStream data is -> {}", data);return data;}/// --------------------------------------------------------以下为辅助方法、辅助类/*** 获取文件(顺带创建文件夹,如果需要的话)** @param filePath*            文件path* @return  文件对象* @date 2019/9/10 10:48*/private static File getFile(String filePath) {File file = new File(filePath);if (!file.getParentFile().exists()) {boolean result = file.getParentFile().mkdirs();log.info(" create directory {} {}", file.getParent(), result);}return file;}/*** 识别二维码内容信息** @param image 二维码图片信息BufferedImage** @return  二维码内容* @throws NotFoundException NotFoundException* @date 2019/9/10 1:59*/private static String decodeQrCode(BufferedImage image) throws NotFoundException {BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Result result;HashMap<DecodeHintType, Object> hints = new HashMap<>(4);hints.put(DecodeHintType.CHARACTER_SET, "utf-8");result = new MultiFormatReader().decode(bitmap, hints);return result.getText();}/*** 生成二维码图片信息BufferedImage* <p>* 注:BufferedImage即为二维码图片的数据容器,可以利用其进一步生成二维码图片** @param content*         二维码的数据内容* @param width*         二维码的宽(px)* @param height*         二维码的高(px)** @return 二维码图片信息BufferedImage* @throws WriterException WriterException* @date 2019/9/9 16:39*/private static BufferedImage genBufferedImage(String content, int width, int height)throws WriterException {Map<EncodeHintType, Object> hints = getHints();// 生成一个矩阵(即:生成一个二维数组)BitMatrix matrix;matrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hints);int[] pixels = new int[width * height];for (int y = 0; y < matrix.getHeight(); y++) {for (int x = 0; x < matrix.getWidth(); x++) {// 控制二维码颜色, 前面那个为 二维码的颜色, 后面那个为底色pixels[y * width + x] = matrix.get(x, y) ? qrCodeColor : qrCodeBackgroundColor;}}BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);image.getRaster().setDataElements(0, 0, width, height, pixels);return image;}/*** 生成(带内嵌图片的)二维码图片信息BufferedImage* <p>* 注:BufferedImage即为二维码图片的数据容器,可以利用其进一步生成二维码图片** @param content*         二维码的数据内容* @param width*         二维码的宽(px)* @param height*         二维码的高(px)* @param embeddedImagePath*         二维码中要嵌套的图片path** @return 二维码图片信息BufferedImage* @throws IOException IOException* @throws WriterException WriterException* @date 2019/9/9 16:39*/private static BufferedImage genBufferedImageWithEmbeddedImg(String content, int width,int height, String embeddedImagePath)throws WriterException, IOException {// 读取要嵌套的图像,并将其压缩到指定的宽高BufferedImage scaleImage = scale(embeddedImagePath, embeddedImgDefaultWidth,embeddedImgDefaultHeight, false);int embeddedImgFinalWidth = scaleImage.getWidth();int embeddedImgFinalHalfWidth = embeddedImgFinalWidth / 2;int embeddedImgFinalHeight = scaleImage.getHeight();int embeddedImgFinalHalfHeight = embeddedImgFinalHeight / 2;int[][] srcPixels = new int[embeddedImgFinalWidth][embeddedImgFinalHeight];for (int i = 0; i < embeddedImgFinalWidth; i++) {for (int j = 0; j < embeddedImgFinalHeight; j++) {srcPixels[i][j] = scaleImage.getRGB(i, j);}}Map<EncodeHintType, Object> hint = getHints();// 生成一个矩阵(即:生成一个二维数组)( 注:下面会在这个矩阵上绘图)BitMatrix matrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, width, height, hint);// 二维码矩阵转为一维像素数组int qrCodeHalfWidth = matrix.getWidth() / 2;int qrCodeHalfHeight = matrix.getHeight() / 2;int[] pixels = new int[width * height];// 是否处于【嵌入图片 与 二维码图片 之间的框】里boolean atEmbeddedImgFrameArea;// 是否处于【嵌入图片的位置】里boolean atEmbeddedImgArea;// 内嵌的图片(左下角) 在 二维码图片 中的坐标Xint embeddedImgCoordinatesX = qrCodeHalfWidth - embeddedImgFinalHalfWidth;// 内嵌的图片(左下角) 在 二维码图片 中的坐标Yint embeddedImgCoordinatesY = qrCodeHalfHeight - embeddedImgFinalHalfHeight;for (int y = 0; y < matrix.getHeight(); y++) {for (int x = 0; x < matrix.getWidth(); x++) {atEmbeddedImgArea = x > qrCodeHalfWidth - embeddedImgFinalHalfWidth&& x < qrCodeHalfWidth + embeddedImgFinalHalfWidth&& y > qrCodeHalfHeight - embeddedImgFinalHalfHeight&& y < qrCodeHalfHeight + embeddedImgFinalHalfHeight;atEmbeddedImgFrameArea = (x > qrCodeHalfWidth - embeddedImgFinalHalfWidth - frameWidth&& x < qrCodeHalfWidth - embeddedImgFinalHalfWidth + frameWidth&& y > qrCodeHalfHeight - embeddedImgFinalHalfHeight - frameWidth&& y < qrCodeHalfHeight + embeddedImgFinalHalfHeight + frameWidth)||(x > qrCodeHalfWidth + embeddedImgFinalHalfWidth - frameWidth&& x < qrCodeHalfWidth + embeddedImgFinalHalfWidth + frameWidth&& y > qrCodeHalfHeight - embeddedImgFinalHalfHeight - frameWidth&& y < qrCodeHalfHeight + embeddedImgFinalHalfHeight + frameWidth)||(x > qrCodeHalfWidth - embeddedImgFinalHalfWidth - frameWidth&& x < qrCodeHalfWidth + embeddedImgFinalHalfWidth + frameWidth&& y > qrCodeHalfHeight - embeddedImgFinalHalfHeight - frameWidth&& y < qrCodeHalfHeight - embeddedImgFinalHalfHeight + frameWidth)||(x > qrCodeHalfWidth - embeddedImgFinalHalfWidth - frameWidth&& x < qrCodeHalfWidth + embeddedImgFinalHalfWidth + frameWidth&& y > qrCodeHalfHeight + embeddedImgFinalHalfHeight - frameWidth&& y < qrCodeHalfHeight + embeddedImgFinalHalfHeight + frameWidth);// 在二维码矩阵数像素组里 嵌入 嵌入图片的像素数组if (atEmbeddedImgArea) {pixels[y * width + x] = srcPixels[x - embeddedImgCoordinatesX][y - embeddedImgCoordinatesY];}// 嵌入图片 与 二维码图片 之间的框(设置其颜色)else if (atEmbeddedImgFrameArea) {pixels[y * width + x] = frameWidthColor;// 二维码图片区域} else {// 控制二维码颜色, 前面那个为 二维码的颜色, 后面那个为底色pixels[y * width + x] = matrix.get(x, y) ? qrCodeColor : qrCodeBackgroundColor;}}}BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);image.getRaster().setDataElements(0, 0, width, height, pixels);return image;}/*** 获取hint信息** @return hint* @date 2019/9/10 1:14*/private static Map<EncodeHintType, Object> getHints() {Map<EncodeHintType, Object> hint = new HashMap<>(8);hint.put(EncodeHintType.CHARACTER_SET, "utf-8");hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 二维码整体白框hint.put(EncodeHintType.MARGIN, 1);return hint;}/*** 把传入的原始图像按高度(或宽度)进行缩小,生成符合要求的图标的BufferedImage信息* <p>* 注:若图片原来的大小比给定的宽高小,那么不会进行放大,而是仍然保持原来的大小。** @param srcImageFile*         源文件地址* @param width*         (缩小后的)宽度* @param height*         (缩小后的)高度* @param autoFill*         是否对按比例缩小后的图片进行填充,使其完全达到给定的宽高。*         <p>*         注:图片按照最长边与对应的宽(或高)的比例缩小后,最长边缩小后的尺寸与给定的宽(或高)一致了,*         但是其高(或宽),与缩小后的最短边不一定一样。此时,我们可以考虑使用给定的颜色对*         其进行填充。如: 想要嵌入进去的图片的实际宽是80, 高是100; 但是这里指定缩小后的尺寸为*         宽为10,高为10。 由下面的逻辑可知:缩小比例为0.1, 缩小后,图片的宽就变成了8,高就变*         成了10,此时高是满足我们的要求的,但是宽差了2个像素。此时就可以将其进行填充了。*         <p>*         注:建议为false。** @return 图片的BufferedImage信息* @throws IOException IOException* @date 2019/9/10 1:59*/private static BufferedImage scale(String srcImageFile, int width, int height, boolean autoFill)throws IOException {// 缩小比例double ratio;File file = getFile(srcImageFile);BufferedImage srcImage = ImageIO.read(file);Image destImage = srcImage.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);// 如果原图片的高或者宽 大于 指定的高或宽时,(以最长的一边来计算缩放比例,并)进行缩放if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {if (srcImage.getHeight() > srcImage.getWidth()) {ratio = (new Integer(height)).doubleValue() / srcImage.getHeight();} else {ratio = (new Integer(width)).doubleValue() / srcImage.getWidth();}AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio),null);destImage = op.filter(srcImage, null);}if (autoFill) {BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D graphic = image.createGraphics();graphic.setColor(Color.red);graphic.fillRect(0, 0, width, height);if (width == destImage.getWidth(null)) {graphic.drawImage(destImage, 0, (height - destImage.getHeight(null)) / 2,destImage.getWidth(null),destImage.getHeight(null), Color.white, null);} else {graphic.drawImage(destImage, (width - destImage.getWidth(null)) / 2, 0,destImage.getWidth(null),destImage.getHeight(null), Color.white, null);}graphic.dispose();destImage = image;}return (BufferedImage) destImage;}/*** 一行字符串拆分成多行*/private static String[] splitStrLines(String str, int len) {int blocks = str.length() / len + 1;String[] strArray = new String[blocks];for (int i = 0; i < blocks; i++) {if ((i + 1) * len > str.length()) {strArray[i] = str.substring(i * len);} else {strArray[i] = str.substring(i * len, (i + 1) * len);}}return strArray;}/*** Writes a {@link BitMatrix} to {@link BufferedImage},* file or stream. Provided here instead of core since it depends on* Java SE libraries.*/private static class MatrixToImageWriter {private static final MatrixToImageConfig DEFAULT_CONFIG = new MatrixToImageConfig();private MatrixToImageWriter() {}/*** Renders a {@link BitMatrix} as an image, where "false" bits are rendered* as white, and "true" bits are rendered as black.*/private static BufferedImage toBufferedImage(BitMatrix matrix) {return toBufferedImage(matrix, DEFAULT_CONFIG);}/*** As {@link #toBufferedImage(BitMatrix)}, but allows customization of the output.*/private static BufferedImage toBufferedImage(BitMatrix matrix, MatrixToImageConfig config) {int width = matrix.getWidth();int height = matrix.getHeight();BufferedImage image = new BufferedImage(width, height, config.getBufferedImageColorModel());int onColor = config.getPixelOnColor();int offColor = config.getPixelOffColor();for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, matrix.get(x, y) ? onColor : offColor);}}return image;}/*** @deprecated use {@link #writeToPath(BitMatrix, String, Path)}*/@Deprecatedprivate static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {writeToPath(matrix, format, file.toPath());}/*** Writes a {@link BitMatrix} to a file.** @see #toBufferedImage(BitMatrix)*/private static void writeToPath(BitMatrix matrix, String format, Path file) throws IOException {writeToPath(matrix, format, file, DEFAULT_CONFIG);}/*** @deprecated use {@link #writeToPath(BitMatrix, String, Path, MatrixToImageConfig)}*/@Deprecatedprivate static void writeToFile(BitMatrix matrix, String format, File file,MatrixToImageConfig config) throws IOException {writeToPath(matrix, format, file.toPath(), config);}/*** As {@link #writeToFile(BitMatrix, String, File)}, but allows customization of the output.*/@SuppressWarnings("all")private static void writeToPath(BitMatrix matrix, String format, Path file,MatrixToImageConfig config) throws IOException {BufferedImage image = toBufferedImage(matrix, config);if (!ImageIO.write(image, format, file.toFile())) {throw new IOException("Could not write an image of format " + format + " to " + file);}}/*** Writes a {@link BitMatrix} to a stream.** @see #toBufferedImage(BitMatrix)*/private static void writeToStream(BitMatrix matrix, String format, OutputStream stream)throws IOException {writeToStream(matrix, format, stream, DEFAULT_CONFIG);}/*** As {@link #writeToStream(BitMatrix, String, OutputStream)}, but allows customization* of the output.*/private static void writeToStream(BitMatrix matrix, String format, OutputStream stream,MatrixToImageConfig config) throws IOException {BufferedImage image = toBufferedImage(matrix, config);if (!ImageIO.write(image, format, stream)) {throw new IOException("Could not write an image of format 【" + format + "】");}}/*** 配置类封装* <p>* Encapsulates custom configuration used in methods of {@link MatrixToImageWriter}.*/private static class MatrixToImageConfig {private static final int BLACK = Color.BLACK.getRGB();private static final int WHITE = Color.WHITE.getRGB();private final int onColor;private final int offColor;/*** Creates a default config with on color {@link #BLACK} and off color {@link #WHITE},* generating normal* black-on-white barcodes.*/private MatrixToImageConfig() {this(BLACK, WHITE);}/*** @param onColor*         pixel on color, specified as an ARGB value as an int* @param offColor*         pixel off color, specified as an ARGB value as an int*/private MatrixToImageConfig(int onColor, int offColor) {this.onColor = onColor;this.offColor = offColor;}private int getPixelOnColor() {return onColor;}private int getPixelOffColor() {return offColor;}private int getBufferedImageColorModel() {// Use faster BINARY if colors match defaultreturn onColor == BLACK && offColor == WHITE? BufferedImage.TYPE_BYTE_BINARY : BufferedImage.TYPE_INT_RGB;}}}
}

声明: 此工具类由本人二次整理改造后分享给大家,原编写者未知,虽然本人重写了大部分逻辑代码,但是核心部分仍然是采用的原来的代码。若涉及侵权问题,请随时联系笔者。


^_^ 如有不当之处,欢迎指正

^_^ 参考链接
        https://blog.csdn.net/jam_fanatic/article/details/82818857

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

生成二维码、识别二维码的工具类相关推荐

  1. iOS二维码识别/二维码生成

    文章目录 前言 扫一扫识别二维码图片 长按图片识别二维码图片 生成二维码图片 代码完善 识别二维码图片优化 小结 前言 最近在做一个关于二维码的组件,已发布,现总结下. 开发的APP所需支持的最低版本 ...

  2. 小程序实现扫码识别二维码内容

    前言 在开发程序过程中经常和二维码打交道,经常要查看二维码的内容是什么,所以决定自己开发一个可以识别二维码,生成二维码的小工具. 一.项目展示 用户可以识别生活中常见的支持条码.二维码.DataMat ...

  3. android扫码二维码识别二维码

    1. 快速集成扫码二维码,识别二维码功能.经过加工处理优化的,直接返回扫码结果字符串和图片的bitmap数据. 直接上代码: package com.xinxinchelian.myscanzxing ...

  4. WinForm调用摄像头扫码识别二维码

    前言 因公司业务需求,需要在Windows系统下调用摄像头识别二维码需求,就有了这个功能.根据网上网友提供的一些资料,自己整合应用到项目中,效果还不错(就是感觉像素不是太好).现在将调用摄像头+识别二 ...

  5. uniapp 扫码识别(一维码、二维码)

    注:需开启扫码功能,首先要在manifest.json配置中打开APP模块配置中 Barcode(扫码).Camera&Gallery(相机和相册) 自带扫码插件:uni.scanCode(O ...

  6. 如何使用h5-scan-qrcode插件实现一个h5页面扫码识别二维码功能

    为了适应公司代码全程使用jquery构造 如需其他js或者vue 可根据此代码去改(因为好多地方会用到这个东西所以我封装成了一个js文件) https://dragonir.github.io/h5- ...

  7. Opencv+Zbar二维码识别(一维码校正)

    一维码由一组规则排列的黑色线条.白色线条以及对应的字符组成.对倾斜的(没有严重形变)一维码的角度校正,可以根据其黑白相间.排列规则的特点,计算傅里叶频谱,通过傅里叶频谱中直线的倾斜角度计算空间域图像一 ...

  8. 【Java源码分析】集合框架-Collections工具类-Arrays工具类

    集合框架Collection 和Collections和Arrays工具类 一开始总是搞不清楚Collection和Collections的区别,不过看下代码应该很清楚,一个是接口,一个是工具类 Co ...

  9. mp4视频获取时长、封面图、编码、转码(mpeg4转h264)工具类

    application.properties server.port=8908 file.uploadfolder=D:/school/ #分片文件临时目录 file.chunkfolder=D:/s ...

  10. Java使用ftl模板文件生成Word,以及Word转换图片或Pdf工具类

    Java使用ftl模板文件生成Word 一.写在前面 最近在项目中使用打印功能,发现这个功能我已经写过多次了,下面这个文章的发步日期在2020年,不得不感慨时间之快啊. https://blog.cs ...

最新文章

  1. AI 算法给手画线稿自动上色指南来了
  2. 利用SeekFree的核心板调试MM32F3277的ISP功能
  3. 冠军杜兰特和Deta比赛
  4. java 序列化 例子_Java序列化和反序列化例子
  5. UML学生成绩管理系统需求分析
  6. 按钮旁边加一个提示_地铁站的那些“红色按钮”,你知道是干啥用的吗?乱按可能被拘留...
  7. python爬虫urllib 数据处理_Python 爬虫笔记之Urllib的用法
  8. 郝蕾怒骂河南人---江湖再起风云,网络哪里有净土
  9. oracle表设计实践,Oracle数据库实训报告.docx
  10. MFC开发IM-第十九篇、获取编辑框内容,并且追加内容
  11. 一加7是什么协议_刘作虎“拔钉”成功:大量一加5、一加3用户入手一加8T
  12. iis支持java吗_如何让iis支持jsp,servlet
  13. 2022爱分析・汽车行业数字化实践报告
  14. [Matlab]维纳滤波器设计
  15. 金蝶K3工业单据中间层插件开发教程
  16. Kali Linux信息收集工具全集
  17. 【新知实验室 TRTCIM】实时互动课堂最佳实践
  18. Alphabetic Removals
  19. 非常高兴可以订购到龙芯电脑
  20. 什么是Java(什么?Java?)

热门文章

  1. “Internet explorer已阻止此网站显示有安全证书错误的内容”“iTunes无法授权”的解决方法
  2. linux操作系统_Linux操作系统与使用
  3. Traceback抛出详细错误信息
  4. gif透明背景动画_iPad 手绘进阶指南!这份Procreate保姆级教程,自制动画只要 3 分钟...
  5. 在CentOS8上实现私有CA和证书申请
  6. Android 和dialog 防录屏功能失效,游戏防录屏功能失效.
  7. adc去质器什么意思_谁是最强ADC去质器?图1一般,图3还行,图4一秒一个ADC
  8. jquery.ztree 打开父节点_增额终身寿险的正确打开方式
  9. cortona3d介绍以及软件下载安装使用
  10. integer最后一位四舍五入_解决toFixed四舍五入陷阱