Java 標準庫 javax.imageio 與 java.awt.image 提供零依賴的圖片讀寫與縮放能力,適合輕量級項目;大規模處理建議引入 Thumbnailator 或 TwelveMonkeys ImageIO。
/** 縮小到原尺寸的 1/times(times>1) */
public BufferedImage resizeImage(BufferedImage src, float times) {
int w = src.getWidth(), h = src.getHeight();
int tw = Math.max(1, (int)(w / times));
int th = Math.max(1, (int)(h / times));
return scale(src, tw, th);
}
/** 按倍數縮放(0.5 = 縮小一半,2 = 放大兩倍) */
public BufferedImage zoomImage(BufferedImage src, float factor) {
int w = src.getWidth(), h = src.getHeight();
int tw = Math.max(1, (int)(w * factor));
int th = Math.max(1, (int)(h * factor));
return scale(src, tw, th);
}
/** 通用高質量縮放 */
private BufferedImage scale(BufferedImage src, int tw, int th) {
BufferedImage dst = new BufferedImage(tw, th, BufferedImage.TYPE_INT_RGB);
Graphics2D g = dst.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.drawImage(src.getScaledInstance(tw, th, Image.SCALE_SMOOTH), 0, 0, null);
g.dispose();
return dst;
}
public boolean writeHighQuality(BufferedImage img, String outPath) {
try (FileOutputStream fos = new FileOutputStream(outPath)) {
// 需 JDK 內置 com.sun.image.codec.jpeg 或引入 TwelveMonkeys
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
JPEGEncodeParam param = JPEGCodec.getDefaultJPEGEncodeParam(img);
param.setQuality(0.95f, true); // 0.0~1.0,越大質量越高
encoder.encode(img, param);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
注意:com.sun.image.codec.jpeg為 Sun 專有 API,JDK 9+ 已移除。生產環境請改用ImageIO.write(img, "jpg", out)搭配ImageWriteParam設置質量,或引入twelvemonkeys-imageio-jpeg。
public class BatchThumbnailer {
private static final String[] IMG_EXTS = {"jpg", "jpeg", "png", "bmp", "gif"};
public static void main(String[] args) throws IOException {
File inDir = new File("F:/pic");
File outDir = new File("F:/picNew");
if (!outDir.exists()) outDir.mkdirs();
float factor = 0.25f; // 縮小到 25%
BatchThumbnailer t = new BatchThumbnailer();
for (File f : inDir.listFiles((dir, name) -> {
String ext = name.substring(name.lastIndexOf('.')+1).toLowerCase();
return Arrays.asList(IMG_EXTS).contains(ext);
})) {
if (f.length() == 0) continue;
BufferedImage img = ImageIO.read(f);
BufferedImage thumb = t.zoomImage(img, factor);
String outName = f.getName().replaceFirst("\\.[^.]+$", "_thumb.jpg");
t.writeHighQuality(thumb, new File(outDir, outName).getAbsolutePath());
}
System.out.println("批量完成!");
}
// zoomImage / writeHighQuality 同前
}
| 場景 | 建議 |
|---|---|
| 透明背景 PNG | 用 BufferedImage.TYPE_INT_ARGB 保留 Alpha 通道 |
| 超大圖(>50MP) | 分塊讀取或用 ImageReader.setInput(..., true) 流式解碼,避免 OOM |
| 並發處理 | 線程池 + CompletableFuture,CPU 核心數為宜 |
| Web 服務 | 引入 Thumbnailator:Thumbnails.of(in).scale(0.25).toFile(out) 一行搞定 |
getScaledInstance 預設為 SCALE_FAST,質量差;必須顯式指定 SCALE_SMOOTH 或用 Graphics2D 雙線性插值。File 拼接,避免「路徑不存在」。