在相簿瀏覽、頭像上傳等場景中,縮略圖生成與區域裁剪是高頻需求。本文提供兩個生產級工具類:ImageUtil(等比/強制縮略圖)與 ImageUtil2(座標裁剪),並詳細說明前端座標獲取與尺寸適配技巧。
ImageUtil.thumbnailImage()thumb_public void thumbnailImage(String imagePath, int w, int h,
String prefix, boolean force) {
File imgFile = new File(imagePath);
if (!imgFile.exists()) { log.warn("圖片不存在"); return; }
// 校驗副檔名
String suffix = getSuffix(imgFile);
if (!isValidSuffix(suffix)) { log.error("非支援格式"); return; }
Image srcImg = ImageIO.read(imgFile);
int srcW = srcImg.getWidth(null), srcH = srcImg.getHeight(null);
// 等比模式:計算最佳尺寸
if (!force) {
double ratioW = (double) srcW / w;
double ratioH = (double) srcH / h;
if (ratioW < ratioH) { // 以寬為基準
if (srcW > w) h = (int) Math.round(srcH * w / (double) srcW);
} else { // 以高為基準
if (srcH > h) w = (int) Math.round(srcW * h / (double) srcH);
}
}
// 繪製縮略圖
BufferedImage thumb = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics g = thumb.getGraphics();
g.drawImage(srcImg, 0, 0, w, h, Color.LIGHT_GRAY, null);
g.dispose();
// 輸出
String outPath = imgFile.getParent() + File.separator + prefix + imgFile.getName();
ImageIO.write(thumb, suffix, new File(outPath));
log.debug("縮略圖生成成功:{}", outPath);
}
// 等比縮略圖,長邊不超過 150px
new ImageUtil().thumbnailImage("C:/photos/avatar.jpg", 100, 150, "thumb_", false);
ImageUtil2.cutImage()使用者在前端(如 Jcrop、自製 JS 拖拉框)選取裁剪區域,獲得 x, y, width, height 四個參數,後端據此從原圖切出對應區域。
ImageReader 區域讀取,記憶體效率高)public void cutImage(File srcImg, OutputStream output, Rectangle rect) {
// 校驗檔案與格式(同上)
FileInputStream fis = new FileInputStream(srcImg);
ImageInputStream iis = ImageIO.createImageInputStream(fis);
ImageReader reader = ImageIO.getImageReadersBySuffix(suffix).next();
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(rect); // 關鍵:設定讀取區域
BufferedImage bi = reader.read(0, param);
ImageIO.write(bi, suffix, output);
// 關閉資源...
}
// 直接指定輸出資料夾,自動加前綴 cut_
cutImage(srcImgFile, destFolder, new Rectangle(x, y, w, h));
// 字串路徑版
cutImage("src.jpg", "destFolder", 40, 28, 224, 228);
左側拖拉選區,右側即時預覽。透過 F12 觀察 DOM 變化,確認 x, y, width, height 對應屬性:

圖:左側可拖拉選區,右側即時預覽

Jcrop 直接暴露 x, y, w, h 參數,整合極簡單。但缺點是前端顯示區域固定,大圖會被壓縮顯示,導致座標與原圖不符。
問題:前端將圖片 CSS 限制為 300×300 顯示,使用者在 300×300 畫布上選取座標。若原圖為 1200×1200,直接用這些座標裁剪原圖,結果會偏移且縮小 4 倍。
解決方案(推薦流程):
ImageUtil.thumbnailImage)此法確保「前端所見即後端所切」,完全避開座標映射換算麻煩。
原文附件:CSDN 下載連結
原文出處:Java 圖片裁剪和生成縮略圖