網頁設計常用圖片作為欄位標題(如「熱點聚焦」),但文字內容頻繁變更,美工需反覆修圖、替換,維護成本高。文字疊背景圖又難以達到精細視覺效果。
利用 <img src="/ImageServlet?text=標題&imageFile=bg.jpg&...">,Servlet 讀取背景圖,繪製文字後輸出 JPEG 流,瀏覽器直接顯示合成圖片。參數化文字、字體、顏色、座標,實現極致靈活。
package net.xdevelop.merge;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;
public class TextIntoImage extends HttpServlet {
private static final String CONTENT_TYPE = "image/jpeg";
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { doPost(req, resp); }
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType(CONTENT_TYPE);
// 參數解析
String text = getParam(req, "text", "");
String imageFile = getParam(req, "imageFile", "");
int x = getIntParam(req, "x", 0);
int y = getIntParam(req, "y", 0);
String fontColor = getParam(req, "fontColor", "000000");
int fontSize = getIntParam(req, "fontSize", 16);
String fontStyle = getParam(req, "fontStyle", "plain");
String fontName = getParam(req, "fontName", "SansSerif");
ServletOutputStream out = resp.getOutputStream();
if (imageFile.toLowerCase().endsWith(".jpg") || imageFile.toLowerCase().endsWith(".jpeg")) {
String realPath = getServletContext().getRealPath(imageFile);
try (FileInputStream fis = new FileInputStream(realPath)) {
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fis);
BufferedImage img = decoder.decodeAsBufferedImage();
Graphics g = img.getGraphics();
// 顏色
g.setColor(new Color(Integer.parseInt(fontColor, 16)));
// 字體
int style = Font.PLAIN;
if ("italic".equalsIgnoreCase(fontStyle)) style = Font.ITALIC;
else if ("bold".equalsIgnoreCase(fontStyle)) style = Font.BOLD;
g.setFont(new Font(fontName, style, fontSize));
// 繪製文字
g.drawString(text, x, y);
// 輸出
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
encoder.encode(img);
}
}
out.close();
}
private String getParam(HttpServletRequest req, String name, String def) {
String v = req.getParameter(name);
return (v != null && !v.isEmpty()) ? v : def;
}
private int getIntParam(HttpServletRequest req, String name, int def) {
String v = req.getParameter(name);
try { return (v != null && !v.isEmpty()) ? Integer.parseInt(v) : def; }
catch (NumberFormatException e) { return def; }
}
}
<servlet>
<servlet-name>textintoimage</servlet-name>
<servlet-class>net.xdevelop.merge.TextIntoImage</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>textintoimage</servlet-name>
<url-pattern>/TextIntoImage</url-pattern>
</servlet-mapping>
<img src="/TextIntoImage?text=熱點聚焦&imageFile=/bg.jpg&x=20&y=20
&fontColor=FFFFFF&fontStyle=bold&fontName=宋體&fontSize=16" />
Graphics2D + AffineTransform)。ImageIO)。| 優點 | 缺點 |
|---|---|
| 零維護:文字即時生效,無需美工介入 | 每次請求動態生成,高併發需快取 |
| 參數化靈活:字體/顏色/位置隨意調整 | 僅支援 JPEG(範例),需擴展支援其他格式 |
| 相容性佳:標準 <img> 標籤,無需 JS/CSS 支援 | 文字不可選、不可縮放(屬於圖片),無障礙性較弱 |