首页 > 编程语言 >java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题

java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题

时间:2022-12-30 18:34:55浏览次数:78  
标签:文字 Graphics2D java String BufferedImage width new import


文章目录

  • ​​先看成品​​
  • ​​前言​​
  • ​​一、项目目录结构​​
  • ​​一、海报制作PosterUtil.java工具类​​
  • ​​1. 描述​​
  • ​​2. 代码​​
  • ​​二、测试生成海报​​
  • ​​1. 描述​​
  • ​​2. 直接上代码​​
  • ​​四、其他测试​​
  • ​​1. Test1_CreateImage 测试创建图片​​
  • ​​a、代码​​
  • ​​b、效果​​
  • ​​2. Test2_CreateEcharts 创建echarts图​​
  • ​​a、代码​​
  • ​​b、效果​​
  • ​​3. Test3_HeadImageToCircle 创建圆形头像​​
  • ​​a、代码​​
  • ​​b、效果​​

先看成品

  • 做成海报样品如下:(第二个是java后端使用echarts生成)

  • 海报原模板如下:


java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题_小程序


前言

  • 刚做的微信小程序,用户说要加个海报功能,而且是 ​用java在后端生成​​ ,直接返回给前端一个URL, 就有点费劲啦,以前没整过,然后开始研究,用了三天的时间把样品做出来了,先送上来给大家看看,除了二维码是真的,其余都是假的,也请大家不要乱搞哦,菜鸟在这里谢过啦。 ​java 整合echarts
  • 代码都上传到GitHub了,这里仅仅是贴出来主要部分,GitHub传送门:​https://github.com/fengfanli/draw_poster_echarts​
  • 问题总结
  • 总博客:java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
  1. ​文字换行算法详解​​,传送门:​​java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解​​
  2. ​头像切割成圆形方法详解​​,传送门:​​java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解​​
  3. ​获取微信二维码详情​​,传送门:​​java制作海报三:获取微信二维码详情,并改变大小,合成到海报(另一张图片)上​​
  4. ​java BufferedImage 转 InputStream​​​和 ​​png 图片合成到模板(另一个图片)上时,透明部分变成了黑色​​,传送门:​​java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色​​
  5. ​java 整合echarts 画出 折线图​​,传送门:
  6. ​Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题​​,传送门:​​java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题​​
  7. ​项目部署到linux下中文不显示,echarts图上的中文也不显示问题​​,传送门:​​java制作海报七:java Graphics2D 合成图片 在 linux下中文不显示,echarts图上的中文也不显示问题​​

一、项目目录结构

运行 ​​Main_CreatePosterAndEchart​​ 类 可以直接生成。注意一下 OSS ,我这里给删除了一点,可以注释掉,生成保存到本地。

java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题_小程序_02

一、海报制作PosterUtil.java工具类

1. 描述

里面是制作海报的工具类,手写了一些方法,比如:写文字方法(里面包括了换行算法)、画图片方法、头像切割成圆形方法、保存到本地方法、改变图片的大小方法等等。

2. 代码

package com.feng.posterUtils;

import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
* @ClassName PictorialUtils
* @Description TODO
* @Author fengfanli
* @Date 2021/3/29 16:48
* @Version 1.0
*/
public class PosterUtil {


/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description //TODO 初始化背景模板
* @Date 9:55 2021/3/30
* @Param [path]
**/
public static BufferedImage drawInit(String path, InputStream inputStream) throws Exception {
BufferedImage canvas = null;
if (path != null) {
URL url = new URL(path);
canvas = ImageIO.read(url);
}
if (inputStream != null) {
canvas = ImageIO.read(inputStream);
}
return canvas;
}

/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description //TODO 初始化模板并改变宽度和高度
* @Date 9:56 2021/3/30
* @Param [path, width, height]
**/
public static BufferedImage drawInitAndChangeSize(String path, InputStream inputStream, int width, int height) throws Exception {
BufferedImage canvas = null;
if (path != null) {
URL url = new URL(path);
canvas = ImageIO.read(url);
}
if (inputStream != null) {
canvas = ImageIO.read(inputStream);
}
canvas = changeSize(canvas, width, height);
return canvas;
}


/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description // TODO 改变宽度和高度:先画一个空白的图,再将需要改变大小的图 画上去,再限制大小
* @Date 9:56 2021/3/30
* @Param [originalImage, width, height]
**/
public static BufferedImage changeSize(BufferedImage originalImage, int width, int height) {
// 抗锯齿
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // originalImage.getType() 改为 BufferedImage.TYPE_INT_RGB
Graphics2D g2d = image.createGraphics();
image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.OPAQUE);
g2d = image.createGraphics();
g2d.drawImage(originalImage, 0, 0, width, height, null);
g2d.dispose();
return image;
}


/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description //TODO 在背景模板上放置 image
* @Date 9:57 2021/3/30
* @Param [canvas, logo, logoX, logoY]
**/
public static void drawImage(BufferedImage canvas, BufferedImage logo, int logoX, int logoY) {
Graphics2D g2d = canvas.createGraphics();
//g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(logo, logoX, logoY, null);
g2d.dispose();
}

/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description //TODO 画图 改变背景颜色,并改变大小(原图片先生成,合成时在缩小)
* TODO 重点1 :图片合成时会出现失真的情况。
* TODO 合成方案有两种:a、原图片先缩小,在合成(会失真)
* TODO b、原图片先生成,合成时在缩小(会好点)
* @Date 9:57 2021/3/30
* @Param [canvas, logo, logoX, logoY]
**/
public static void drawImageAndChangeBackgroundColorAndChangeSize(BufferedImage canvas, BufferedImage logo, Integer logoX, Integer logoY, Integer width, Integer height) throws IOException {
Graphics2D g2d = canvas.createGraphics();

// 解决png透明图片会变黑的问题(画一个新图片,然后合成,记得透明度)
Graphics2D graphics = logo.createGraphics();
BufferedImage compatibleImage = null;
compatibleImage = graphics.getDeviceConfiguration().createCompatibleImage(logo.getWidth(null), logo.getHeight(null), BufferedImage.TYPE_INT_RGB);
// 下面这行也可以代替上面这行
//BufferedImage compatibleImage = new BufferedImage(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT);
graphics = compatibleImage.createGraphics();
graphics.drawImage(logo, 0, 0, logo.getWidth(null), logo.getHeight(null), null);
graphics.dispose();

// 合成图片
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(compatibleImage, logoX, logoY, width, height, null);
g2d.dispose();
}

/**
* @return void
* @Author fengfanli
* @Description //TODO 画图 改变背景颜色
* TODO 重点1 :png图片合成到另一个图片时,透明地带出现黑色情况, 原因:Graphics2D 创建图片背景为黑色
* @Date 16:31 2021/4/8
* @Param [canvas, logo, logoX, logoY]
**/
public static void drawImageAndChangeBackgroundColor(BufferedImage canvas, BufferedImage logo, Integer logoX, Integer logoY) throws IOException {
Graphics2D g2d = canvas.createGraphics();

// 解决png透明图片会变黑的问题(画一个新图片,然后合成,记得透明度)
Graphics2D graphics = logo.createGraphics();
BufferedImage compatibleImage = graphics.getDeviceConfiguration().createCompatibleImage(logo.getWidth(null), logo.getHeight(null), Transparency.TRANSLUCENT);
// 下面这行也可以代替上面这行
//BufferedImage compatibleImage = new BufferedImage(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT);
graphics = compatibleImage.createGraphics();
graphics.drawImage(logo, 0, 0, null);
graphics.dispose();

// 合成图片
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(compatibleImage, logoX, logoY, null);
g2d.dispose();
}


/**
* @return java.awt.Graphics2D
* @Author fengfanli
* @Description //TODO 在背景模板上写字,注意 需要换行算法
* @Date 9:58 2021/3/30
* @Param [bufferedImage, words, wordsFont, fontSize, wordsX, wordsY, wordsWidth, wordsHeight]
**/
public static void drawWords(BufferedImage bufferedImage, String words, Boolean isAddFontSpace, String wordsFont, int fontSize, int wordsX,
int wordsY, int wordsWidth, int wordsHeight) {
Graphics2D g2d = bufferedImage.createGraphics();
// 抗锯齿 添加文字
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); // VALUE_TEXT_ANTIALIAS_ON 改为 VALUE_TEXT_ANTIALIAS_LCD_HRGB
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.getDeviceConfiguration().createCompatibleImage(wordsWidth, wordsHeight, Transparency.TRANSLUCENT);
Font font = new Font(wordsFont, Font.BOLD, fontSize);
g2d.setFont(font);
Color color = new Color(51, 51, 51);
g2d.setColor(color);
// 换行算法
drawWordAndLineFeed(g2d, font, words, wordsX, wordsY, wordsWidth);
g2d.dispose();
}

/**
* @return void
* @Author fengfanli
* @Description //TODO 写字换行算法
* @Date 18:08 2021/4/1
* @Param []
**/
private static void drawWordAndLineFeed(Graphics2D g2d, Font font, String words, int wordsX, int wordsY, int wordsWidth) {
FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
// 获取字符的最高的高度
int height = metrics.getHeight();

int width = 0;
int count = 0;
int total = words.length();
String subWords = words;
int b = 0;
for (int i = 0; i < total; i++) {
// 统计字符串宽度 并与 预设好的宽度 作比较
if (width <= wordsWidth) {
width += metrics.charWidth(words.charAt(i)); // 获取每个字符的宽度
count++;
} else {
// 画 除了最后一行的前几行
String substring = subWords.substring(0, count);
g2d.drawString(substring, wordsX, wordsY + (b * height));
subWords = subWords.substring(count);
b++;
width = 0;
count = 0;
}
// 画 最后一行字符串
if (i == total - 1) {
g2d.drawString(subWords, wordsX, wordsY + (b * height));
}
}
}


/**
* @return java.awt.image.BufferedImage
* @Author fengfanli
* @Description //TODO 将正方形的头像 改为 圆形头像
* @Date 14:37 2021/3/31
* @Param [imgUrl, width]
**/
public static BufferedImage drawImgToCircle(String imgUrl, int width) throws IOException {
BufferedImage avatarImage = ImageIO.read(new URL(imgUrl));
//int width = 120;
// 透明底的图片
BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = formatAvatarImage.createGraphics();
//把图片切成一个圓
{
// 抗锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
int border = 1;
//图片是一个圆型
Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
//需要保留的区域
graphics.setClip(shape);
graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
graphics.dispose();
}
return formatAvatarImage;
}


/**
* @return java.lang.String
* @Author fengfanli
* @Description //TODO 存放到本地
* @Date 9:58 2021/3/30
* @Param [canvas, type, urlPath]
**/
public static void save(BufferedImage canvas, String type, String urlPath) throws Exception {
ImageIO.write(canvas, type, new File(urlPath));
}
}

二、测试生成海报

1. 描述

注释很详细,直接看注释即可

2. 直接上代码

package com.feng.controller;

import com.alibaba.fastjson.JSONObject;
import com.feng.bean.BakeEventList;
import com.feng.bean.PhotoSeaMainModel;
import com.feng.bean.XfxUserbaseModel;
import com.feng.echartsUtils.EchartsUtil;
import com.feng.echartsUtils.HttpUtil;
import com.feng.fileUtils.PropertiesFileUtil;
import com.feng.ossUtils.OssUtil;
import com.feng.posterUtils.PosterUtil;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.*;

/**
* @ClassName Main
* @Description TODO
* @Author admin
* @Date 2021/3/30 15:21
* @Version 1.0
*/
public class Main_CreatePosterAndEchart {

public static void main(String[] args) {
// 生成海报
Map<String, Object> result = createPoster();
System.out.println(result);
// 生成 带echarts图的海报
Map<String, Object> posterDrawEchartTable = createPosterDrawEchartTable();
System.out.println(posterDrawEchartTable);
}

/**
* @Author fengfanli
* @Description //TODO 创建海报,画字、画图
* @Date 17:41 2021/4/8
* @Param []
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
public static Map<String, Object> createPoster() {
String nickName = "爱吃鱼的猫";
// headUrl
String headUrl = "/i/?i=20180529211243786?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3plbmdyZW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/7";
// 单品生豆背景模板图
String background = "https://xkximg.xiaokaxia.com/wx/1/9dfb96f770e64642835289912cc13c46.png";
// 统一字体 格式
String wordsFont = "平方-简";

Map<String, Object> map = new HashMap<>();
try {
// 初始化模板图
BufferedImage bufferedImage = PosterUtil.drawInit(background, null);
// 将头像图片处理成圆形
BufferedImage head = PosterUtil.drawImgToCircle(headUrl, 92);
// 画 微信头像
PosterUtil.drawImage(bufferedImage, head, 49, 49);

// 下面三个数据都可以从数据库中动态获取
String title = "布隆迪BURUNDI恩戈齐NGOZI2020-2021瑰夏GEISHA日晒处理";
String provider = "生豆商信息生豆商信息生豆商信息生豆商信息生豆商信息生豆商信息生豆商信息生豆商信息生豆商信息"; // 42
if (provider.length() > 42) {
provider = provider.substring(0, 42) + "...";
}
String remark = "备注信息备注信息备注信息备注信息备注信息备注信息备注信息备注信息备注信息备注信息";
if (remark.length() > 28) {
remark = remark.substring(0, 28) + "...";
}
String rawInfoMood = "为您诚挚推荐生豆信息";

// 画 二维码 并改变大小
// 1. 先 获取二维码(二维码携带一个参数)
InputStream erWeiMa = getErWeiMa(1);
// 2. 初始化并的改变大小
BufferedImage logoImg = PosterUtil.drawInitAndChangeSize(null, erWeiMa, 130, 130);
// 将二维码保存到本地
PosterUtil.save(logoImg, "png", "d:\\test.png");
// 3. 画二维码
PosterUtil.drawImage(bufferedImage, logoImg, 532, 1108);

// 自定义咖啡背景图片
String customCoffeeImageUrl = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1789442356,2769602647&fm=26&gp=0.jpg";
BufferedImage coffeeImage = PosterUtil.drawInitAndChangeSize(customCoffeeImageUrl, null, 575, 431);
PosterUtil.drawImage(bufferedImage, coffeeImage, 87, 379);

// 画字:nickName
PosterUtil.drawWords(bufferedImage, nickName, false, wordsFont, 28, 158, 90, 1000, 26);
// 画字:rawInfoMood:为您诚挚推荐生豆信息
PosterUtil.drawWords(bufferedImage, rawInfoMood, false, wordsFont, 20, 158, 125, 1000, 19);
// 画字:title

PosterUtil.drawWords(bufferedImage, title, true, wordsFont, 36, 88, 265, 552, 119);
// 画字:provider
PosterUtil.drawWords(bufferedImage, provider, false, wordsFont, 30, 89, 870, 552, 100);
// 画字:remark
PosterUtil.drawWords(bufferedImage, remark, false, wordsFont, 24, 88, 1000, 552, 70);

// 海报 保存到本地
PosterUtil.save(bufferedImage, "png", "d:\\singleRawBeanBackground.png");

// 上传到 OSS
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", os);
InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
// map = uploadShareSeaImg(inputStream, "bakeShare", request);
map = uploadShareSeaImg(inputStream, "bakeShare");
return map;
} catch (Exception e) {
System.out.println("PictorialController createPoster error:" + e.getLocalizedMessage());
return null;
}
}


/**
* @Author fengfanli
* @Description //TODO 创建海报,画字,画图,画echarts图
* @Date 17:41 2021/4/8
* @Param []
* @return java.util.Map<java.lang.String,java.lang.Object>
**/
public static Map<String, Object> createPosterDrawEchartTable() {
String nickName = "爱吃鱼的猫";
// headUrl
String headUrl = "/i/?i=20180529211243786?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3plbmdyZW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/7";
// 单品烘焙背景模板图
String background = "https://xkximg.xiaokaxia.com/wx/1/fb16ea06f66644009f54b8efbb670bd2.png";
// 统一字体 格式
String wordsFont = "平方-简";

Map<String, Object> map = new HashMap<>();
try {
// 初始化模板图
BufferedImage bufferedImage = PosterUtil.drawInit(background, null);
// 将头像图片处理成圆形
BufferedImage head = PosterUtil.drawImgToCircle(headUrl, 92);
// 画 微信头像
PosterUtil.drawImage(bufferedImage, head, 49, 49);

// 下面三个数据都可以从数据库中动态获取
String title = "布隆迪BURUNDI恩戈齐NGOZI2020-2021瑰夏GEISHA日晒处理";
String rawInfoMood = "为您诚挚推荐烘焙信息";

// 画 二维码 并改变大小
// 1. 先 获取二维码(二维码携带一个参数)
InputStream erWeiMa = getErWeiMa(1);
// 2. 初始化并的改变大小
BufferedImage logoImg = PosterUtil.drawInitAndChangeSize(null, erWeiMa, 130, 130);
// 将二维码保存到本地
PosterUtil.save(logoImg, "png", "d:\\test.png");
// 3. 画二维码
PosterUtil.drawImage(bufferedImage, logoImg, 532, 1108);

// 自定义咖啡背景图片
String customCoffeeImageUrl = "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1789442356,2769602647&fm=26&gp=0.jpg";
BufferedImage coffeeImage = PosterUtil.drawInitAndChangeSize(customCoffeeImageUrl, null, 575, 287);
PosterUtil.drawImage(bufferedImage, coffeeImage, 87, 379);

// 画字:nickName
PosterUtil.drawWords(bufferedImage, nickName, false, wordsFont, 28, 158, 90, 1000, 26);
// 画字:rawInfoMood:为您诚挚推荐生豆信息
PosterUtil.drawWords(bufferedImage, rawInfoMood, false, wordsFont, 20, 158, 125, 1000, 19);
// 画字:title
PosterUtil.drawWords(bufferedImage, title, true, wordsFont, 36, 88, 265, 552, 119);
// 画表格
List<BakeEventList> bakeEventLists = new ArrayList<>();
bakeEventLists.add(new BakeEventList("12:01", 10.10));
bakeEventLists.add(new BakeEventList("13:01", 15.10));
bakeEventLists.add(new BakeEventList("14:01", 18.10));
bakeEventLists.add(new BakeEventList("15:01", 5.10));
bakeEventLists.add(new BakeEventList("16:01", 4.10));
try {
EchartsUtil.createEcharts(bufferedImage, bakeEventLists);
} catch (Exception e) {
System.out.println("PosterController createPoster bake draw table error:" + e);
}

// 海报 保存到本地
PosterUtil.save(bufferedImage, "png", "d:\\singleRawBeanBackground.png");

// 上传值 OSS
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "png", os);
InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
// map = uploadShareSeaImg(inputStream, "bakeShare", request);
map = uploadShareSeaImg(inputStream, "bakeShare");
return map;
} catch (Exception e) {
System.out.println("PictorialController createPictorial error:" + e.getLocalizedMessage());
return null;
}
}


/**
* @return java.io.InputStream
* @Author fengfanli
* @Description //TODO 从微信平台 获取小程序二维码
* @Date 16:53 2021/4/1
* @Param []
**/
public static InputStream getErWeiMa(Integer id) {
// 获取二维码:1、先获取access_token 2、在获取 二维码
String appId = PropertiesFileUtil.getInstance("app").get("wx.app.ip");
String appSecret = PropertiesFileUtil.getInstance("app").get("wx.app.secret");
System.out.println("appId==" + appId + ";appSecret==" + appSecret);
// 获取 access_token
String getUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
System.out.println("getUrl==" + getUrl);
String str = HttpUtil.sendGet(getUrl);
JSONObject json = (JSONObject) JSONObject.parse(str);
String access_token = (String) json.get("access_token");
System.out.println("access_token:" + access_token);
// 获取 二维码图片流
String postURL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token;
System.out.println("postURL==" + postURL);
JSONObject jsonObject = new JSONObject();
// 这里往二维码里放入前端传过来的 id,前端获取之后,根据id 去获取详情
jsonObject.put("scene", id);
String scene = JSONObject.toJSONString(jsonObject);
InputStream inputStream = null;
inputStream = HttpUtil.sendPostForErWeiMa(postURL, scene);
return inputStream;
}


/**
* @return java.util.Map<java.lang.String , java.lang.Object>
* @Author fengfanli
* @Description //TODO 上传生成的海报 上传到云服务器 并返回给前端 url
* @Date 16:54 2021/4/1
* @Param [inputStream, shareCategory, request]
**/
public static Map<String, Object> uploadShareSeaImg(InputStream inputStream, String shareCategory) {
// 获取用户的目的是为了 1、文件新名称,2、将海报添加到数据库做记录
// XfxUserbaseModel user = upmsSessionDao.getUser(request); // 通过 request 获取当前用户信息。
XfxUserbaseModel user = new XfxUserbaseModel(); // 就是一个用户实体类
user.setId(1);
// 新名称
String newFileName = UUID.randomUUID().toString().replace("-", "") + ".png";
String key = "wx/" + user.getId() + "/" + shareCategory + "/" + newFileName;
String ok = OssUtil.uploadImg(key, inputStream);
if (!"OK".equals(ok)) {
System.out.println("PosterController oss uploadShareSeaImg fail:" + user.getId());
}
Map<String, Object> map = new HashMap<>(2);
map.put("ossKey", key);
map.put("fileUrl", OssUtil.getImgUrl(key));
// 将做好的海报URL oss key 放到 数据库
PhotoSeaMainModel model = new PhotoSeaMainModel();
model.setUserId(user.getId());
model.setTitle(shareCategory);
model.setFileOss(key);
// photoSeaService.addPhotoSeaModel(model);
return map;
}

}

四、其他测试

1. Test1_CreateImage 测试创建图片

a、代码

package com.feng.controller;

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Test1_CreateImage {

/**
* @Author fengfanli
* @Description //TODO 生成一个白色的图片
* @Date 15:51 2021/4/8
* @Param [args]
* @return void
**/
public static void main(String[] args) throws Exception {
BufferedImage bufIma = new BufferedImage( 50, 50, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufIma.createGraphics();
g2d.setBackground(new Color(255, 255, 255));
g2d.clearRect(0, 0, 50, 50);
ImageIO.write(bufIma, "png", new File("d:\\6.png"));

}
}

b、效果

java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题_html_03

2. Test2_CreateEcharts 创建echarts图

a、代码

package com.feng.controller;

import com.alibaba.fastjson.JSON;
import com.feng.echartsUtils.EchartsUtil;
import com.feng.echartsUtils.FreemarkerUtil;
import freemarker.template.TemplateException;
import org.apache.http.client.ClientProtocolException;

import java.io.IOException;
import java.util.HashMap;

/**
* @ClassName CreateEcharts
* @Description TODO
* @Author admin
* @Date 2021/4/8 15:40
* @Version 1.0
*/
public class Test2_CreateEcharts {

/**
* @Author fengfanli
* @Description //TODO 创建一个echarts图
* @Date 18:06 2021/4/8
* @Param [args]
* @return void
**/
public static void main(String[] args) throws ClientProtocolException, IOException, TemplateException {
// 变量
String title = "水果";
String[] categories = new String[]{"苹果", "香蕉", "西瓜"};
int[] values = new int[]{3, 2, 1};

// 模板参数
HashMap<String, Object> datas = new HashMap<>();
datas.put("categories", JSON.toJSONString(categories));
datas.put("values", JSON.toJSONString(values));
datas.put("title", title);

// 生成option字符串
String option = FreemarkerUtil.generateString("option.ftl", "echarts", datas);

// 根据option参数
String base64 = EchartsUtil.generateEchartsBase64(option);

System.out.println("BASE64:" + base64);
EchartsUtil.generateImage(base64, "C:\\Users\\admin\\Desktop\\test.png");
}
}

b、效果

java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题_Image_04

3. Test3_HeadImageToCircle 创建圆形头像

a、代码

package com.feng.controller;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;

/**
* Created by zengrenyuan on 18/5/29.
*/
/**
* @Author fengfanli
* @Description //TODO 将头像画成圆形
* @Date 18:29 2021/4/7
* @Param
* @return
**/
public class Test3_HeadImageToCircle {

/**
* @Author fengfanli
* @Description //TODO 将一个头像 变成圆形
* @Date 18:11 2021/4/8
* @Param [args]
* @return void
**/
public static void main(String[] args) throws IOException {
String url = "/i/?i=20180529211243786?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3plbmdyZW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/7";
BufferedImage avatarImage = ImageIO.read(new URL(url));
int width = 120;
// 透明底的图片
BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D graphics = formatAvatarImage.createGraphics();
//把图片切成一个圓
{
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//留一个像素的空白区域,这个很重要,画圆的时候把这个覆盖
int border = 1;
//图片是一个圆型
Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
//需要保留的区域
graphics.setClip(shape);
graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
graphics.dispose();
}
try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test2.png")) {
ImageIO.write(formatAvatarImage, "PNG", os);
}
//在圆图外面再画一个圆
{
//新创建一个graphics,这样画的圆不会有锯齿
graphics = formatAvatarImage.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int border = 3;
//画笔是4.5个像素,BasicStroke的使用可以查看下面的参考文档
//使画笔时基本会像外延伸一定像素,具体可以自己使用的时候测试
Stroke s = new BasicStroke(4.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
graphics.setStroke(s);
graphics.setColor(Color.WHITE);
graphics.drawOval(border, border, width - border * 2, width - border * 2);
graphics.dispose();
}
try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test3.png")) {
ImageIO.write(formatAvatarImage, "PNG", os);
}
{
url = "/i/?i=20180529213113521";
BufferedImage srcImg = ImageIO.read(new URL(url));
//scrImg加载完之后没有任何颜色
BufferedImage blankImage = new BufferedImage(srcImg.getWidth(), srcImg.getHeight(), BufferedImage.TYPE_INT_RGB);
graphics = blankImage.createGraphics();
graphics.drawImage(srcImg, 0, 0, null);

int x = (blankImage.getWidth() - width) / 2;
int y = (blankImage.getHeight() - width) / 2;
graphics.drawImage(formatAvatarImage, x, y, width, width, null);
try (OutputStream os = new FileOutputStream("C:\\Users\\admin\\Desktop\\test4.png")) {
ImageIO.write(blankImage, "PNG", os);
}
}

}
}

b、效果

java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题_html_05


标签:文字,Graphics2D,java,String,BufferedImage,width,new,import
From: https://blog.51cto.com/u_15926676/5981145

相关文章

  • Java面试题之 mysql面试题
    文章目录​​导言​​​​MySQL的逻辑架构​​​​1.reference​​​​2.架构图​​​​3.日志介绍​​​​一、mysql存储引擎​​​​1.存储引擎是什么​​​​2.各......
  • java租房app房东直租系统租房网站
    简介本系统是前后端分离的项目,前端使用mui开发科打包成为安卓的apk。后端采用springboot开发。主要是房东登录注册后,可以发布房源信息,可以上架下架编辑删除房源信息等,租房......
  • java养老系统养老院系统养老院网站源码
    简介本系统是养老院系统,主要是老人入住养老院的业务逻辑,有护工和医生对老人进行护理看病记录等信息管理,缴费入住外出记录管理等。演示视频https://www.bilibili.com/vid......
  • java企业通知小程序微信消息推送小程序企业消息通知系统网站源码
    简介本系统主要是利用小程序和springboot开发的企业分组消息推送,主要是员工关注小程序,由分组领导创建消息主体并设置消息提醒时间,利用微信的消息模板对选定的员工进行消息......
  • java开发的玩具商城系统玩具店
    简介Java使用ssm框架开发的玩具商城,用户可以浏览商品,搜索,分类查看商品,添加购物车和购买商品,可注册登录,在个人中心管理自己的订单。商家也就是管理员可以在后台发布商品,上......
  • java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
    文章目录​​前言​​​​1.字符与字节​​​​2.编码形式​​​​2.1编码表由来​​​​2.1IDEA查看并设置项目编码格式​​​​3.File类(学IO之前先学这个)​​​​4.......
  • 第七章《Java的异常处理》第4节:throw与throws关键字
    ​在Java的异常处理系统中,除了前面学过的try、catch和finally关键字之外,还有两个非常重要的关键字,它们分别是throw和throws。这两个关键字之间只相差一个字母,但意义却相差很......
  • 【校招VIP】“推推”Java项目课程:产品原型:产品需求要点分析
    VIP的服务,不一样的校招,大家好,我是校招VIP的大拿老师。今天呢我们继续来看商业实战项目推推小说详情模块的第一节课:产品原型。Java同学一定要理解产品在正式的商业项目里......
  • java代码实现上传文件到谷歌云
    1、runconfiguration添加vm参数:-Dhttps.proxy=http://googleapis-dev.gcp.cloud.uk.hsbc:3128-Dhttps.proxyHost=googleapis-dev.gcp.cloud.uk.hsbc-Dhttps.proxyPort=3......
  • java 中的char , utf16 utf8
    在设计Java时决定采用16位的Unicode字符集....(中间省略)...现在16位的Char类型已经不能满足描述所有Unicode字符的需要了。Java为了解决这个问题的方法是使用码点和代码单......