• 【SpringBoot】生成二维码、在图片中嵌入二维码


    背景

    说明:本文章是介绍,在一张背景图片中嵌入生成的二维码和中文文字。

    用处:比如活动分享二维码的时候,提供一张背景图,然后在背景图中嵌入二维码等。

    注意:二维码和文字的位置需要你自行调整。

              

    一、依赖引入

    1. <dependency>
    2. <groupId>com.google.zxinggroupId>
    3. <artifactId>zxing-parentartifactId>
    4. <version>3.5.0version>
    5. <type>pomtype>
    6. dependency>

    二、创建工具类

    生成工具类:ImageFileUtils

    1、导入包

    1. import com.google.zxing.BarcodeFormat;
    2. import com.google.zxing.EncodeHintType;
    3. import com.google.zxing.WriterException;
    4. import com.google.zxing.common.BitMatrix;
    5. import com.google.zxing.qrcode.QRCodeWriter;
    6. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    7. import com.hvit.user.yst.request.CreateQrcodeRequest;
    8. import org.apache.commons.lang3.StringUtils;
    9. import javax.imageio.ImageIO;
    10. import javax.servlet.http.HttpServletResponse;
    11. import java.awt.*;
    12. import java.awt.image.BufferedImage;
    13. import java.io.*;
    14. import java.net.URL;
    15. import java.util.HashMap;
    16. import java.util.Map;
    17. import java.util.UUID;

    2、生成二维码

    1. // 生成二维码图片
    2. // text:二维码内容
    3. // size: 二维码尺寸
    4. private static BufferedImage generateQRCode(String text, int size) {
    5. Map hints = new HashMap<>();
    6. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    7. hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    8. try {
    9. QRCodeWriter writer = new QRCodeWriter();
    10. BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);
    11. int width = bitMatrix.getWidth();
    12. int height = bitMatrix.getHeight();
    13. BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    14. Graphics2D graphics = qrImage.createGraphics();
    15. graphics.setColor(Color.WHITE);
    16. graphics.fillRect(0, 0, size, size);
    17. graphics.setColor(Color.BLACK);
    18. for (int x = 0; x < size; x++) {
    19. for (int y = 0; y < size; y++) {
    20. if (bitMatrix.get(x, y)) {
    21. graphics.fillRect(x, y, 1, 1);
    22. }
    23. }
    24. }
    25. // 渲染二维码
    26. Graphics2D graphics1 = qrImage.createGraphics();
    27. // 添加蓝色边框
    28. int borderSize = 10; // 边框大小
    29. Color myColor = new Color(0x19, 0x76, 0xFF); // 红色
    30. graphics1.setColor(myColor);
    31. graphics1.fillRect(0, 0, size, borderSize); // 上边框
    32. graphics1.fillRect(0, 0, borderSize, size); // 左边框
    33. graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框
    34. graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框
    35. return qrImage;
    36. } catch (WriterException e) {
    37. e.printStackTrace();
    38. return null;
    39. }
    40. }

    说明:以上生成的二维码是带有蓝色边框的二维码!如图:

                                                           

    3、在背景图片上加入文字,并且居中支持\n换行

    1. // 在图片上添加图片
    2. private static void addImageToImage(BufferedImage baseImage, BufferedImage overlayImage, int x, int y) {
    3. Graphics2D g2d = baseImage.createGraphics();
    4. g2d.drawImage(overlayImage, x, y, null);
    5. g2d.dispose();
    6. }
    7. // 在图片上添加文本,支持手动换行,文本水平居中
    8. private static void addTextToImage(BufferedImage baseImage, String text, Font font, Color color, int maxWidth, int y) {
    9. Graphics2D g2d = baseImage.createGraphics();
    10. g2d.setFont(font);
    11. g2d.setColor(color);
    12. FontMetrics fm = g2d.getFontMetrics();
    13. int lineHeight = fm.getHeight();
    14. int currentY = y;
    15. String[] lines = text.split("\n");
    16. for (String line : lines) {
    17. int lineWidth = fm.stringWidth(line);
    18. int lineX = (maxWidth - lineWidth) / 2; // 居中
    19. g2d.drawString(line, lineX, currentY);
    20. currentY += lineHeight;
    21. }
    22. g2d.dispose();
    23. }

    4、调用方法

    1. public static void main(String[] args) throws Exception {
    2. // 1. 读取原始图片
    3. BufferedImage image = null;
    4. try {
    5. image = ImageIO.read(new File("C:\\Users\\caozhen\\Desktop\\图片素材\\1.png")); // 替换成您的图片路径
    6. } catch (IOException e) {
    7. e.printStackTrace();
    8. }
    9. if (image == null) {
    10. System.err.println("无法读取图片");
    11. return;
    12. }
    13. // 2. 在图片上添加透明的二维码
    14. String qrText = "https://qhdm.mzt.zj.gov.cn:9090/szmp/#/wait?code=b20267e5298948a2bca5de8d4a8081a4&type=dz&timeStrap=1694503662057"; // 替换成您的二维码文本
    15. int qrSize = 500; // 二维码尺寸
    16. BufferedImage qrCodeImage = generateQRCode(qrText, qrSize);
    17. int qrX = (image.getWidth() - qrSize) / 2;
    18. int qrY = 1050; // 设置二维码的垂直位置
    19. addImageToImage(image, qrCodeImage, qrX, qrY);
    20. // 3. 在图片上添加中文文本,支持手动换行
    21. String chineseText = "浙江省湖州市吴兴区妙西镇\n" +
    22. "妙山村下姚166号";
    23. Font font = new Font("微软雅黑", Font.BOLD, 70); // 替换成所需的字体和大小
    24. Color textColor = Color.BLACK; // 文本颜色
    25. int textX = 20; // 文本左侧的边距
    26. int textY = 800; // 设置文本的垂直位置
    27. int textWidth = image.getWidth() - 40; // 文本可用的宽度
    28. addTextToImage(image, chineseText, font, textColor, textWidth, textY);
    29. // 4. 保存带有二维码和文本的图片
    30. try {
    31. ImageIO.write(image, "png", new File("C:\\Users\\caozhen\\Desktop\\图片素材\\output.png")); // 替换成保存的文件路径
    32. } catch (IOException e) {
    33. e.printStackTrace();
    34. }
    35. }

    5、最终生成的图片成功

          

    三、如何生成透明的二维码?

    1、生成二维码

    1. // 生成透明的二维码图片
    2. private static BufferedImage generateQRCode(String text, int size) {
    3. Map hints = new HashMap<>();
    4. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    5. hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    6. hints.put(EncodeHintType.MARGIN, 0); // 无边距
    7. try {
    8. QRCodeWriter writer = new QRCodeWriter();
    9. BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);
    10. int width = bitMatrix.getWidth();
    11. int height = bitMatrix.getHeight();
    12. BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    13. // 这里就是生成透明二维码关键之处
    14. for (int x = 0; x < width; x++) {
    15. for (int y = 0; y < height; y++) {
    16. qrImage.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : new Color(0, 0, 0, 0).getRGB());
    17. }
    18. }
    19. // 渲染二维码
    20. Graphics2D graphics1 = qrImage.createGraphics();
    21. // 添加蓝色边框
    22. int borderSize = 10; // 边框大小
    23. Color myColor = new Color(0x19, 0x76, 0xFF); // 红色
    24. graphics1.setColor(myColor);
    25. graphics1.fillRect(0, 0, size, borderSize); // 上边框
    26. graphics1.fillRect(0, 0, borderSize, size); // 左边框
    27. graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框
    28. graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框
    29. return qrImage;
    30. } catch (WriterException e) {
    31. e.printStackTrace();
    32. return null;
    33. }
    34. }

     2、看看透明二维码结果

         

    四、如何希望生成的是浏览器下载图片

    1、 代码调整

    1. 1.在方法入参的时候加上HttpServletResponse response
    2. // 保存带有二维码和文本的图片
    3. // 将图片发送到浏览器
    4. response.setContentType("image/png");
    5. response.setHeader("Content-Disposition", "attachment; filename=\"output.png\"");
    6. OutputStream os = response.getOutputStream();
    7. ImageIO.write(image, "png", os);
    8. os.close();

    五、完整接口调用流程

    1.controller层

    1. @RestController
    2. @RequestMapping("/xxx/user/")
    3. @Api(value = "生成二维码", description = "生成二维码")
    4. public class QrcodeController {
    5. @RequestMapping(value = "/createAddressQrcode", method = RequestMethod.POST)
    6. public void createAddressQrcode(HttpServletResponse response) throws IOException {
    7. ImageFileUtils imageFileUtils = new ImageFileUtils();
    8. imageFileUtils.createImage(response);
    9. }
    10. }

     2、工具类ImageFileUtils

    1. public class ImageFileUtils {
    2. public void createImage(HttpServletResponse response) throws IOException {
    3. // 1. 读取原始图片
    4. BufferedImage image = null;
    5. try {
    6. //这里是读取网络图片
    7. URL url = new URL("https:xxxxxxxxxxxxxxxxxxxxxxxxxx");
    8. image = ImageIO.read(url);
    9. } catch (IOException e) {
    10. e.printStackTrace();
    11. }
    12. if (image == null) {
    13. return R.error("无法读取图片");
    14. }
    15. // 2. 在图片上添加透明的二维码
    16. String qrText = "https:xxxxxxxxxxxxxxxx"; // 替换成您的二维码文本
    17. int qrSize = 500; // 二维码尺寸
    18. BufferedImage qrCodeImage = generateQRCode(qrText, qrSize);
    19. int qrX = (image.getWidth() - qrSize) / 2;
    20. int qrY = 1050; // 设置二维码的垂直位置
    21. addImageToImage(image, qrCodeImage, qrX, qrY);
    22. // 3. 在图片上添加中文文本,支持手动换行
    23. String chineseText = createQrcodeRequest.getAddress();
    24. Font font = new Font("微软雅黑", Font.BOLD, 90); // 替换成所需的字体和大小
    25. Color textColor = Color.BLACK; // 文本颜色
    26. int textX = 20; // 文本左侧的边距
    27. int textY = 800; // 设置文本的垂直位置
    28. int textWidth = image.getWidth() - 40; // 文本可用的宽度
    29. addTextToImage(image, chineseText, font, textColor, textWidth, textY);
    30. // 4. 保存带有二维码和文本的图片
    31. // 将图片发送到浏览器
    32. response.setContentType("image/png");
    33. response.setHeader("Content-Disposition", "attachment; filename=\"output.png\"");
    34. OutputStream os = response.getOutputStream();
    35. ImageIO.write(image, "png", os);
    36. os.close();
    37. }
    38. // 生成二维码图片
    39. private static BufferedImage generateQRCode(String text, int size) {
    40. Map hints = new HashMap<>();
    41. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    42. hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    43. try {
    44. QRCodeWriter writer = new QRCodeWriter();
    45. BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);
    46. int width = bitMatrix.getWidth();
    47. int height = bitMatrix.getHeight();
    48. BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    49. Graphics2D graphics = qrImage.createGraphics();
    50. graphics.setColor(Color.WHITE);
    51. graphics.fillRect(0, 0, size, size);
    52. graphics.setColor(Color.BLACK);
    53. for (int x = 0; x < size; x++) {
    54. for (int y = 0; y < size; y++) {
    55. if (bitMatrix.get(x, y)) {
    56. graphics.fillRect(x, y, 1, 1);
    57. }
    58. }
    59. }
    60. // 渲染二维码
    61. Graphics2D graphics1 = qrImage.createGraphics();
    62. // 添加蓝色边框
    63. int borderSize = 10; // 边框大小
    64. Color myColor = new Color(0x19, 0x76, 0xFF); // 红色
    65. graphics1.setColor(myColor);
    66. graphics1.fillRect(0, 0, size, borderSize); // 上边框
    67. graphics1.fillRect(0, 0, borderSize, size); // 左边框
    68. graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框
    69. graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框
    70. return qrImage;
    71. } catch (WriterException e) {
    72. e.printStackTrace();
    73. return null;
    74. }
    75. }
    76. // 在图片上添加图片
    77. private static void addImageToImage(BufferedImage baseImage, BufferedImage overlayImage, int x, int y) {
    78. Graphics2D g2d = baseImage.createGraphics();
    79. g2d.drawImage(overlayImage, x, y, null);
    80. g2d.dispose();
    81. }
    82. // 在图片上添加文本,支持手动换行,文本水平居中
    83. private static void addTextToImage(BufferedImage baseImage, String text, Font font, Color color, int maxWidth, int y) {
    84. Graphics2D g2d = baseImage.createGraphics();
    85. g2d.setFont(font);
    86. g2d.setColor(color);
    87. FontMetrics fm = g2d.getFontMetrics();
    88. int lineHeight = fm.getHeight();
    89. int currentY = y;
    90. String[] lines = text.split("\n");
    91. for (String line : lines) {
    92. int lineWidth = fm.stringWidth(line);
    93. int lineX = (maxWidth - lineWidth) / 2; // 居中
    94. g2d.drawString(line, lineX, currentY);
    95. currentY += lineHeight;
    96. }
    97. g2d.dispose();
    98. }
    99. }

     六、注意事项

    就是当程序部署到linux服务器时,文字格式没有变化的处理方案!

    原因:就是linux服务器没有微软雅黑字体,所以导致没有效果。

    解决方案是将windows中微软雅黑字体放到linux服务器下即可。

    1、到 C:\windows\fonts 复制对应字体库,微软雅黑、宋体、黑体等,各文件后缀可能不一样,有的为ttf,有的为ttc,不影响使用。

    2、上传刚才复制的字体库到/usr/share/fonts/zh_CN目录下,如果没有该目录,用命令:mkdir /usr/share/fonts/zh_CN  来创建,然后再上传。

    3、修改字体权限,使root以外的用户可以使用这些字体:chmod -R 777 /usr/share/fonts/zh_CN,使用777 赋予全部权限

    4、重启springboot项目即可。

     总结

    好了,以上就是在图片上嵌入二维码和加入文字的代码了!

    有问题可以在评论区留言或者私信我,看到会回复你。

  • 相关阅读:
    TCP-4次挥手小记
    素数和_C语言
    PostgreSQL 数据类型详细说明
    Javascript基础
    大促前夕即高点,综合电商平台的“稀缺”魔法正在消失?
    mmdetection使用记录汇总
    MySQL 官方出品,比 mydumper 更快的多线程逻辑备份工具-MySQL Shell Dump & Load
    资源管理的部分
    前端秘法基础式(HTML)(第二卷)
    java-php-python-springboot校园自行车租赁系统计算机毕业设计
  • 原文地址:https://blog.csdn.net/qq_23126581/article/details/132854868