純 Java2D 即可將文字渲染為 PNG 圖片,支援完整字體屬性(字體、大小、粗體、斜體、底線)、前景色、背景色、反鋸齒。本文提供可直接執行的工具類,支援命令列參數化呼叫。
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
public class TextToImage {
public static void main(String[] args) throws Exception {
if (args.length < 9) {
System.err.println("參數: text family size bold italic underline fcolor bcolor outputFile");
System.err.println("範例: \"Hello\" \"微軟正黑體\" 24 1 0 0 \"255,0,0\" \"\" out.png");
return;
}
String text = args[0];
String family = args[1];
int size = Integer.parseInt(args[2]);
boolean bold = "1".equals(args[3]);
boolean italic = "1".equals(args[4]);
boolean underline = "1".equals(args[5]);
String fcolor = args[6];
String bcolor = args[7];
File outFile = new File(args[8]);
Map<TextAttribute, Object> attrs = new HashMap<>();
attrs.put(TextAttribute.FAMILY, family.isEmpty() ? "SansSerif" : family);
attrs.put(TextAttribute.SIZE, size);
if (bold) attrs.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
if (italic) attrs.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
if (underline) attrs.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
// 前景色
if (fcolor.contains(",")) {
String[] c = fcolor.split(",");
attrs.put(TextAttribute.FOREGROUND, new Color(Integer.parseInt(c[0]), Integer.parseInt(c[1]), Integer.parseInt(c[2])));
} else {
attrs.put(TextAttribute.FOREGROUND, Color.BLACK);
}
// 背景色(可選)
if (bcolor.contains(",")) {
String[] c = bcolor.split(",");
attrs.put(TextAttribute.BACKGROUND, new Color(Integer.parseInt(c[0]), Integer.parseInt(c[1]), Integer.parseInt(c[2])));
}
Font font = new Font(attrs);
createImage(text, font, outFile);
System.out.println("已產生: " + outFile.getAbsolutePath());
}
public static void createImage(String str, Font font, File outFile) throws Exception {
// 計算文字邊界
FontRenderContext frc = new FontRenderContext(AffineTransform.getScaleInstance(1, 1), true, true);
Rectangle2D bounds = font.getStringBounds(str, frc);
int width = (int) Math.ceil(bounds.getWidth()) + 1;
int height = (int) Math.ceil(bounds.getHeight()) + 4;
// 建立支援透明度的圖片
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
// 反鋸齒與渲染品質
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setFont(font);
// 繪製基線位置:y = ascent
FontMetrics fm = g2d.getFontMetrics();
int y = fm.getAscent();
g2d.drawString(str, 0, y);
g2d.dispose();
ImageIO.write(img, "PNG", outFile);
}
}
# 紅字、白底、粗體、24pt、微軟正黑體
java TextToImage "你好世界" "微軟正黑體" 24 1 0 0 "255,0,0" "255,255,255" hello.png
# 透明背景、藍字、斜體、底線
java TextToImage "Transparent" "Serif" 30 0 1 1 "0,0,255" "" transparent.png
| 功能 | 實現方式 |
|---|---|
| 字體屬性 | TextAttribute Map 傳入 Font 建構子 |
| 文字邊界計算 | Font.getStringBounds() + FontRenderContext |
| 透明背景 | BufferedImage.TYPE_INT_ARGB + 無背景色屬性 |
| 反鋸齒 | RenderingHints.KEY_ANTIALIASING + KEY_TEXT_ANTIALIASING |
| 基線對齊 | FontMetrics.getAscent() 作為 drawString y 座標 |
TextLayout 或 LineBreakMeasurer 實現自動換行。AffineTransform 位移繪製陰影、TextAttribute.STROKE 設定描邊。BufferedImage 與 Graphics2D、使用物件池。Font.createFont(Font.TRUETYPE_FONT, new File("custom.ttf")) 載入外部 TTF。