Java如何实现向图片添加文本并自适应适配指定矩形区域
Java 图片文本自动换行+字号自适应适配矩形区域实现
实现逻辑
- 先从最大预设字号开始逐步缩小字号,逐一验证当前字号下,文本按矩形宽度自动换行后的总高度是否小于等于矩形高度,找到能完整放下所有文本的最大字号
- 自动换行时按字符粒度拆分,保证每行宽度不超过矩形的最大宽度
- 所有行整体在矩形区域内水平+垂直居中
完整实现代码
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class ImageTextAdaptive { public static void main(String[] args) throws IOException { BufferedImage image = ImageIO.read(new File("img.png")); Graphics2D g2d = (Graphics2D) image.getGraphics(); // 开启抗锯齿让文本更清晰 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 定义文本要适配的矩形区域,这里示例用整个图片,你可以改成自定义尺寸的矩形 Rectangle targetRect = new Rectangle(0, 0, image.getWidth(), image.getHeight()); String content = "TexvzgdsfadvcfkgsdASKJDFHJGgkdgfsakagjASGHDJStTexvzgdsfadvcfkgsdASKJDFHJGgkdgfsakagjASGHDJSt"; // 绘制自适应文本 drawAdaptiveCenteredText(g2d, content, targetRect); g2d.dispose(); ImageIO.write(image, "png", new File("out.png")); } /** * 绘制自适应居中的文本,自动换行+自动调整字号适配矩形区域 */ public static void drawAdaptiveCenteredText(Graphics2D g2d, String text, Rectangle rect) { // 初始最大字号,可根据需求调整 float maxFontSize = 72f; float minFontSize = 6f; Font currentFont = g2d.getFont().deriveFont(maxFontSize); List<String> wrappedLines = new ArrayList<>(); float finalFontSize = maxFontSize; // 逐步缩小字号,直到找到能放下所有文本的最大字号 while (finalFontSize >= minFontSize) { currentFont = g2d.getFont().deriveFont(finalFontSize); FontMetrics metrics = g2d.getFontMetrics(currentFont); wrappedLines = wrapText(text, metrics, rect.width); // 计算所有行的总高度 int totalHeight = wrappedLines.size() * metrics.getHeight(); if (totalHeight <= rect.height) { break; } finalFontSize--; } // 绘制所有行,整体居中 FontMetrics finalMetrics = g2d.getFontMetrics(currentFont); g2d.setFont(currentFont); int lineHeight = finalMetrics.getHeight(); int totalTextHeight = wrappedLines.size() * lineHeight; // 垂直居中的起始y坐标 int currentY = rect.y + (rect.height - totalTextHeight) / 2 + finalMetrics.getAscent(); for (String line : wrappedLines) { // 每行水平居中 int x = rect.x + (rect.width - finalMetrics.stringWidth(line)) / 2; g2d.drawString(line, x, currentY); currentY += lineHeight; } } /** * 按指定宽度自动换行,返回拆分后的行列表 */ private static List<String> wrapText(String text, FontMetrics metrics, int maxWidth) { List<String> lines = new ArrayList<>(); StringBuilder currentLine = new StringBuilder(); for (char c : text.toCharArray()) { currentLine.append(c); if (metrics.stringWidth(currentLine.toString()) > maxWidth) { // 超过宽度就去掉最后一个字符,把当前行加入列表,然后用最后一个字符开启新行 currentLine.deleteCharAt(currentLine.length() - 1); lines.add(currentLine.toString()); currentLine = new StringBuilder(String.valueOf(c)); } } // 加入最后一行 if (currentLine.length() > 0) { lines.add(currentLine.toString()); } return lines; } }
关键参数调整说明
- 可以修改
maxFontSize和minFontSize的初始值,适配你的业务场景需要的字号范围 - 如果需要按单词换行(仅针对英文场景),可以修改
wrapText方法的拆分逻辑,按空格拆分后计算整词宽度,避免单词被截断 - 如果要设置文本颜色,在调用
drawString前调用g2d.setColor()方法设置即可
内容的提问来源于stack exchange,提问作者Fabio grossi
相关产品推荐
相关产品推荐

