首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實作圖片繪製文字與多圖合成完整指南

     編輯:Java 相關知識

前言

在 Java 開發中,動態生成帶有文字浮水印或合成多張圖片的需求非常常見。本文將透過完整的程式碼範例,示範如何使用 java.awt 套件中的 Graphics2D 和 BufferedImage 類別,實現「在圖片上寫字」以及「兩張圖片合成」的功能。

核心類別設計:PicProcessor

我們封裝一個 PicProcessor 類別,統一處理圖片載入、文字繪製、圖片合成與輸出儲存等操作,提高程式碼的復用性與可維護性。

1. 圖片載入支援本地與網路路徑

/**
 * 從本地檔案系統載入圖片至緩衝區
 */
public BufferedImage loadImageLocal(String imgPath) {
    try {
        return ImageIO.read(new File(imgPath));
    } catch (IOException e) {
        System.err.println("本地圖片載入失敗: " + e.getMessage());
    }
    return null;
}

/**
 * 從網路 URL 載入圖片至緩衝區
 */
public BufferedImage loadImageUrl(String imgUrl) {
    try {
        URL url = new URL(imgUrl);
        return ImageIO.read(url);
    } catch (IOException e) {
        System.err.println("網路圖片載入失敗: " + e.getMessage());
    }
    return null;
}

2. 靈活的字體與顏色設定

private Font font = new Font("微軟正黑體", Font.PLAIN, 36);
private Color fontColor = Color.ORANGE;
private int fontSize = 36;

/**
 * 設定繪製文字的字體樣式、大小與顏色
 */
public void setFontStyle(String fontName, int fontSize, Color color) {
    this.fontSize = fontSize;
    this.font = new Font(fontName, Font.PLAIN, fontSize);
    this.fontColor = color;
}

3. 單行文字繪製(座標自動修正)

/**
 * 在圖片上繪製單行文字,若座標超出範圍則自動調整至右下角
 */
public BufferedImage drawText(BufferedImage img, String text, int x, int y) {
    if (img == null || text == null) return img;

    Graphics2D g = img.createGraphics();
    try {
        // 開啟抗鋸齒,提升文字渲染品質
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.setFont(font);
        g.setColor(fontColor);

        int imgW = img.getWidth();
        int imgH = img.getHeight();

        // 座標邊界檢查與修正
        if (x >= imgW || y >= imgH) {
            x = imgW - fontSize * text.length() - 10;
            y = imgH - fontSize - 5;
        }
        // 確保座標不為負
        x = Math.max(0, x);
        y = Math.max(fontSize, y);

        g.drawString(text, x, y);
    } finally {
        g.dispose(); // 釋放圖形資源
    }
    return img;
}

4. 多行文字繪製支援橫向/縱向排版

/**
 * 繪製多段文字
 * @param horizontal true: 橫向排列(同一行);false: 縱向換行
 */
public BufferedImage drawTextLines(BufferedImage img, String[] texts, int x, int y, boolean horizontal) {
    if (img == null || texts == null) return img;

    Graphics2D g = img.createGraphics();
    try {
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.setFont(font);
        g.setColor(Color.RED); // 多行文字預設紅色

        int imgW = img.getWidth();
        int imgH = img.getHeight();

        if (x >= imgW || y >= imgH) {
            x = 10;
            y = fontSize + 10;
        }

        for (String line : texts) {
            if (line == null) continue;
            g.drawString(line, x, y);
            if (horizontal) {
                // 橫向:x 軸位移(估算字寬)
                x += (int)(line.length() * fontSize * 0.6) + 5;
            } else {
                // 縱向:y 軸位移
                y += fontSize + 5;
            }
        }
    } finally {
        g.dispose();
    }
    return img;
}

5. 圖片合成(疊加/並排)

/**
 * 將前景圖合成到背景圖指定位置(支援透明度)
 */
public BufferedImage overlayImage(BufferedImage background, BufferedImage foreground, int x, int y, float alpha) {
    if (background == null || foreground == null) return background;

    Graphics2D g = background.createGraphics();
    try {
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        g.drawImage(foreground, x, y, null);
    } finally {
        g.dispose();
    }
    return background;
}

/**
 * 將兩張圖片水平並排合成新圖片
 */
public BufferedImage mergeHorizontal(BufferedImage left, BufferedImage right, int gap) {
    if (left == null) return right;
    if (right == null) return left;

    int newW = left.getWidth() + right.getWidth() + gap;
    int newH = Math.max(left.getHeight(), right.getHeight());
    BufferedImage combined = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

    Graphics2D g = combined.createGraphics();
    try {
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, newW, newH);
        g.drawImage(left, 0, 0, null);
        g.drawImage(right, left.getWidth() + gap, 0, null);
    } finally {
        g.dispose();
    }
    return combined;
}

6. 圖片儲存

/**
 * 將 BufferedImage 寫入本地檔案(支援 jpg/png)
 */
public boolean saveImage(BufferedImage img, String outputPath, String format) {
    if (img == null || outputPath == null) return false;
    try {
        File outFile = new File(outputPath);
        // 確保父目錄存在
        outFile.getParentFile().mkdirs();
        return ImageIO.write(img, format, outFile);
    } catch (IOException e) {
        System.err.println("圖片儲存失敗: " + e.getMessage());
        return false;
    }
}

完整使用範例

public static void main(String[] args) {
    PicProcessor processor = new PicProcessor();
    
    // 1. 載入背景圖
    BufferedImage bg = processor.loadImageLocal("input/background.jpg");
    
    // 2. 設定字體
    processor.setFontStyle("標楷體", 48, Color.WHITE);
    
    // 3. 繪製標題文字
    bg = processor.drawText(bg, "Java 圖片處理範例", 50, 100);
    
    // 4. 繪製多行說明文字
    String[] lines = {"功能一:文字浮水印", "功能二:多圖合成", "功能三:自訂字體顏色"};
    bg = processor.drawTextLines(bg, lines, 50, 160, false);
    
    // 5. 載入 Logo 並疊加到右下角
    BufferedImage logo = processor.loadImageLocal("input/logo.png");
    if (logo != null) {
        int logoX = bg.getWidth() - logo.getWidth() - 20;
        int logoY = bg.getHeight() - logo.getHeight() - 20;
        bg = processor.overlayImage(bg, logo, logoX, logoY, 0.9f);
    }
    
    // 6. 儲存結果
    processor.saveImage(bg, "output/result.jpg", "jpg");
    System.out.println("圖片生成完成!");
}

關鍵技術點總結

  • Graphics2D:核心繪圖類別,提供向量繪圖、文字渲染、圖片合成等高階功能。
  • RenderingHints:啟用抗鋸齒 (KEY_TEXT_ANTIALIASING) 可大幅提升文字顯示品質。
  • AlphaComposite:控制圖片合成時的透明度與混合模式。
  • BufferedImage.TYPE_INT_ARGB:支援透明通道的圖片類型,合成 PNG 圖片時必須使用。
  • 資源管理:Graphics2D 使用後務必呼叫 dispose() 釋放原生資源,避免記憶體洩漏。

常見問題與解決方案

問題原因解決方法
中文顯示為方塊/亂碼系統缺少指定字體使用系統確定存在的字體(如「微軟正黑體」、「標楷體」),或嵌入 TTF 字體檔
文字位置不正確座標系誤解(y 軸向下)y 座標為基線位置,實際顯示需加上字體大小;使用 FontMetrics 精確計算
合成後圖片有黑色背景目標圖片類型不支援透明建立新圖片時使用 BufferedImage.TYPE_INT_ARGB
OutOfMemoryError圖片尺寸過大或未釋放資源分塊處理大圖、及時 dispose()、調大 JVM 堆記憶體

延伸應用建議

此基礎框架可輕鬆擴展為:

  1. 批次浮水印工具:遍歷資料夾自動為所有圖片加浮水印
  2. 海報生成器:結合模板圖片、動態文字、QR Code 生成行銷海報
  3. 證件照合成:將人像抠圖後合成到標準底色背景
  4. 圖片拼接:支援網格、自由排版多圖拼接

完整原始碼已上傳至 GitHub 專案,歡迎參考與貢獻。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved