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

Java 圖片裁剪完整實現:ImageIO 流式處理與矩形區域精準截取

     編輯:Java 相關知識

前言

圖片裁剪是圖像處理常見需求。本文基於 Java 原生 ImageIO API 實現無損圖片裁剪,支援 JPG/PNG 格式,採用流式處理避免大圖載入記憶體溢出,通過 ImageReadParam 設置源區域實現高效解碼裁剪。

核心類設計:ImageCut

封裝裁剪參數 (x, y, width, height)、源/目標路徑、格式常量。提供構造器與 Getter/Setter,主方法演示裁剪 (134,0) 起點、366x366 區域。

public class ImageCut {
    private String srcpath = "e:/poool.jpg";
    private String subpath = "e:/pool_end";
    private static final String IMAGE_FORM_OF_JPG = "jpg";
    private static final String IMAGE_FORM_OF_PNG = "png";
    private int x, y, width, height;

    public ImageCut() {}
    public ImageCut(int x, int y, int width, int height) {
        this.x = x; this.y = y; this.width = width; this.height = height;
    }

    public static void main(String[] args) throws Exception {
        ImageCut imageCut = new ImageCut(134, 0, 366, 366);
        imageCut.cut(imageCut.getSrcpath(), imageCut.getSubpath());
    }
    // ...
}

格式適配與 ImageReader 獲取

根據文件後綴動態選擇 ImageReader,支援擴展更多格式 (BMP, TIFF, GIF 等)。

public Iterator<ImageReader> getImageReadersByFormatName(String postFix) {
    switch (postFix.toLowerCase()) {
        case IMAGE_FORM_OF_JPG:
            return ImageIO.getImageReadersByFormatName("jpeg");  // 標準格式名
        case IMAGE_FORM_OF_PNG:
            return ImageIO.getImageReadersByFormatName("png");
        default:
            return ImageIO.getImageReadersByFormatName("jpeg");
    }
}

核心裁剪邏輯:cut 方法

關鍵步驟:創建輸入流 → 獲取後綴 → 獲取 Reader → 創建 ImageInputStream → 設置輸入源 (僅向前搜索) → 獲取默認 ReadParam → 設置源區域 Rectangle → 讀取裁剪區域 → 寫入目標文件 (帶時間戳避免衝突)。

public void cut(String srcpath, String subpath) throws IOException {
    FileInputStream is = null;
    ImageInputStream iis = null;
    try {
        is = new FileInputStream(srcpath);
        String postFix = getPostfix(srcpath);
        System.out.println("圖片格式為:" + postFix);
        
        Iterator<ImageReader> it = getImageReadersByFormatName(postFix);
        ImageReader reader = it.next();
        
        iis = ImageIO.createImageInputStream(is);
        reader.setInput(iis, true);  // 僅向前搜索,優化記憶體
        
        ImageReadParam param = reader.getDefaultReadParam();
        Rectangle rect = new Rectangle(x, y, width, height);
        param.setSourceRegion(rect);  // 核心:設置裁剪區域
        
        BufferedImage bi = reader.read(0, param);  // 讀取第0幀並應用參數
        
        // 保存:目標路徑_時間戳.後綴
        String outputPath = subpath + "_" + new Date().getTime() + "." + postFix;
        ImageIO.write(bi, postFix, new File(outputPath));
        
    } finally {
        if (is != null) is.close();
        if (iis != null) iis.close();
    }
}

輔助方法:獲取文件後綴

public String getPostfix(String inputFilePath) {
    return inputFilePath.substring(inputFilePath.lastIndexOf(".") + 1);
}

關鍵技術點深度解析

組件/類作用關鍵配置
ImageIO統一圖像 I/O 入口createImageInputStream、getImageReadersByFormatName、write
ImageReader特定格式解碼器setInput(輸入流, 僅向前)、read(索引, ReadParam)
ImageReadParam解碼參數控制setSourceRegion(Rectangle) 設置裁剪區域
Rectangle矩形區域定義(x, y, width, height) 坐標原點左上角
ImageInputStream隨機訪問輸入流支援標記/重置、僅向前模式節省緩衝

支援格式擴展指南

在 getImageReadersByFormatName 中添加 case 分支即可,常見格式名對應:

  • JPEG: "jpeg" (非 "jpg")
  • PNG: "png"
  • BMP: "bmp"
  • GIF: "gif"
  • TIFF: "tiff"
  • WBMP: "wbmp"

生產環境優化建議

  1. 參數校驗:裁剪區域不超出原圖邊界,width/height > 0
  2. 異常細化:區分 IIOException、FileNotFoundException、UnsupportedOperationException
  3. 記憶體優化:大圖裁剪時設置 JVM -Xmx、考慮分塊處理
  4. 質量控制:JPG 輸出時可通過 ImageWriteParam 設置壓縮質量 (0.0-1.0)
  5. 元數據保留:如需保留 EXIF 信息,需額外處理 IIOMetadata
  6. 並發處理:批量裁剪採用線程池,注意 ImageReader 非線程安全
  7. 臨時文件清理:失敗時確保刪除不完整輸出文件

常見問題與解決

問題原因解決
裁剪結果空白/全黑坐標超出圖片範圍裁剪前讀取圖片寬高驗證 Rectangle 邊界
輸出圖片失真JPG 重複壓縮質量損失設置 ImageWriteParam 壓縮質量 0.9+ 或輸出 PNG
PNG 透明背景變黑未正確處理 Alpha 通道確保 BufferedImage 類型為 TYPE_INT_ARGB
大圖 OOM完整解碼載入堆內存使用 setInput(..., true) 僅向前模式 + 增加堆內存
格式不支援無對應 ImageReader 插件引入 TwelveMonkeys ImageIO 插件庫擴展格式支援
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved