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

Java ImageIO 實現圖片壓縮縮放:高質量、不變形、任意尺寸

     編輯:Java 相關知識

背景

早期方案依賴 com.sun.image.codec.jpeg.JPEGImageEncoder,屬於 Sun 內部 API,Java 7+ 已移除,編譯報錯。標準替代方案:javax.imageio.ImageIO + BufferedImage + Graphics2D,純標準庫、無依賴、跨平台。

核心工具類 ImageHelper

public class ImageHelper {
    private static ImageHelper instance;
    public static ImageHelper getInstance() {
        return instance == null ? instance = new ImageHelper() : instance;
    }

    /** 按比例縮放 */
    public static void scaleImage(String srcPath, String destPath, double scale, String format) {
        try {
            BufferedImage src = ImageIO.read(new File(srcPath));
            int w = (int) (src.getWidth() * scale);
            int h = (int) (src.getHeight() * scale);
            BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = dest.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(src.getScaledInstance(w, h, Image.SCALE_SMOOTH), 0, 0, null);
            g.dispose();
            ImageIO.write(dest, format, new File(destPath));
        } catch (IOException e) { e.printStackTrace(); }
    }

    /** 指定寬高縮放(可選保持比例) */
    public static void scaleImageWithParams(String srcPath, String destPath,
            int targetW, int targetH, boolean keepRatio, String format) {
        try {
            BufferedImage src = ImageIO.read(new File(srcPath));
            if (keepRatio) {
                int[] wh = calcAutoSize(src, targetW, targetH);
                targetW = wh[0]; targetH = wh[1];
            }
            BufferedImage dest = new BufferedImage(targetW, targetH, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = dest.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(src.getScaledInstance(targetW, targetH, Image.SCALE_SMOOTH), 0, 0, null);
            g.dispose();
            ImageIO.write(dest, format, new File(destPath));
        } catch (IOException e) { e.printStackTrace(); }
    }

    /** 計算保持比例下的目標尺寸 */
    private static int[] calcAutoSize(BufferedImage src, int maxW, int maxH) {
        double scaleW = (double) maxW / src.getWidth();
        double scaleH = (double) maxH / src.getHeight();
        double scale = Math.min(scaleW, scaleH);
        return new int[] { (int) (src.getWidth() * scale), (int) (src.getHeight() * scale) };
    }

    // 高精度除法輔助(保留 3 位小數)
    private static double div(int a, int b) {
        return new BigDecimal(a).divide(new BigDecimal(b), 4, RoundingMode.HALF_UP).doubleValue();
    }
}

關鍵技術點解析

  1. 渲染提示:RenderingHints.KEY_INTERPOLATION 設置 VALUE_INTERPOLATION_BILINEAR(雙線性插值)或 BICUBIC(雙三次),大幅提升縮放質量。
  2. SCALE_SMOOTH:Image.getScaledInstance(w, h, Image.SCALE_SMOOTH) 選用平滑縮放算法,比 SCALE_FAST/SCALE_DEFAULT 效果好。
  3. 保持比例:計算寬高縮放比取最小值,避免拉伸變形,留白區域默認填充背景色(可擴展為透明背景)。
  4. 格式靈活:ImageIO.write(image, "jpg/png/bmp/gif", out) 支持主流格式,JPEG 可通過 ImageWriteParam 設置壓縮質量(0.0-1.0)。
  5. 內存管理:Graphics2D.dispose() 及時釋放圖形上下文資源。

進階:JPEG 質量控制

ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.85f); // 0-1,推薦 0.8-0.9
writer.setOutput(new FileImageOutputStream(new File(destPath)));
writer.write(null, new IIOImage(dest, null, null), param);
writer.dispose();

總結

基於標準 ImageIO 的縮放方案完全替代內部 API,代碼簡潔、質量可控、支持任意目標尺寸與保持比例,生產環境穩定可靠。若需極致性能(如批量處理),可考慮 TwelveMonkeys ImageIO 插件或 JNI 綁定 libjpeg-turbo。

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