背景

我目前参与小程序的产品研发,为了方便产品的转发和推广,会对课提供生成海报转发或者分享的功能,前期海报合成这个功能是由项目组的老同事负责开发,后来小程序海报这块功能需要单独做一个功能用于专门根据不同的课程类型来生成海报的功能,很荣幸这个任务交由我开发。编码过程这边就略过了,直接看代码如下所示:

EmojiUtils工具类

package com.xyq.maventest.util;import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/****
* Project Name:maventest
* <p>emoji标签转换工具类<br>
*
* @ClassName: EmojiUtils
* @date 2019年1月22日  下午4:29:26
*
* @author youqiang.xiong
* @version 1.0
* @since
* @see*/
public class EmojiUtils {private static Logger logger = LoggerFactory.getLogger(EmojiUtils.class);/*** 将emoji标签转换成utf8字符集保存进数据库* @param str* @return*/public static String emojiConvert(String str) {String patternString = "([\\x{10000}-\\x{10ffff}\\ud800-\\udfff])";Pattern pattern = Pattern.compile(patternString);Matcher matcher = pattern.matcher(str);StringBuffer sb = new StringBuffer();while(matcher.find()) {// matcher.appendReplacement(sb,"?");try {matcher.appendReplacement(sb,"[[" + URLEncoder.encode(matcher.group(1),"UTF-8") + "]]");} catch(UnsupportedEncodingException e) {logger.error("emojiConvert error"+ e.getMessage());return str;}}matcher.appendTail(sb);logger.debug("emojiConvert " + str + " to " + sb.toString() + ", len:" + sb.length());return sb.toString();}/*** 还原utf8数据库中保存的含转换后emoji表情的字符串* @param str* @return*/public static String emojiRecovery(String str) {if(StringUtils.isEmpty(str)){return "";}try{String patternString = "\\[\\[(.*?)\\]\\]";Pattern pattern = Pattern.compile(patternString);Matcher matcher = pattern.matcher(str);StringBuffer sb = new StringBuffer();while(matcher.find()) {try {matcher.appendReplacement(sb, URLDecoder.decode(matcher.group(1), "UTF-8"));} catch(UnsupportedEncodingException e) {logger.error("emojiRecovery error"+ e.getMessage());return "";}}matcher.appendTail(sb);logger.debug("emojiRecovery " + str + " to " + sb.toString());return sb.toString();}catch (Exception e){logger.error("emojiRecovery error",e);}return str;}}

ImageUtils 工具类

核心代码如下:

/****
* Project Name:wechat-management-util
* <p>各种海报合成图片工具类<br>
*
* @ClassName: ImageUtils
* @date 2019年1月22日  下午3:52:43
*
* @author youqiang.xiong
* @version 1.0
* @since
* @see*/
public class ImageUtils {private static final Logger logger = LoggerFactory.getLogger(ImageUtils.class);/***** * Project Name: wechat-management-util* <p>公开课小程序后台生成分享海报 <br> ** @author youqiang.xiong* @date 2019年1月11日  下午4:28:21* @version v1.0* @since * @param background   *           背景图* @param poster*            教师形象图* @param qr*          二维码图片* @param avatar*          头像图片* @param font*             字体* @param nickname*           昵称* @param courseName*             课程名称* @param courseTip*            课程大纲* @return * @throws IOException*/public static BufferedImage createSharePoster(BufferedImage background, BufferedImage poster,BufferedImage qr,BufferedImage avatar,Font font, String nickname,String courseName,String courseTip ) throws  IOException{// 开启抗锯齿RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 使用高质量压缩renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);int height = background.getHeight() * 750 / background.getWidth();// 图片大小BufferedImage img = new BufferedImage(750, height, BufferedImage.TYPE_INT_RGB);// 开启画图Graphics2D g = (Graphics2D) img.getGraphics();try {g.setRenderingHints(renderingHints);// 教师海报图 - 需要将原图进行剪切 剪切后的长度是 750*830BufferedImage teacherImage = cutPic(poster, 158, 0, 750, 830);g.drawImage(teacherImage.getScaledInstance(750,teacherImage.getHeight(), Image.SCALE_FAST), 0, 0, null);// 画底图g.drawImage(background.getScaledInstance(750, height, Image.SCALE_FAST), 0, 0, null);// 画头像if (null != avatar) {g.drawImage(ImageUtils.roundImage(avatar, avatar.getWidth(), avatar.getHeight(), 360).getScaledInstance(45*2, 45*2, Image.SCALE_FAST), 25*2, 603*2, null);}// 画二维码if (null != qr) {g.drawImage(qr.getScaledInstance(70*2, 70*2, Image.SCALE_FAST), 286*2, 591*2, null);}// 设置字体大小font = font.deriveFont(34f);// 设置字体颜色Color color = new Color(55,69,97);g.setColor(color);g.setFont(font);//昵称 nickname = nickname == null ? "" : nickname;nickname = EmojiUtils.emojiRecovery(nickname);if(nickname.length() > 5) {nickname = nickname.substring(0, 5) + "...";}int stringWidth = getWidth(g.getFontRenderContext(), g, nickname);g.drawString(nickname, 84 * 2 , 623 * 2);//画'向您推荐好课' String recommendText = "向您推荐好课";font = font.deriveFont(24f);// 设置字体颜色color = new Color(55,69,97);g.setColor(color);g.setFont(font);g.drawString(recommendText, 84 * 2 +  stringWidth , 623 * 2);// 写课程名称font = font.deriveFont(60.0f);color = new Color(69,75,106);g.setColor(color);g.setFont(font);int courseWidth = getWidth(g.getFontRenderContext(), g, courseName);if(courseWidth >= 334*2) {String c1 = courseName.substring(0, 10);String c2 = courseName.substring(10, courseName.length());int courseHeight = getHeight(g.getFontRenderContext(), g, c1);g.drawString(c1, 21 * 2 , (430 * 2) - 2);g.drawString(c2, 21 * 2 , 420 * 2 + courseHeight + 2);}else {g.drawString(courseName, 21 * 2 , 448 * 2);}//写课程大纲List<String> tipList = Arrays.asList(courseTip.split("\n"));String tip1 = tipList.get(0);if(tip1.length() >= 20) {tip1 = tip1.substring(0, 19) + "...";}String tip2 = tipList.get(1);if(tip2.length() >= 20) {tip2 = tip2.substring(0, 19) + "...";}String tip3 = tipList.get(2);if(tip3.length() >= 20) {tip3 = tip3.substring(0, 19) + "...";}font = font.deriveFont(30.0f);color = new Color(176,153,104);g.setColor(color);g.setFont(font);g.drawString(tip1, 47 * 2 , 494 * 2);g.drawString(tip2, 47 * 2 , 527 * 2);g.drawString(tip3, 47 * 2 , 559 * 2);img = Thumbnails.of(img).scale(1f).outputQuality(1f).asBufferedImage();} catch (IOException e) {throw  new IOException(e.getMessage());} finally {g.dispose();}return img;}
}public static int getWidth(FontRenderContext context, Graphics2D g, String text) {return (int) g.getFont().getStringBounds(text, context).getWidth();}public static int getHeight(FontRenderContext context, Graphics2D g, String text) {return (int) g.getFont().getStringBounds(text, context).getHeight();}public static BufferedImage roundImage(BufferedImage image, int width, int height, int cornerRadius) {BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);Graphics2D g2 = outputImage.createGraphics();g2.setComposite(AlphaComposite.Src);g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2.setColor(Color.WHITE);g2.fill(new RoundRectangle2D.Float(0, 0, width, height, cornerRadius, cornerRadius));g2.setComposite(AlphaComposite.SrcAtop);g2.drawImage(image, 0, 0, null);g2.dispose();return outputImage;}public static BufferedImage roundImage(BufferedImage image, int cornerRadius) {return roundImage(image, image.getWidth(), image.getHeight(), cornerRadius);}public static Font getPingFang() {BufferedInputStream bis = null;Font definedFont = null;try {bis = new BufferedInputStream(new FileInputStream("C:\\Users\\youqiang.xiong\\git\\WechatManagement\\wechat-management-parent\\wechat-management-m-web\\src\\main\\resources\\pingfang.ttf"));} catch (FileNotFoundException e) {e.printStackTrace();}try {definedFont = Font.createFont(Font.TRUETYPE_FONT, bis);return definedFont;} catch (FontFormatException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}

pom.xml 新增依赖

 <dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.8</version></dependency>

编写main方法,测试合成图片

  public static void main(String[] args) {try {BufferedImage bg = ImageIO.read(new File("C:\\Users\\youqiang.xiong\\Desktop\\底图\\make_poster_base.png"));BufferedImage poster = ImageIO.read(new File("C:\\\\Users\\\\youqiang.xiong\\\\Desktop\\\\底图\\\\poster.jpg"));BufferedImage qr = ImageIO.read(new File("C:\\\\Users\\\\youqiang.xiong\\\\Desktop\\\\底图\\\\qr.jpg"));BufferedImage avatar = ImageIO.read(new URL("https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTK4DYtvaMV6YIficQnj2D8CiaabaSAq1kzNZUAZCWn5oGv6n8AnjuYTH3bBqELica2yeKbYiakSUMsQIQ/132"));String nickname = "易幻";String courseName = "做有知识的消费者,过1%的品质生活";String courseTip = "给人看和给人讲的PPT有什么区别?\n为什么用了模板还是很丑为什么用了模板还是很丑为什么用了模板还是很丑?\n如何体现PPT制作的专业性?";BufferedImage img = ImageUtils.createSharePoster(bg, poster, qr, avatar, getPingFang(), nickname, courseName, courseTip);ImageIO.write(img, "jpg", new File("C:\\Users\\youqiang.xiong\\Desktop\\底图\\result5.jpg"));} catch (Exception e) {e.printStackTrace();}}

上面的图片是读取我本地的图片,为了方便大家测试,我也把这几张底图和教师形象图上传,以便大家测试,下载图片到本地后,记得修改main方法中的图片路径

第1张海报底图make_poster_base.png

第2张教师形象图poster.jpg

第3张小程序码图片qr.jpg

图片准备好,运行main方法,在指定目录下会生成合成图片 如下图所示:

放大图片效果:

到这里一个完成合成小程序海报图的功能已经完成,还算是比较简单的,只需要根据ui给的设计稿来调整字体大小,颜色,xy坐标,长宽即可。

微信小程序海报生成图片合成工具类相关推荐

  1. 微信小程序之生成图片保存到相册

    微信小程序之生成图片保存到相册 需求概要 电商项目中需要将自己小店的商品带上自己的小程序码生成海报,保存到本地,然后分享到万能的朋友圈,QQ空间,微博等等来广而告之- 如下图,三种海报格式轮播展示,左 ...

  2. 微信小程序之生成图片分享

    通过社交软件分享的方式来进行营销小程序,是一个常用的运营途径.小程序本身支持直接将一个小程序的链接卡片分享至微信好友或微信群,然后别人就可以通过点击该卡片进入该小程序页面.但是小程序目前不支持直接分享 ...

  3. 微信小程序商品详情html,微信小程序关于商品详情类的富文本解析器

    微信小程序关于商品详情类的富文本解析器 2020年08月10日 | 萬仟网IT编程 | 我要评论 微信小程序关于商品详情类的富文本解析器富文本的解析,在vue中有v-html解析富文本的方法,但是在微 ...

  4. 【微信小程序】5分钟实现微信小程序海报

    5分钟实现微信小程序海报页 备受青睐 不用安装.微信小程序是一种不需要安装即可使用的应用 跨平台性.一份代码即可多个平台使用 推广容易.用户扫一扫或搜一下即可打开应用 推荐使用 随着业务需求的不多发展 ...

  5. 微信小程序海报功能插件

    文章目录 前言 一.微信小程序海报功能插件 二.效果 前言 微信小程序海报功能插件. 提示:以下是本篇文章正文内容,下面案例可供参考 一.微信小程序海报功能插件 https://github.com/ ...

  6. 用canvas绘制微信小程序海报页面并保存相册-适用微信原生

    微信小程序绘制海报并保存相册 tip:代码中使用的是uni的api 如果使用原生微信小程序开发,可以把uni更换成wx使用 文章目录 微信小程序绘制海报并保存相册 前言 一.分析需求 二.准备数据 三 ...

  7. 微信小程序云开发日记类日记记录分享动态

    微信公众号:创享日记(微信号csds992022) 发送关键词:日记类小程序 免费获取源码 1 概述 1.1 关于本手册 为了使您对研岸日记记录社交软件的使用有清晰详尽的了解,特此编写<用户手册 ...

  8. 计算机毕业设计之微信小程序的废品回收类程序 垃圾回收app论文

    摘 要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,废品回收类小程序被用户普遍使用,为方便用户能够 ...

  9. (附源码)springboot基于微信小程序的高校计算机类课程思政库的设计与实现 毕业设计 271611

    小程序+spring boot高校计算机类课程思政库 摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用 ...

最新文章

  1. 使用SQLServer配置管理器配置SQLServer数据库引擎实例,以便侦听特定的固定1433端口。...
  2. 重磅开源人工智能纹理分割自动分割由参考纹理覆盖图像自监督学习
  3. 类型参数的约束(C# 编程指南)
  4. Android 在menu中同时显示Icon和Text
  5. 52是什么水平_送礼送什么白酒,适合送礼的白酒推荐,看这篇最新白酒送礼指南就行了...
  6. 如何在Eclipse中查看Android API源码以及support包源码
  7. php新手最容易犯的错误,学习PHP过程中容易犯的一些错误
  8. .net 怎么在控制器action中返回一个试图_一个view事件分发,面试官6连问直击灵魂,我被虐的体无完肤...
  9. JQuery DataTables Editor---只修改页面内容
  10. audio标签的controls属性_HTML5 新增标签和属性
  11. PHP-Java-Bridge使用笔记
  12. Ble扫描导致wifi信号弱/断开解决
  13. equals方法 和 ==的区别
  14. Matlab取整函数
  15. c语言 控制电脑程序,c语言程序设计
  16. 天线测试系统NSAT-1000,天线测试方案推荐
  17. Oracle汉字排序nls_sort
  18. FontAwesome静态旋转翻转图标类(fa-rotatefa-flip)
  19. 如何获取自己的公网地址
  20. 基于阿里云生态构建网聚宝业务监控系统

热门文章

  1. 知到网课大学生心理健康教育考试试题|真题题库(含答案)
  2. 英才计划计算机潜质测评试题,2018年“英才计划”综合实践活动通知
  3. ASP.NET MVC5 实现基于Quartz.NET任务调度
  4. 创新实训(46)——基于ElasticSearch的Completion Suggest实现搜索提示
  5. 【Java】JDK安装在D盘,环境变量如何配置?
  6. 尚硅谷-康师傅-MySQL详细笔记(1-9章)
  7. matlab求多元函数的极小值,[转载]利用MATLAB求多元函数的极值(2)
  8. 我的面试宝典(1):给自己定位-霍兰德职业测试
  9. php函数 去空格,php删除空格函数是什么
  10. 高版本Andriod Studio集成HMS环境看这篇就够了(附加步骤多图、资源下载、源代码、问题总结)