本元件提供完整的圖片動態生成能力,適用於驗證碼、報表圖表、水印圖片等場景。核心特性包含:
OutputStream(適合 Web 直接串流回應)AbstractImageCreator定義圖片生成的標準流程(模板方法),將「繪製文字」與「儲存圖片」延遲至子類實作:
public abstract class AbstractImageCreator {
private static final Random RND = new Random(System.currentTimeMillis());
// 可配置屬性(省略 getter/setter)
private int width = 200, height = 80;
private Color rectColor, bgColor;
private int lineNum = 0;
private String formatName = "JPEG";
private Color fontColor = Color.BLACK;
private String fontName = "宋體";
private int fontSize = 15;
// 模板方法:定義生成骨架
public final void drawImage(String text) throws IOException {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
// 1. 背景與邊框
g.setColor(bgColor != null ? bgColor : new Color(240, 251, 200));
g.fillRect(0, 0, width, height);
g.setColor(rectColor != null ? rectColor : Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
// 2. 干擾線
drawRandomLine(g);
// 3. 繪製文字(由子類實作)
drawString(g, text);
// 4. 輸出(由子類實作)
saveImage(image);
g.dispose();
}
private void drawRandomLine(Graphics2D g) {
for (int i = 0; i < lineNum; i++) {
g.setColor(getRandomColor(100, 155));
int x1 = RND.nextInt(width), y1 = RND.nextInt(height);
int x2 = RND.nextInt(width), y2 = RND.nextInt(height);
g.drawLine(x1, y1, x2, y2);
}
}
private Color getRandomColor(int base, int range) {
range = Math.min(range, 255 - base);
return new Color(base + RND.nextInt(range),
base + RND.nextInt(range),
base + RND.nextInt(range));
}
// 留給子類實作的抽象方法
protected abstract void drawString(Graphics2D g, String text);
protected abstract void saveImage(BufferedImage image) throws IOException;
}
DefaultImageCreatorpublic class DefaultImageCreator extends AbstractImageCreator {
private String outputFilePath;
// getter/setter 省略
@Override
protected void drawString(Graphics2D g, String text) {
g.setColor(getFontColor());
Font font = new Font(getFontName(), Font.PLAIN, getFontSize());
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
int lineHeight = fm.getHeight();
int x = 0, line = 1;
for (char c : text.toCharArray()) {
if (Character.isISOControl(c) || x >= getWidth() - fm.charWidth(c)) {
line++; x = 0; // 自動換行
}
g.drawString(String.valueOf(c), x, line * lineHeight);
x += fm.charWidth(c);
}
}
@Override
protected void saveImage(BufferedImage img) throws IOException {
ImageIO.write(img, getFormatName(), new File(outputFilePath));
}
}
OutputStreamImageCreatorpublic class OutputStreamImageCreator extends DefaultImageCreator {
private OutputStream out;
// getter/setter 省略
@Override
protected void saveImage(BufferedImage img) throws IOException {
if (out != null) ImageIO.write(img, getFormatName(), out);
}
}
// 產生含干擾線的驗證碼圖片並寫入檔案
StringBuilder sb = new StringBuilder();
sb.append("中華人民共和國\n").append("中華人民共和國\n");
DefaultImageCreator creator = new DefaultImageCreator("c:/captcha.jpg");
creator.setWidth(150);
creator.setHeight(100);
creator.setLineNum(60); // 60 條干擾線
creator.setFontSize(20);
creator.drawImage(sb.toString());
// Web 環境直接輸出到響應串流
// OutputStreamImageCreator creator = new OutputStreamImageCreator(response.getOutputStream());
// creator.drawImage("隨機驗證碼");
Substance 或 Java2D 進階渲染提升視覺品質Google Guava Cache 快取常用字型測量結果<img src="data:image/jpeg;base64,..."> 直接嵌入