图片上叠加文字

在一个原有图片上叠加上指定的文字

编写一个工具类实现文字叠加的功能,叫ImageUttils

import cn.hutool.core.img.Img;
import cn.hutool.core.io.resource.Resource;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
//import sun.misc.BASE64Encoder;
import org.apache.commons.codec.binary.Base64;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;/*** @ClassName ImageUtils* @Description 图片合成工具类* @Version**/
@Component
@Slf4j
public class ImageUtils {@Value("${image.fontSize}")private int fontSize;@Value("${image.backgroundColor}")private String backgroundColor;@Value("${image.fontColor}")private String fontColor;@Value("${image.compression}")private double compression;@Value("${text.line.height}")private int textLineHeight;@Value("${image.compress.size}")private Double imageCompressSize;public byte[] addTextToImage(String imageUrl, String text){
//        logger.info("修改base64");log.info("进入ImageUtils图片合成方法");long t1 = System.currentTimeMillis();//获取图片byte[] bytes = new byte[0];ByteArrayOutputStream baos  = null;try {Image image = ImageIO.read(new URL(imageUrl));int width = (int)(image.getWidth(null) * compression);int height = (int)(image.getHeight(null) * compression);log.debug("原图的大小为:width = {}, height = {}", width, height);int size = (int)(fontSize * compression);int n = width/size;String[] split = null;bytes = null;try {text= getStringByEnter(n, text);
//                split = StringUtils.split(text, "\\r?\\n");//更换成一下方式,上面的方法获取的split = nullsplit = text.split("\n");} catch (Exception e) {log.error("imageUrl={},text={},getStringByEnter error , e = {}", imageUrl, text, e);}int heightPlus = 0;if (split== null || split.length==0){heightPlus = textLineHeight;} else {heightPlus = split.length * textLineHeight;}log.debug("heightPlus = {}", heightPlus);BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 =  bi.createGraphics();g2.drawImage(image, 0, 0, width, height - heightPlus, null);g2.setColor(colorMapping(fontColor));g2.setFont(new Font("宋体",Font.BOLD, size));//g2.drawString(text, 0, height - 2 * size);for(int i = 0 ; i < split.length; i++){String line = split[i];g2.drawString(line, 0, height - size*(split.length - i));}g2.dispose();baos = new ByteArrayOutputStream();//图片格式要保证和源图格式相同,否则图片大小差别会很大ImageIO.write(bi, "jpg", baos);bytes = baos.toByteArray();//压缩图片ByteArrayOutputStream out = new ByteArrayOutputStream();InputStream sbs = new ByteArrayInputStream(bytes);Img.from(sbs).setQuality(imageCompressSize).write(out);return out.toByteArray();} catch (Exception e) {log.error("imageUrl={}, text={}, addTextToImage error = {}",imageUrl, text, e);} finally {try {baos.close();} catch (IOException e) {log.error("imageUrl={}, text={}, io close error , e = {}", imageUrl,text, e);}}long t2 = System.currentTimeMillis();log.info("imageUrl={}, text={}, addTextToImage cost = {}ms", imageUrl,text, t2 -t1);return bytes;}private static String getClassPath() {String classPath = null;URL url = ImageUtils.class.getResource("/");if(null != url){classPath = url.toString().replaceFirst("file:/", "/");}return classPath;}/*** 自动换行* @param string* @return*/public String getStringByEnter(int length, String string) throws Exception {StringBuilder sb = new StringBuilder();for (int i = 0; i < string.length(); i++){/*if (string.substring(0, i).getBytes("GBK").length > length){return string.substring(0, i - 1) + "\n" +getStringByEnter(length, string.substring(i - 1));}*/sb.append(string.charAt(i));if((i+1)%length == 0){sb.append("\n");}}return sb.toString();}public String encodeBase64File(String path) throws Exception {File file = new File(path);FileInputStream inputFile = new FileInputStream(file);byte[] buffer = new byte[(int) file.length()];inputFile.read(buffer);inputFile.close();
//        return new BASE64Encoder().encode(buffer);return Base64.encodeBase64String(buffer);}private Color colorMapping(String color){Color color1 = Color.BLACK;switch (color) {case "red":color1 =  Color.RED;break;case "white":color1 = Color.WHITE;break;case "gray":color1 = Color.GRAY;break;case "blue":color1 = Color.BLUE;break;default:color1 = Color.BLACK;break;}return color1;}
}

其中入参在配置文件中,如下

#------图片页面字体设置-------
image.backgroundColor=black
image.fontColor=red
image.fontSize=20
image.compression=1.0
text.line.height=33

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

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

相关文章

绝对路径拼接漏洞 [NISACTF 2022]babyupload

打开题目 最开始以为是文件上传的漏洞 结果发现无论我们上传什么文件都会显示bad filename 去网上看了大佬的wp知道 我们直接去看源代码得到提示 /source 那我们去访问一下这个路径看看 得到一个下载文件 用记事本打开得到 源代码如下 from flask import Flask, request, r…

软考46-上午题-【数据库】-数据查询语言DQL1

一、SQL数据查询功能 SELECT语句的语法如下&#xff1a; 【注意】&#xff1a; 使用DISTINCT选项可以去重&#xff1b; form子句中出现多个基本表或视图时&#xff0c;系统首先执行笛卡尔积操作。 下面的查询示例均以这些表为基础 1-1、投影查询-SELECT 【回顾】&#xff1a;…

设计模式(七)装饰模式

相关文章设计模式系列 1.装饰模式简介 装饰模式介绍 装饰模式是结构型设计模式之一&#xff0c;不必改变类文件和使用继承的情况下&#xff0c;动态地扩展一个对象的功能&#xff0c;是继承的替代方案之一。它是通过创建一个包装对象&#xff0c;也就是装饰来包裹真实的对象…

【日常聊聊】Sora- 探索AI视频模型的无限可能

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 方向一&#xff1a;技术解析 方向二&#xff1a;应用场景 方向三&#xff1a;未来展望 方向四&#xff1a;伦理与创意 方向…

[linux][异常检测] hung task, soft lockup, hard lockup, workqueue stall

hung task&#xff0c;soft lockup&#xff0c;hard lockup&#xff0c;workqueue stall 是 linux 内核中的异常检测机制&#xff0c;这 4 个检测均是通过时间维度上的检测来判断异常。 在时间维度上的检测机制&#xff0c;有两个核心的点&#xff1a; &#xff08;1&#xff…

web组态插件

插件演示地址&#xff1a;http://www.byzt.net 关于组态软件&#xff0c;首先要从组态的概念开始说起。 什么是组态 组态&#xff08;Configure&#xff09;的概念来自于20世纪70年代中期出现的第一代集散控制系统&#xff08;Distributed Control System&#xff09;&#xf…

紫外-可见吸收光谱法(UV-Vis)是最常用吸收光谱技术 市场持续扩大

紫外-可见吸收光谱法&#xff08;UV-Vis&#xff09;是最常用吸收光谱技术 市场持续扩大 紫外-可见吸收光谱法&#xff0c;也称为紫外-可见分光光度法&#xff0c;简称UV-Vis&#xff0c;利用样品分子在紫外和可见光激发下产生电子能级跃迁形成的吸收光谱&#xff0c;对元素进行…

[C++]set用法

一、set是什么 set是STL中的常见容器&#xff0c;set中不允许有重复元素&#xff0c;并且set中的元素是排好序的 二、set简单使用 1、使用set需要添加头文件#include<set> 2、set的声明 set<int> a;//set中存放的是int类型的数据3、与set相关的函数 set<i…

基于Java SSM框架实现高校网课管理系统项目【项目源码+论文说明】

基于java的SSM框架实现高校网课管理系统演示 摘要 随着移动应用技术的发展&#xff0c;越来越多的学生借助于移动手机、电脑完成生活中的事务&#xff0c;许多的行业也更加重视与互联网的结合&#xff0c;以提高教学的教育水平和寻求更高的经济利益。针对高校网课管理系统&…

猫头虎分享已解决Bug || 解决SyntaxError: Unexpected token o in JSON at position 1

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

HashMap的put()方法执行流程

HashMap的数据结构在jdk1.8之前是数组链表&#xff0c;为了解决数据量过大、链表过长是查询效率会降低的问题变成了数组链表红黑树的结构&#xff0c;利用的是红黑树自平衡的特点。 链表的平均查找时间复杂度是O(n)&#xff0c;红黑树是O(log(n))。 HashMap中的put方法执行过…

mysql的增删改查(常用)

增(insert) 语法&#xff1a; insert into 表名&#xff08;字段&#xff09; values( 字段对应的值) 案例&#xff1a; 创建一个学生表 结构如下&#xff1a; create table student(id int ,name varchar(20),age int); 向表中插入2条数据 create table student(id int ,n…

golang 函数式编程库samber/mo使用: Result

golang 函数式编程库samber/mo使用&#xff1a; Result 如果您不了解samber/mo库&#xff0c; 请先阅读上一篇 Option &#xff0c; 这篇讲述结构体Result的使用 Result和Option区别 samber/mo有了Option&#xff0c; 为什么还有Result呢? 我们先看看定义&#xff1a; Opt…

【CSS】什么是文档流、什么是BFC,怎么触发BFC,BFC 有什么应用场景

什么是文档流 文档流是 html 元素的排列方式文档流分为 标准文档流【格式化上下文】 它是页面中的一块渲染区域&#xff0c;有一套渲染规则&#xff0c;决定了其子元素如何布局&#xff0c;以及和其他元素之间元素按照其在 HTML 中的先后位置至上而下布局&#xff0c;在这个过…

小程序--vscode配置

要在vscode里开发微信小程序&#xff0c;需要安装以下两个插件&#xff1a; 安装后&#xff0c;即可使用vscode开发微信小程序。 注&#xff1a;若要实现鼠标悬浮提示&#xff0c;则需新建jsconfig.json文件&#xff0c;并进行配置&#xff0c;即可实现。 jsconfig.json内容如…

linux系统---安装使用nginx

目录 一、编译安装Nginx 1、关闭防火墙&#xff0c;将安装nginx所需要软件包传到/opt目录下 ​编辑2、安装依赖包 3、创建运行用户、组 4、编译安装nginx 5、创建软链接后直接nginx启动 ​编辑 6、创建nginx自启动文件 ​编辑6.1 重新加载配置、设置开机自启并开启服务…

一次奇怪的事故:机器网络连接打满,导致服务不可用

业务背景 发生事故的业务系统是一个toB业务&#xff0c;业务是服务很多中小企业进行某项公共信息指标查询。系统特点:业务处理相对简单&#xff0c;但是流量大&#xff0c;且对请求响应要求较高&#xff1a; 业务请求峰值qps达50w&#xff0c;平时流量达20w左右。 请求响应时…

开发工具篇第36讲:如何使用Typora+Gitee+PicGo+OSS+Idea创建属于自己的云笔记

如何使用Typora+Gitee+PicGo+OSS+Idea创建属于自己的云笔记 好记性不如烂笔头,记笔记是一个好习惯,本人习惯通过Typora软件记录markdown笔记,但是遇到了多设备同步笔记的问题,本文是开发工具篇第36讲,介绍通过Typora+PicGo+Gitee搭建个人云笔记平台,使得多设备都能看到最…

175基于matlab信号匹配追踪稀疏分解代码

基于matlab信号匹配追踪稀疏分解代码&#xff0c;基于gabor时频原子&#xff0c;对信号重构效果好。输出原子选择过程&#xff0c;重构误差及重构后的信号。程序已调通&#xff0c;可直接运行。 175 匹配追踪稀疏分解 gabor时频原子 (xiaohongshu.com)

申创贝拓电气设备邀您参观2024生物发酵展

参展企业介绍 BETTO贝拓电气成立于2017年&#xff0c;初期总部坐落于安徽合肥&#xff0c;从事工业电控机柜的设计和销售工作。2022年总部迁往上海&#xff0c;有了自己的制造基地&#xff0c;涉及制造和销售工业控制柜、操作台、IT机柜、户外机柜、人机界面、悬臂、电气安装成…