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

背景

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

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

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

          

一、依赖引入

        <!-- https://mvnrepository.com/artifact/com.google.zxing/zxing-parent --><dependency><groupId>com.google.zxing</groupId><artifactId>zxing-parent</artifactId><version>3.5.0</version><type>pom</type></dependency>

二、创建工具类

生成工具类:ImageFileUtils

1、导入包

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.hvit.user.yst.request.CreateQrcodeRequest;
import org.apache.commons.lang3.StringUtils;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

2、生成二维码

    // 生成二维码图片// text:二维码内容// size: 二维码尺寸private static BufferedImage generateQRCode(String text, int size) {Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");try {QRCodeWriter writer = new QRCodeWriter();BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);Graphics2D graphics = qrImage.createGraphics();graphics.setColor(Color.WHITE);graphics.fillRect(0, 0, size, size);graphics.setColor(Color.BLACK);for (int x = 0; x < size; x++) {for (int y = 0; y < size; y++) {if (bitMatrix.get(x, y)) {graphics.fillRect(x, y, 1, 1);}}}// 渲染二维码Graphics2D graphics1 = qrImage.createGraphics();// 添加蓝色边框int borderSize = 10; // 边框大小Color myColor = new Color(0x19, 0x76, 0xFF); // 红色graphics1.setColor(myColor);graphics1.fillRect(0, 0, size, borderSize); // 上边框graphics1.fillRect(0, 0, borderSize, size); // 左边框graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框return qrImage;} catch (WriterException e) {e.printStackTrace();return null;}}

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

                                                       

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

    // 在图片上添加图片private static void addImageToImage(BufferedImage baseImage, BufferedImage overlayImage, int x, int y) {Graphics2D g2d = baseImage.createGraphics();g2d.drawImage(overlayImage, x, y, null);g2d.dispose();}// 在图片上添加文本,支持手动换行,文本水平居中private static void addTextToImage(BufferedImage baseImage, String text, Font font, Color color, int maxWidth, int y) {Graphics2D g2d = baseImage.createGraphics();g2d.setFont(font);g2d.setColor(color);FontMetrics fm = g2d.getFontMetrics();int lineHeight = fm.getHeight();int currentY = y;String[] lines = text.split("\n");for (String line : lines) {int lineWidth = fm.stringWidth(line);int lineX = (maxWidth - lineWidth) / 2; // 居中g2d.drawString(line, lineX, currentY);currentY += lineHeight;}g2d.dispose();}

4、调用方法

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

5、最终生成的图片成功

      

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

1、生成二维码

    // 生成透明的二维码图片private static BufferedImage generateQRCode(String text, int size) {Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");hints.put(EncodeHintType.MARGIN, 0); // 无边距try {QRCodeWriter writer = new QRCodeWriter();BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);// 这里就是生成透明二维码关键之处for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {qrImage.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : new Color(0, 0, 0, 0).getRGB());}}// 渲染二维码Graphics2D graphics1 = qrImage.createGraphics();// 添加蓝色边框int borderSize = 10; // 边框大小Color myColor = new Color(0x19, 0x76, 0xFF); // 红色graphics1.setColor(myColor);graphics1.fillRect(0, 0, size, borderSize); // 上边框graphics1.fillRect(0, 0, borderSize, size); // 左边框graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框return qrImage;} catch (WriterException e) {e.printStackTrace();return null;}}

 2、看看透明二维码结果

     

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

1、 代码调整

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

五、完整接口调用流程

1.controller层

@RestController
@RequestMapping("/xxx/user/")
@Api(value = "生成二维码", description = "生成二维码")
public class QrcodeController {@RequestMapping(value = "/createAddressQrcode", method = RequestMethod.POST)public void createAddressQrcode(HttpServletResponse response) throws IOException {ImageFileUtils imageFileUtils = new ImageFileUtils();imageFileUtils.createImage(response);}}

 2、工具类ImageFileUtils

public class ImageFileUtils {public void createImage(HttpServletResponse response) throws IOException {// 1. 读取原始图片BufferedImage image = null;try {//这里是读取网络图片URL url = new URL("https:xxxxxxxxxxxxxxxxxxxxxxxxxx");image = ImageIO.read(url);} catch (IOException e) {e.printStackTrace();}if (image == null) {return R.error("无法读取图片");}// 2. 在图片上添加透明的二维码String qrText = "https:xxxxxxxxxxxxxxxx"; // 替换成您的二维码文本int qrSize = 500; // 二维码尺寸BufferedImage qrCodeImage = generateQRCode(qrText, qrSize);int qrX = (image.getWidth() - qrSize) / 2;int qrY = 1050; // 设置二维码的垂直位置addImageToImage(image, qrCodeImage, qrX, qrY);// 3. 在图片上添加中文文本,支持手动换行String chineseText = createQrcodeRequest.getAddress();Font font = new Font("微软雅黑", Font.BOLD, 90); // 替换成所需的字体和大小Color textColor = Color.BLACK; // 文本颜色int textX = 20; // 文本左侧的边距int textY = 800; // 设置文本的垂直位置int textWidth = image.getWidth() - 40; // 文本可用的宽度addTextToImage(image, chineseText, font, textColor, textWidth, textY);// 4. 保存带有二维码和文本的图片// 将图片发送到浏览器response.setContentType("image/png");response.setHeader("Content-Disposition", "attachment; filename=\"output.png\"");OutputStream os = response.getOutputStream();ImageIO.write(image, "png", os);os.close();}// 生成二维码图片private static BufferedImage generateQRCode(String text, int size) {Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");try {QRCodeWriter writer = new QRCodeWriter();BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE, size, size, hints);int width = bitMatrix.getWidth();int height = bitMatrix.getHeight();BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);Graphics2D graphics = qrImage.createGraphics();graphics.setColor(Color.WHITE);graphics.fillRect(0, 0, size, size);graphics.setColor(Color.BLACK);for (int x = 0; x < size; x++) {for (int y = 0; y < size; y++) {if (bitMatrix.get(x, y)) {graphics.fillRect(x, y, 1, 1);}}}// 渲染二维码Graphics2D graphics1 = qrImage.createGraphics();// 添加蓝色边框int borderSize = 10; // 边框大小Color myColor = new Color(0x19, 0x76, 0xFF); // 红色graphics1.setColor(myColor);graphics1.fillRect(0, 0, size, borderSize); // 上边框graphics1.fillRect(0, 0, borderSize, size); // 左边框graphics1.fillRect(size - borderSize, 0, borderSize, size); // 右边框graphics1.fillRect(0, size - borderSize, size, borderSize); // 下边框return qrImage;} catch (WriterException e) {e.printStackTrace();return null;}}// 在图片上添加图片private static void addImageToImage(BufferedImage baseImage, BufferedImage overlayImage, int x, int y) {Graphics2D g2d = baseImage.createGraphics();g2d.drawImage(overlayImage, x, y, null);g2d.dispose();}// 在图片上添加文本,支持手动换行,文本水平居中private static void addTextToImage(BufferedImage baseImage, String text, Font font, Color color, int maxWidth, int y) {Graphics2D g2d = baseImage.createGraphics();g2d.setFont(font);g2d.setColor(color);FontMetrics fm = g2d.getFontMetrics();int lineHeight = fm.getHeight();int currentY = y;String[] lines = text.split("\n");for (String line : lines) {int lineWidth = fm.stringWidth(line);int lineX = (maxWidth - lineWidth) / 2; // 居中g2d.drawString(line, lineX, currentY);currentY += lineHeight;}g2d.dispose();}
}

 六、注意事项

就是当程序部署到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项目即可。

 总结

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/83610.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

两种风格的纯CSS3加载动画

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>加载动画</title><style>.loader {w…

已解决 TypeError: Fetch argument None has invalid type <class ‘NoneType‘>

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

深入学习 Redis Cluster - 基于 Docker、DockerCompose 搭建 Redis 集群,处理故障、扩容方案

目录 一、基于 Docker、DockerCompose 搭建 Redis 集群 1.1、前言 1.2、编写 shell 脚本 1.3、执行 shell 脚本&#xff0c;创建集群配置文件 1.4、编写 docker-compose.yml 文件 1.5、启动容器 1.6、构建集群 1.7、使用集群 1.8、如果集群中&#xff0c;有节点挂了&am…

24.Xaml ListView控件-----显示数据

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…

Python灰帽编程——网页信息爬取

文章目录 网页信息爬取1. 相关模块1.1 requests 模块1.1.1 模块中的请求方法1.1.2 请求方法中的参数1.1.3 响应对象中属性 1.2 RE 模块1.2.1 匹配单个字符1.2.2 匹配一组字符1.2.3 其他元字符1.2.4 核心函数 2. 网页信息爬取2.1 获取网页HTML 源代码2.2 提取图片地址2.3 下载图…

服务器端应用的安装

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

机器学习第九课--随机森林

一.什么是集成模型 对于几乎所有的分类问题(图像识别除外&#xff0c;因为对于图像识别问题&#xff0c;目前深度学习是标配)&#xff0c;集成模型很多时候是我们的首选。比如构建一个评分卡系统&#xff0c;业界的标配是GBDT或者XGBoost等集成模型&#xff0c;主要因为它的效…

Windows/Linux(命令、安装包和源码安装)平台各个版本QT详细安装教程

前言 本文章主要介绍了Windows/Linux平台下&#xff0c;QT4&#xff0c;QT5&#xff0c;QT6的安装步骤。为什么要把QT版本分开介绍呢&#xff0c;因为这三个版本&#xff0c;安装步骤都不一样。Windows平台&#xff0c;QT4的Qt Creator&#xff0c;QT库和编译器是分开的&#…

Postman应用——Collection、Folder和Request

文章目录 Collection新建CollectionCollection重命名保存Request到Collection在Collection下创建Request删除Collection Folder新建FolderFolder重命名保存Request到Folder在Folder下创建Request在Folder下创建Folder删除Folder Request创建临时RequestRequest重命名删除Reques…

攻防世界-WEB-fileinclude

访问url&#xff0c;可以看到一些提示&#xff0c;绝对路径/var/www/html/index.php&#xff0c;也提示了flag在flag.php中。 快捷键Ctrlu,查看网页源代码 思路&#xff1a; 源代码中看到 include($lan.".php"); &#xff0c;可知此处存在文件包含。$lan的值是从co…

QGIS怎么修改源代码?持续更新...

修改配置文件保存位置 修改目的&#xff1a;放着和本地安装的其他QGIS共用一份配置文件 修改文件&#xff1a;core/qgsuserprofilemanager.cpp 修改位置&#xff1a;第37行 return basePath QDir::separator() "my_profiles";修改完毕后&#xff0c;再次生成一下…

Spring Authorization Server入门 (十八) Vue项目使用PKCE模式对接认证服务

Vue单页面项目使用授权码模式对接流程说明 以下流程摘抄自官网 在本例中为授权代码流程。 授权码流程的步骤如下&#xff1a; 客户端通过重定向到授权端点来发起 OAuth2 请求。 对于公共客户端&#xff0c;此步骤包括生成code_verifier 并计算code_challenge&#xff0c;然后…

wpf资源Resources探究性学习(一)

测试环境&#xff1a; vistual studio 2017 .net framework 3.5 window 10 新建WPF应用(.net framework)&#xff0c;项目名称为&#xff1a;WpfDemo&#xff0c;如下图&#xff1a; 新建完项目后&#xff0c;默认带有一个名为MainWindow.xaml的代码 一 简单使用字符串资源…

1_图神经网络GNN基础知识学习

文章目录 安装PyTorch Geometric安装工具包 在KarateClub数据集上使用图卷积网络 (GCN) 进行节点分类两个画图函数Graph Neural Networks数据集&#xff1a;Zacharys karate club network.PyTorch Geometric数据集介绍 edge_index使用networkx可视化展示 Graph Neural Networks…

(并查集) 1971. 寻找图中是否存在路径 ——【Leetcode每日一题】

❓ 1971. 寻找图中是否存在路径 难度&#xff1a;简单 有一个具有 n 个顶点的 双向 图&#xff0c;其中每个顶点标记从 0 到 n - 1&#xff08;包含 0 和 n - 1&#xff09;。图中的边用一个二维整数数组 edges 表示&#xff0c;其中 edges[i] [ui, vi] 表示顶点 ui 和顶点 …

Flash的学习

Flash的学习 1 概述 2 特性 STM32 的内部FLASH 包含主存储器、系统存储器以及选项字节区域。 2.1 主存储器 主存储器分为256 页&#xff0c;每页大小为2KB&#xff0c;共512KB。这个分页的概念&#xff0c;实质就是FLASH 存储器 的扇区&#xff0c;与其它FLASH 一样&…

UWB定位模块

UWB定位模组是华星智控自研的小尺寸高集成度模组&#xff0c;模组长宽厚为30.1513.955.62毫米&#xff0c;天线采用IPEX接口分体式设计&#xff0c;方便集成于您的产品中&#xff0c;产品采用本安设计&#xff0c;可以用于煤矿等井下场景&#xff0c;通信距离>100米&#xf…

什么是API接口?API接口的类型,如何调用API接口?

当今互联网技术的发展越来越快&#xff0c;越来越多的网站和应用程序需要获取外部数据来提供更好的服务和用户体验&#xff0c;这就需要使用API接口。本文将会对API接口的概念、类型以及如何调用API接口进行简要介绍。 一、什么是API接口&#xff1f; API&#xff08;Applica…

不可忽视的PG表膨胀优化

我是一个目录 案例1. 什么是表膨胀&#xff1f;2. 表膨胀危害是什么&#xff1f;3. 表膨胀是怎么产生的&#xff1f;4. 如何优化膨胀表&#xff1f; 案例 先来看一例公有云服务登录web页面端卡住案例&#xff1a; 故障现象&#xff1a;WEB端登录非常缓慢&#xff0c;需要耗时5…

【AD】【PCB封装规范计划】 -CON排针类

像这种CON&#xff0c;排针的。画PCB封装的时候&#xff0c;要把数字用丝印标出来&#xff01;&#xff01;&#xff01;