拿来就用的Java海报生成器ImageCombiner(一)
背景
如果您是UI美工大师或者PS大牛,那本文一定不适合你;如果当您需要自己做一张海报时,可以立马有小伙伴帮您实现,那本文大概率也不适合你。但是,如果你跟我一样,遇上到以下场景,最近公司上了不少传播方面的需求,需要合成各种营销图片。人事部和办公室的小伙伴想做一些具有通用场景功能海报,比如宣传报,会议宣传图片,但自己又对于PS这类的工具不是很擅长时,那么您不妨看看我推荐的这款开源小工具,看看这篇文章。作为程序员,可以不会PS,但一定要有自己解决问题的办法。通过开源程序,站在巨人的肩膀上,让你不用重复从0开始造轮子,将时间投入到实际业务维护和开发中。在这里要感谢https://gitee.com/dromara社区的https://gitee.com/dromara/image-combiner。
一、dromara社区
在正式介绍这款工具时,先介绍一下dromara社区,dromara社区是很多开源工具的集结地,很多开源的GVP,比如熟知的MaxKey,Hutool,Sa-Token,Lite_Flow,Lamp-cloud等等,感兴趣的朋友可以到他们的介绍页https://gitee.com/dromara看看介绍和开源项目的列表。

二、image-combiner介绍
1、能做什么
ImageCombiner是一个专门用于Java服务端图片合成的工具,没有很复杂的功能,简单实用,从实际业务场景出发,提供简单的接口,几行代码即可实现图片拼合(当然用于合成水印也可以),素材上支持图片、文本、矩形三种,支持定位、缩放、旋转、圆角、透明度、颜色、字体、字号、删除线、居中绘制、文本自动换行等特性,足够覆盖图片合成的日常需求。
是不是对文字描述没有直观的感受?那就先来一波成果图让你先直观的感受下他的功能。这是一张使用官网的代码生成出来的宣传海报图。是不是跟一些宣传的海报差不多了。后面会给出生成的具体的代码来详细说明大概的步骤来生成如下的结果。

2、image-combiner目录

将代码使用git clone下载下来之后,使用开发IDE(这里以eclipse为例)打开。image-combiner的源代码还是比较清爽的,从它的star数就可以看到,受欢迎的程度还是可以的。

三、如何编程化生成
1、跟着官方例子调试
任何一个开源项目拿到手之后,除了先熟悉开源软件的源码结构之外,在找到程序的主入口之后,通过调试运行来预测和跟踪程序的运行方式,从而掌握其源码的执行原理。在和自己的项目进行集成的时候,就可以进行充分的调优,甚至可以可以按照自己的方式进行优化,如果是一些通用场景,可以提交给社区,最终实现来源开源,反哺开源的正向操作。
打开test目录下的AppTest.java类。这里以一个面比较全的方法类说明image-combiner的主要用法。选取的代码如下:
/*** 完整功能测试** @throws Exception*/@Testpublic void FullTest() throws Exception {String bgImageUrl = "https://img.thebeastshop.com/combine_image/funny_topic/resource/bg_3x4.png"; //背景图(测试url形式)String qrCodeUrl = "http://imgtest.thebeastshop.com/file/combine_image/qrcodef3d132b46b474fe7a9cc6e76a511dfd5.jpg"; //二维码String productImageUrl = "https://img.thebeastshop.com/combine_image/funny_topic/resource/product_3x4.png"; //商品图BufferedImage waterMark = ImageIO.read(new URL("https://img.thebeastshop.com/combine_image/funny_topic/resource/water_mark.png")); //水印图(测试BufferedImage形式)BufferedImage avatar = ImageIO.read(new URL("https://img.thebeastshop.com/member/privilege/level-icon/level-three.jpg")); //头像String title = "# 最爱的家居"; //标题文本String content = "苏格拉底说:“如果没有那个桌子,可能就没有那个水壶”"; //内容文本//合成器和背景图(整个图片的宽高和相关计算依赖于背景图,所以背景图的大小是个基准)ImageCombiner combiner = new ImageCombiner(bgImageUrl, OutputFormat.PNG);combiner.setBackgroundBlur(30); //设置背景高斯模糊(毛玻璃效果)combiner.setCanvasRoundCorner(100); //设置整图圆角(输出格式必须为PNG)//商品图(设置坐标、宽高和缩放模式,若按宽度缩放,则高度按比例自动计算)combiner.addImageElement(productImageUrl, 0, 160, 837, 0, ZoomMode.Width).setRoundCorner(46) //设置圆角.setCenter(true); //居中绘制,会忽略x坐标参数,改为自动计算//标题(默认字体为“阿里巴巴普惠体”,也可以自己指定字体名称或Font对象)combiner.addTextElement(title, 55, 150, 1400);//内容(设置文本自动换行,需要指定最大宽度(超出则换行)、最大行数(超出则丢弃)、行高)combiner.addTextElement(content, "微软雅黑", 40, 150, 1480).setAutoBreakLine(837, 2, 60);//头像(圆角设置一定的大小,可以把头像变成圆的)combiner.addImageElement(avatar, 200, 1200, 130, 130, ZoomMode.WidthHeight).setRoundCorner(200).setBlur(5); //高斯模糊,毛玻璃效果//水印(设置透明度,0.0~1.0)combiner.addImageElement(waterMark, 630, 1200).setAlpha(.8f) //透明度,0.0~1.0.setRotate(15); //旋转,0~360,按中心点旋转//二维码(强制按指定宽度、高度缩放)combiner.addImageElement(qrCodeUrl, 138, 1707, 186, 186, ZoomMode.WidthHeight);//元素对象也可以直接new,然后手动加入待绘制列表TextElement textPrice = new TextElement("¥1290", 40, 600, 1400);textPrice.setStrikeThrough(true); //删除线combiner.addElement(textPrice); //加入待绘制集合//动态计算位置int offsetPrice = textPrice.getX() + textPrice.getWidth() + 10;combiner.addTextElement("¥999", 60, offsetPrice, 1400).setColor(Color.red);//执行图片合并combiner.combine();//保存文件combiner.save("d://fullTest.png");//或者获取流(并上传oss等)//InputStream is = combiner.getCombinedImageStream();//String url = ossUtil.upload(is);}
2、海报生成区分解

针对上述的宣传海报进行了分区,并用数字1-5号进行标记,1号一般用于宣传海报上的主要目标图片,2号一般是商品的名字,3号可以使价格,4号位置通常会对商品或者活动信息进行简单的描述,5号位置可以预留给二维码等信息,这里我们忽略了一个基本需求,就是海报有一个最基础的背景,所以在制作海报前首先还应该准备一张基本的背景图。针对上面这种需求,结合代码应该怎么进行实现?
3、海报相关资源准备

图片合成类ImageCombiner是主要的工作类,可以看下这个类的工作方法如下,可以看到这个类的方法非常丰富,包含所有的图片合成与处理的函数。通过构造ImageElement对象将背景图片设置到海报中,同时海报的宽度等信息也是在这里进行了初始化。

4、添加商品图和相关文字介绍
在背景图的上面,继续添加主要的宣传图片,比如商品图像信息。
//商品图(设置坐标、宽高和缩放模式,若按宽度缩放,则高度按比例自动计算)
combiner.addImageElement(productImageUrl, 0, 160, 837, 0, ZoomMode.Width).setRoundCorner(46) //设置圆角.setCenter(true); //居中绘制,会忽略x坐标参数,改为自动计算//标题(默认字体为“阿里巴巴普惠体”,也可以自己指定字体名称或Font对象)
combiner.addTextElement(title, 55, 150, 1400);//内容(设置文本自动换行,需要指定最大宽度(超出则换行)、最大行数(超出则丢弃)、行高)
combiner.addTextElement(content, "微软雅黑", 40, 150, 1480).setAutoBreakLine(837, 2, 60);//头像(圆角设置一定的大小,可以把头像变成圆的)
combiner.addImageElement(avatar, 200, 1200, 130, 130, ZoomMode.WidthHeight).setRoundCorner(200).setBlur(5); //高斯模糊,毛玻璃效果//水印(设置透明度,0.0~1.0)
combiner.addImageElement(waterMark, 630, 1200).setAlpha(.8f) //透明度,0.0~1.0.setRotate(15); //旋转,0~360,按中心点旋转//二维码(强制按指定宽度、高度缩放)
combiner.addImageElement(qrCodeUrl, 138, 1707, 186, 186, ZoomMode.WidthHeight);
5、动态位置计算
在一些场景中,文字的距离不是提前可控的,比如会根据前面文字的距离来设置后面文字的宽度,实现动态的设置。这里来看image-combiner应该如何实现?
//元素对象也可以直接new,然后手动加入待绘制列表
TextElement textPrice = new TextElement("¥1290", 40, 600, 1400);
textPrice.setStrikeThrough(true); //删除线
combiner.addElement(textPrice); //加入待绘制集合//动态计算位置
int offsetPrice = textPrice.getX() + textPrice.getWidth() + 10;
combiner.addTextElement("¥999", 60, offsetPrice, 1400).setColor(Color.red);

使用Graphics2D对象创建图片并执行相关的写入操作。

通过以上的步骤,就可以生成我们需要的宣传图,是不是很方便,也很简单。
四、总结和展望
1、展望
image-cominer的API和类的设计详细分解,打算在下一篇中进行介绍。image-combiner的其它能力您可以下载代码后在自己的ide中进行实际跑一下,这样比较有直观的效果。这里只是展示了它的基础能力,具体的使用场景需要您来定义。通过编程化海报处理,在应对批量的动态电子证书,动态的个人信息证明等等是非常具有想象力的,再此基础之上,可以进行web化提供云服务接口,或者桌面化,提供给需要的用户进行使用。这些功能的扩展需要大家的聪明才智来头脑风暴,肯定会有很多有意思的Idea。
2、总结
以上就是本文的主要内容,文章首先简单介绍了Dromara开源社区,然后介绍了基于Java的海报生成器image-combiner,通过debug调试的方式完整的介绍了如何使用编程模式来完成一份海报的生成。最后对于image-combiner的功能扩展进行了展望。如果您有兴趣,可以自己来扩展和完善。
相关文章:

拿来就用的Java海报生成器ImageCombiner(一)
背景如果您是UI美工大师或者PS大牛,那本文一定不适合你;如果当您需要自己做一张海报时,可以立马有小伙伴帮您实现,那本文大概率也不适合你。但是,如果你跟我一样,遇上到以下场景,最近公司上了不…...

【C++】类和对象(二)
目录 一、默认成员函数 二、构造函数 1、构造函数概念 2、构造函数编写 3、默认构造函数 4、内置类型成员的补丁 三、析构函数 1、析构函数概念 2、析构函数编写 3、默认析构函数 四、拷贝构造函数 1、拷贝构造函数概念及编写 2、默认拷贝构造函数 3、拷贝构造…...

UDP协议
文章目录一、前沿知识应用层传输层二、UDP协议一、前沿知识 应用层 应用层:描述了应用程序如何理解和使用网络中的通信数据。 我们程序员在应用层的主要工作是自定义协议,因为下面四层都在系统内核/驱动程序/硬件中已经实现好了,不能去修改…...

IT人的晋升之路——关于人际交往能力的培养
对于咱们的程序员来说,工作往往不是最难的,更难的是人际交往和关系的维护处理。很多时候我们都宁愿加班,也不愿意是社交,认识新的朋友,拓展自己的圈子。对外的感觉就好像我们丧失了人际交往能力,是个呆子&a…...

Docker进阶 - 8. docker network 网络模式之 container
目录 1. container 模式概述 2. 使用Alpine操作系统来验证 container 模式 1. container 模式概述 container网络模式新建的容器和已经存在的一个容器共享一个网络ip配置而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个…...

2年功能测试月薪9.5K,100多天自学自动化,跳槽涨薪4k后我的路还很长...
前言 其实最开始我并不是互联网从业者,是经历了一场六个月的培训才入的行,这个经历仿佛就是一个遮羞布,不能让任何人知道,就算有面试的时候被问到你是不是被培训的,我还是不能承认这段历史。我是为了生存,…...

“数字孪生”:为什么要仿真嵌入式系统?
01.仿真是什么? 仿真的概念非常广泛,但归根结底都是使用可控的手段来模仿真实的情况,通常应用于现实世界中实施难度大甚至是无法实践的事物。 众所周知,嵌入式系统通常是形式多样的、面向特定应用的软硬件综合体,无…...
Java基础知识总结(上)
Java基础知识总结 1. Java语言的特点 简单易学,相较于python等语言具有较好的严谨性以及报错机制; 面向对象(封装,继承,多态),Java中所有内容都是基于类进行扩展的,由类创建的实体…...
MySQL 2:MySQL约束
一、定义 约束(constraint),即表中数据的限制条件。在表设计中加入约束的目的是保证表中记录的完整性和有效性。 比如user表,有些列(手机号)的值不能为空,有些列(身份证号ÿ…...

C4--Vivado添加列表中不存在的FLash器件2023-02-10
以华邦SPI FLASH W25Q128JVEIQ为例进行说明。(其他Flash添加步骤一致) 1.本地vivado安装目录D:\Softwares\xlinx_tools\Vivado\2020.2\data\xicom下,找到xicom_cfgmem_part_table.csv文件,这个表与vivado hardware manager中的器…...

php代码审计
准备工作 了解CMS的基本信息 该CMS使用的是什么设计模式?该CMS每个目录大概负责的功能(视图、缓存、控制器等)。该CMS处理请求的基本流程是如何走的?以及在系统中使用的全局过滤函数是如何对数据进行处理的? 代码审计方法 敏感函数回溯 …...

接口测试入门,如何划分接口文档
1.首先最主要的就是要分析接口测试文档,每一个公司的测试文档都是不一样的。具体的就要根据自己公司的接口而定,里面缺少的内容自己需要与开发进行确认。 我认为一针对于测试而言的主要的接口测试文档应该包含的内容分为以下几个方面。 a.具体的一个业…...
数据库学习第二天
第7章 系统预定义函数 函数:代表一个独立的可复用的功能。 和Java中的方法有所不同,不同点在于:MySQL中的函数必须有返回值,参数可以有可以没有。 MySQL中函数分为: (1)系统预定义函数&…...

NODE => CORS跨域资源共享学习
1.CORS跨域资源共享 cors是Express的一个第三方中间件。通过安装和配置cors中间件,可以很方便地解决跨域问题 运行npm install cors 安装中间件使用const cors require(‘cors’) 导入中间件在路由之前调用 app.use(cors()&#…...

golang rabbitMQ 生产者复用channel以及生产者组分发策略
引用的是rabbitMQ官方示例的库:github.com/rabbitmq/amqp091-go在网络编程中我们知道tcp连接的创建、交互、销毁等相关操作的"代价"都是很高的,所以就要去实现如何复用这些连接,并要做到高效并可靠。预期效果:项目初始化…...

掌握了这项技能的性能测试师,90%都升职加薪了
初入职场的新人该怎么做才能让自己快速成长?在公司一直做着手工测试,如何才能提升自己,避免陷入“只涨年龄不涨经验”的尴尬?做为一名软件测试工程师,我们不得不去面对这些问题,有的人找到了答案࿰…...

linux中crontab定时任务导致磁盘满和云监控未报警的的坑
一个后台开发者,兼职运维工作中,配置linux中crontab定时任务,导致磁盘满和云监控未报警的问题的坑。 1.磁盘满 使用命令 df -h2.问题排查 2.1排查日志 命令 cat /var/log/messages日志文件的默认路径是:/var/log 下面是几个…...

vscode中安装python运行调试环境
在运行代码之前,需要到微软商店下载安装python环境,35m,都是自动的。 1、安装python 的extensions插件。 ctrlshiftx 输入 python 后点击 install 按钮。 2、新建文件夹spider文件夹。 3、在新建文件夹spider下新建文件spider.py源代码。…...

【微服务】微服务架构超强讲解,通俗易懂
微服务架构目录一、微服务架构介绍二、出现和发展三、传统开发模式和微服务的区别四、微服务的具体特征五、面向服务的架构SOA(service oriented architecture)和微服务的区别1、SOA喜欢重用,微服务喜欢重写2、SOA喜欢水平服务,微…...
内核中的竞态产生的原因和解决方法
产生原因: 由于多进程对临界资源的抢占 根本原因: 1、对于单核处理器而言,内核支持抢占就会出现竞态 2、对于多核处理器而言,是核与核的竞态 3、进程与中断间存在竞态 4、arm开发板不会出现中断与中断间的竞态(目前&am…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...