拿来就用的Java海报生成器ImageCombiner(一)

news2024/11/29 1:55:33

背景

如果您是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
     */
    @Test
    public 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的功能扩展进行了展望。如果您有兴趣,可以自己来扩展和完善。

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

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

相关文章

新手小白适合做跨境电商吗?

今天的跨境电商已经逐渐成熟,靠运气赚钱的时代早已过去,馅饼不可能从天上掉下来,尤其是你想做一个没有货源的小白劝你醒醒。做跨境电商真的不容易,要想做,首先要分析自己是否适合做。米贸搜整理了以下资料,…

硬件设计—高性能ADC前端电路

高性能模数转换器(ADC)一般对系统的性能有非常高的要求,而AD芯片的“前端”的输入电路设计对ADC系统的的性能有非常大的影响。以下主要介绍了ADC芯片前端输入使用放大器和变压器各自的优势。 1、放大器和变压器根本区别 放大器是有源器件&am…

Docker进阶 - 8. docker network 网络模式之 container

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

ChatGPT注册+微信自动回复

ChatGPT注册微信自动回复1 注册OpenAI1.1 科学上网1.2 准备用于注册OpenAI的邮箱1.3 准备用于验证OpenAI的手机号1.4 注册OpenAI1.5 使用OpenAI2 基于ChatGPT微信实现自动回复2.1 原理2.2 实现ChatGPT是OpenAI基于GPT-3模型构建的自然语言处理模型,近几天ChatGPT突然…

这款浏览器火了,能快速使用ChatGPT,简单一看就会

当下ChatGPT很火,影响的人数非常广泛。作为聊天机器人模型,ChatGPT能完成写论文、编代码、写新闻、画画等高难度要求。那么,如何使用ChatGPT呢?下面介绍一下几个使用方法。值得一提的,目前已经有浏览器支持使用ChatGPT…

C++程序设计——多态:虚函数、抽象类、虚函数表

注:以下示例均是在VS2019环境下 一、多态的概念 通俗来讲,多态就是多种形态,当不同的对象去完成某个行为时,会产生出不同的状态。即不同继承关系的类对象,去调用同一函数时,产生不同的行为。 比如”叫“这…

【React】course

《千锋HTML5实战就业班React课程体系V16版本》课程资料 一、关于React 英文官网:https://reactjs.org/ 中文官网:https://zh-hans.reactjs.org/ React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架&#xff0c…

JAVA工具篇--1 Idea中 Gradle的使用

前言: 既然我们已经使用Maven 来完成对项目的构建,为什么还要使用Gradle 进行项目的构建;gradle和maven都可以作为java程序的构建工具,但两者还是有很大的不同之处的:1.可扩展性,gradle比较灵活&#xff0c…

RabbitMQ-消息应答

一、介绍为了保证消息在发送过程中不丢失,rabbitmq引入消息应答机制,消息应答就是:消费者在接收到消息并且处理该消息之后,告诉rabbitmq它已经处理了,rabbitmq可以把该消息删除了。二、自动应答消息发送之后立即被认为…

pytest-fixture

fixture是pytest特有的功能,它用pytest.fixture标识,定义在函数前面。在编写测试函数的时候,可以将此函数的名称作为传入参数,pytest会以依赖注入方式将该函数的返回值作为测试函数的传入参数。fixture主要的目的是为了提供一种可…

从C语言向C++过渡

文章目录前言1.命名空间1.域的概念2.命名空间的使用2.C输入&输出3.缺省参数1.概念2.分类3.注意事项4.函数重载5.引用1.概念2.使用注意事项3.引用使用场景4.指针和引用的区别6.内联函数7.auto关键字8.nullptr前言 C被成为带类的C,本文由C语言向C过度,将会初步介…

电子器件系列32:逻辑与门芯片74LS11

一、编码规则 先看看这个代码的意思:74LS11 74是一个系列(74 表示为工作温度范围,74: 0 ~ 70度。) ls的意思就是工艺类型(Bipolar(双极)工艺) 11是代码 什么是74系列逻辑芯片? - 知乎 什么是…

【MyBatis】第八篇:一级,二级缓存

其实缓存字面的意思就是将一些内容缓存下来,等下次使用的时候可以直接调用,通过数据库得到数据,有时候会使用相同的数据,所以mybatis自然也支持缓存。 而mybatis按照缓存的效果可以分两大类:一级缓存和二级缓存。 一…

node.js下载和vite项目创建以及可能遇到的错误

目录 一、node.js的下载 1、去官网下载 节点.js (nodejs.org) 2、下载过程 第一步: 第二步: 第三步: 第四步: 第五步: 二、vite项目的创建(使用的工具是Hbuilder x) 第一步: 出现报错…

基于matlab多功能相控阵雷达资源管理的服务质量优化

一、前言此示例说明如何为基于服务质量 (QoS) 优化的多功能相控阵雷达 (MPAR) 监控设置资源管理方案。它首先定义必须同时调查的多个搜索扇区的参数。然后,它介绍了累积检测范围作为搜索质量的度量,并展示了…

低代码开发平台|制造管理-工艺工序搭建指南

1、简介1.1、案例简介本文将介绍,如何搭建制造管理-工艺工序。1.2、应用场景先填充工序信息,再设置工艺路线对应的工序;工序信息及工艺路线列表报表展示的是所有工序、工艺路线信息,可进行新增对应数据的操作。2、设置方法2.1、表…

权限管理实现的两种方式(详解)

登录的接口请求的三个内容:1. token2. 用户信息、角色信息3. 菜单信息第一种:基于角色Role的动态路由管理 (不推荐,但市场用的比较多)首先列出枚举每个角色对应几个路由,然后根据用户登录的角色遍历枚举出来的角色动态注册对应的路…

4年功能测试经验,裸辞后找不到工作怎么办?

软件测试四年,主要是手动测试(部分自动化测试和性能测试,但是用的是公司内部自动化工具,而且我自动化方面是弱项。) 现在裸辞三个月了,面试机会少而且面试屡屡受挫。总结就是自动化,性能&#…

微服务保护:一、初识Sentinel

1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。 如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被阻塞。此时&…

链接脚本学习笔记

IAR 一般步骤 链接器用于链接过程。它通常执行以下过程(请注意,某些步骤可以通过命令行选项或链接器配置文件中的指令关闭): 1.确定应用程序中要包含哪些模块。始终包含对象文件中提供的模块。仅当库文件中的模块为从包含的模块…