Java | 将文字生成在空白图片居中位置(根据图片大小,自动调节文字大小)
话不多说,直接上代码。(大家可以自己根据需要设置图片大小,不过图片过小时,字体会变模糊,尽量设置图片大一点,600~1000左右比较合适)
代码:
import lombok.extern.slf4j.Slf4j;
import sun.font.FontDesignMetrics;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 慌途L
* 描述:将文字居中对齐生成在空白图片中间
*/
@Slf4j
public class ImagesUtils {
/**
* 图片宽度
*/
private static final int WIDTH = 800;
/**
* 图片高度
*/
private static final int HEIGHT = 800;
/**
* 字符间距缩放比
*/
private static final double SCALE_WORD_SPACE = 1.0;
/**
* 文字开头和结尾在图片中距离左、右的总和(单边距离最少30)
*/
private static final int MIN_DISTANCE = 60;
/**
* 文字大小
*/
public static int size = 120;
/**
* 默认字体格式
*/
private static final Font font = new Font("宋体", Font.PLAIN, size);
/**
* 生成图片并转成字节流,方便上传到OSS服务器
*
* @param content 文字
* @return 返回字节流
*/
public static InputStream generateImagesToInputStream(String content) {
BufferedImage image = drawString(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB, content, Color.BLACK, SCALE_WORD_SPACE);
ByteArrayOutputStream os = new ByteArrayOutputStream();
InputStream input = null;
try {
ImageIO.write(image, "jpg", os);
input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
e.printStackTrace();
log.error("根据文字生成图片转换成字节流异常", e);
throw new RuntimeException("根据文字生成图片转换成字节流异常...");
}
}
/**
* 根据文字生成图片
*
* @param content 文字
* @param filePath 生成图片后存的路径和名字(如:D:\\test.jpg)
* @return 返回图片路径
*/
public static String generateImages(String content, String filePath) {
OutputStream out = null;
try {
BufferedImage bufferedImage = drawString(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB, content, Color.BLACK, SCALE_WORD_SPACE);
out = new BufferedOutputStream(new FileOutputStream(filePath));
ImageIO.write(bufferedImage, "jpg", out);
return filePath;
} catch (Exception e) {
e.printStackTrace();
log.error("根据文字生成图片转换成字节流异常", e);
throw new RuntimeException("根据文字生成图片转换成字节流异常...");
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
log.error("关流失败");
}
}
}
/**
* 绘制图片
*
* @param width 画布宽
* @param height 画布高
* @param imageType 画布类型
* @param content 绘制的文本
* @param color 字体颜色
* @param scaleWordSpace 字符间距缩放比
* @return
*/
public static BufferedImage drawString(int width, int height, int imageType, String content, Color color, double scaleWordSpace) {
BufferedImage image = new BufferedImage(width, height, imageType);
Graphics2D graphics = image.createGraphics();
// 填充白色背景图
graphics.fillRect(0, 0, width, height);
graphics.setColor(Color.WHITE);
// 设置字体
Font font = new Font("宋体", Font.PLAIN, size);
graphics.setFont(font);
//根据字体格式,获取字符串占用宽度
int stringWidth = graphics.getFontMetrics().stringWidth(content);
//通过比较字符串体每次设定完尺寸后的宽度是否超过图片宽度限定尺寸,从而减小字体尺寸
while (stringWidth > (width + MIN_DISTANCE)) {
size -= 1;
graphics.setFont(new Font("宋体", Font.PLAIN, size));
stringWidth = graphics.getFontMetrics().stringWidth(content);
}
// 计算文字在图片中的x轴坐标
int x = (width - stringWidth) / 2;
while (x 0) {
tempStr = content.substring(0, 1);
content = content.substring(1);
orgStringWith = graphics.getFontMetrics().stringWidth(tempStr);
graphics.drawString(tempStr, tempx, tempy);
// 如果不是中文则需要增加字符或数字之间的间距
workSpace = !isContainChinese(tempStr) ? 1.3 : workSpace;
if (tempStr.getBytes().length == 1) {
tempx = (int) Math.round(tempx + orgStringWith * workSpace * 0.8);
} else {
tempx = (int) Math.round(tempx + orgStringWith * workSpace);
}
}
}
/**
* 判断字符串中是否包含中文
*
* @param str 待校验字符串
* @return 是:true 否:false
* @warn 不能校验是否为中文标点符号
*/
private static boolean isContainChinese(String str) {
Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
Matcher m = p.matcher(str);
return m.find();
}
public static void main(String[] args) {
String filePath = ImagesUtils.generateImages("12345652316411sdfffdf", "F:\\test.jpg");
System.out.println(filePath);
}
}
欢迎关注公众号:慌途L 后面会慢慢将文章迁移至公众号,也是方便在没有电脑的情况下可以进行翻阅,更新的话会两边同时更新,大家不用担心!
|