通过java
来绘制海报,加载外部字体并设置样式大小与加粗、设置背景图、合并图片,下面是简单示例
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
/** java 绘制海报
* author xiaochi
* date 2024/11/8
*/
public class PosterCreatorTest{
public static void main(String[] args) throws Exception {
// 创建字体
// Font font = new Font("微软雅黑", Font.BOLD, 36);
// 外部字体
String fontPath = "D:\\workspace\\demo3\\src\\main\\resources\\font\\SmileySans2.ttf";
Font font = Font.createFont(Font.TRUETYPE_FONT, new File(fontPath));
// 合并到图片上的文字
String text = "欢迎来到我的世界";
int width = 854;// 容器宽度
int height = 1280;// 容器高度
BufferedImage bgImage = ImageIO.read(new File("D:\\workspace\\demo3\\test1111.png"));
BufferedImage combiner = combiner(width, height,null, bgImage, bgImage.getWidth(),bgImage.getHeight());
Graphics2D g2d = combiner.createGraphics();
// 绘制文本2(不换行)
g2d.setColor(getColor("#1bdf1a"));
g2d.drawString(text, 100, 100);
// 释放图形上下文
g2d.dispose();
// 绘制文本1(换行)
wrapText(combiner,text,font.deriveFont(Font.BOLD,26f),100,50,10,0,null);
// 设置文本旋转45°
wrapText(combiner,text,font.deriveFont(26f),500,50,combiner.getWidth(),0,null);
wrapText(combiner,text,font.deriveFont(26f),500,50,combiner.getWidth(),45,"#ea6f5a");
// 合并图片
BufferedImage mergeImage = ImageIO.read(new File("D:\\02.png"));
merge(combiner,mergeImage,100,100,100,500);
try {
// 保存图片到文件
//ImageIO.write(image, "PNG", new File("D:\\workspace\\demo3\\poster.png"));
// 输出文件流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(combiner,"png",out);
byte[] bytes = out.toByteArray();
out.close();
FileOutputStream fileOutputStream = new FileOutputStream("D:\\workspace\\demo3\\poster333.png");
fileOutputStream.write(bytes);
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建容器
* @param combinerWidth 容器宽度
* @param combinerHeight 容器高度
* @param bgColor 背景色(默认白色,且背景图会覆盖背景色)
* @param bgImage 背景图
* @param bgImageWidth 背景图宽度
* @param bgImageHeight 背景图高度
* @return combiner容器
*/
public static BufferedImage combiner(int combinerWidth,int combinerHeight,String bgColor,BufferedImage bgImage,int bgImageWidth,int bgImageHeight){
BufferedImage combiner = new BufferedImage(combinerWidth,combinerHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = combiner.createGraphics();
// 设置背景颜色
g2d.setColor(Color.white);
if (null != bgColor && !"".equals(bgColor)){
g2d.setColor(getColor(bgColor));
}
g2d.fillRect(0, 0, combinerWidth, combinerHeight);
// 添加背景图片
if (null != bgImage){
// 添加背景图片
g2d.drawImage(bgImage,0,0,bgImageWidth,bgImageHeight,null);
}
// 释放图形上下文
g2d.dispose();
return combiner;
}
/**
* 合并图片
* @param combiner 容器
* @param mergeImage 待合并的图片
* @param width 待合并的图片宽度
* @param height 待合并的图片高度
* @param x 待合并的图片x坐标
* @param y 待合并的图片y坐标
*/
public static void merge(BufferedImage combiner,BufferedImage mergeImage,int width,int height,int x,int y){
//BufferedImage image = new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = combiner.createGraphics();
g2d.drawImage(mergeImage,x,y,width,height,null);
g2d.dispose();
}
/**
* 绘制文字
* @param combiner 容器
* @param text 文字
* @param font 字体(包括大小、样式、颜色)
* @param x 文字x坐标
* @param y 文字y坐标
* @param maxWidth 文字最大宽度(0为竖排显示)
* @param rotate 旋转度数
* @param color 文字颜色(如:#ffffff)
*/
public static void wrapText(BufferedImage combiner,String text,Font font,int x,int y,int maxWidth,double rotate,String color){
Graphics2D g2d = combiner.createGraphics();
//设置字体
g2d.setFont(font);
// 设置文字颜色
if (null != color && !"".equals(color)){
g2d.setColor(getColor(color));
}
// 抗锯齿属性
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //提升观感
// 设置旋转
AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(rotate),x,y); // 旋转45度,旋转中心为(文字x坐标,100)
g2d.setTransform(at);
FontMetrics fontMetrics = g2d.getFontMetrics(font);
String[] lines = splitText(text, maxWidth, fontMetrics); //实现文字自动换行
int lineHeight = g2d.getFontMetrics().getHeight();
int ystart = y;
for (String line : lines) {
g2d.drawString(line, x, ystart);
ystart += lineHeight;
}
g2d.dispose();
}
/**
* 获取颜色
* @param color #2395439
* @return
*/
public static Color getColor(String color) {
if (color.charAt(0) == '#') {
color = color.substring(1);
}
if (color.length() != 6) {
return null;
}
try {
int r = Integer.parseInt(color.substring(0, 2), 16);
int g = Integer.parseInt(color.substring(2, 4), 16);
int b = Integer.parseInt(color.substring(4), 16);
return new Color(r, g, b);
} catch (NumberFormatException nfe) {
return null;
}
}
/**
* 切割文字
* @param text
* @param maxWidth
* @param fontMetrics
* @return
*/
private static String[] splitText(String text, int maxWidth, FontMetrics fontMetrics) {
StringBuilder wrappedText = new StringBuilder();
String[] words = text.split(""); //以每个字符做拆分,可根据实际需求做更改,下同
List<String> lines = new ArrayList<>();
for (String word : words) {
// 检查添加新单词后是否会超过最大宽度
if (wrappedText.length() > 0) {
// 检查加上新单词后的总长度
if (fontMetrics.stringWidth(wrappedText.toString() + word) > maxWidth) {
// 如果超过最大宽度,将当前字符串添加到行列表,并开始新的一行
lines.add(wrappedText.toString());
wrappedText = new StringBuilder(word);
} else {
// 如果不超过最大宽度,添加新单词
wrappedText.append(word);
}
} else {
wrappedText.append(word);
}
}
// 添加最后一行
if (wrappedText.length() > 0) {
lines.add(wrappedText.toString());
}
// 将行列表转换为数组
return lines.toArray(new String[0]);
}
}
OK了。