使用 BufferedImage.TYPE_INT_RGB 建立目標圖片時,無 Alpha 通道,透明像素預設填充為黑色 (0x000000)。解決關鍵:建立支援透明度的圖片類型(TYPE_INT_ARGB),並正確設定 Graphics2D 合成規則。
public static void resizePNG(String srcPath, String dstPath,
int targetW, int targetH, boolean keepRatio) throws IOException {
File srcFile = new File(srcPath);
BufferedImage srcImg = ImageIO.read(srcFile);
// 1. 計算目標尺寸
int w = srcImg.getWidth(), h = srcImg.getHeight();
if (keepRatio) {
double scale = Math.min((double) targetW / w, (double) targetH / h);
w = (int) (w * scale);
h = (int) (h * scale);
} else {
w = targetW; h = targetH;
}
// 2. 建立支援透明度的目標圖片
BufferedImage dstImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// 3. 取得 Graphics2D 並設定高品質渲染
Graphics2D g2d = dstImg.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setComposite(AlphaComposite.Src); // 關鍵:直接複製像素含 Alpha,不混合
// 4. 繪圖
g2d.drawImage(srcImg, 0, 0, w, h, null);
g2d.dispose();
// 5. 輸出 PNG
ImageIO.write(dstImg, "PNG", new File(dstPath));
}
| 錯誤寫法 | 正確寫法 | 說明 |
|---|---|---|
| new BufferedImage(w, h, TYPE_INT_RGB) | new BufferedImage(w, h, TYPE_INT_ARGB) | ARGB 含 8-bit Alpha 通道 |
| 無 composite 設定 | g2d.setComposite(AlphaComposite.Src) | Src 模式直接覆蓋,保留透明像素 |
| getScaledInstance + drawImage | drawImage(src, 0, 0, w, h, null) | 單步繪圖避免中間轉型丟失 Alpha |
// 計算縮放後尺寸
double scale = Math.min((double) targetW / srcW, (double) targetH / srcH);
int nw = (int) (srcW * scale), nh = (int) (srcH * scale);
int dx = (targetW - nw) / 2, dy = (targetH - nh) / 2;
// 建立目標畫布(可指定背景色或透明)
BufferedImage canvas = new BufferedImage(targetW, targetH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = canvas.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setColor(new Color(0,0,0,0)); // 透明背景
g.fillRect(0, 0, targetW, targetH);
g.drawImage(srcImg, dx, dy, nw, nh, null);
g.dispose();
"PNG"、"png" 皆可,但建議大寫。ImageReader 串流解碼。核心只需三行變更:TYPE_INT_ARGB + AlphaComposite.Src + 直接 drawImage,徹底告別縮圖黑底,輸出完美透明 PNG。