核心 API:ImageIO + BufferedImage
public class ImageInfo {
public static void main(String[] args) throws IOException {
File file = new File("image.png");
BufferedImage image = ImageIO.read(file);
if (image == null) {
System.out.println("不支持的圖片格式或文件損壞");
return;
}
// 1. 獲取寬高 (像素)
int width = image.getWidth();
int height = image.getHeight();
System.out.printf("尺寸: %d x %d 像素%n", width, height);
System.out.printf("總像素: %,d%n", (long) width * height);
// 2. 獲取像素數據 (ARGB)
int[] pixels = new int[width * height];
image.getRGB(0, 0, width, height, pixels, 0, width);
// 遍歷像素
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int argb = pixels[y * width + x];
int alpha = (argb >> 24) & 0xFF;
int red = (argb >> 16) & 0xFF;
int green = (argb >> 8) & 0xFF;
int blue = argb & 0xFF;
// 處理像素...
}
}
// 3. 獲取圖片類型
int type = image.getType();
System.out.println("圖片類型: " + typeName(type));
// 4. 顏色模型
ColorModel cm = image.getColorModel();
System.out.println("顏色模型: " + cm);
System.out.println("是否有 Alpha: " + cm.hasAlpha());
}
static String typeName(int type) {
return switch (type) {
case BufferedImage.TYPE_INT_ARGB -> "TYPE_INT_ARGB";
case BufferedImage.TYPE_INT_RGB -> "TYPE_INT_RGB";
case BufferedImage.TYPE_3BYTE_BGR -> "TYPE_3BYTE_BGR";
case BufferedImage.TYPE_BYTE_GRAY -> "TYPE_BYTE_GRAY";
case BufferedImage.TYPE_USHORT_565_RGB -> "TYPE_USHORT_565_RGB";
default -> "UNKNOWN(" + type + ")";
};
}
}
高性能像素訪問:DataBuffer 直接訪問
// 避免 getRGB() 數組拷貝開銷,直接操作底層數據
WritableRaster raster = image.getRaster();
DataBuffer buffer = raster.getDataBuffer();
if (buffer instanceof DataBufferInt) {
// TYPE_INT_ARGB / TYPE_INT_RGB
int[] data = ((DataBufferInt) buffer).getData();
// 直接操作 data 數組
} else if (buffer instanceof DataBufferByte) {
// TYPE_3BYTE_BGR / TYPE_BYTE_GRAY
byte[] data = ((DataBufferByte) buffer).getData();
// 注意:BGR 順序,每像素 3 字節
} else if (buffer instanceof DataBufferUShort) {
// TYPE_USHORT_565_RGB
short[] data = ((DataBufferUShort) buffer).getData();
}
圖片元信息讀取:ImageReader (不加載像素數據)
public static Dimension getImageSizeFast(File file) throws IOException {
try (ImageInputStream in = ImageIO.createImageInputStream(file)) {
Iterator readers = ImageIO.getImageReaders(in);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(in);
int width = reader.getWidth(0);
int height = reader.getHeight(0);
return new Dimension(width, height);
} finally {
reader.dispose();
}
}
}
return null;
}
- 優勢:只讀取文件頭,不解碼像素數據,極快、內存占用極低
- 適用:批量掃描圖片尺寸、生成縮略圖索引
常見圖片格式支持
| 格式 | 讀取 | 寫入 | 備註 |
| PNG | ✓ | ✓ | 無損、支持 Alpha、JDK 內置 |
| JPEG/JPG | ✓ | ✓ | 有損、無 Alpha、JDK 內置 |
| BMP | ✓ | ✓ | 無壓縮、JDK 內置 |
| GIF | ✓ | ✓ | 動畫、256 色、JDK 內置 |
| WBMP | ✓ | ✓ | 無線位圖、JDK 內置 |
| TIFF | 需插件 | 需插件 | JAI / TwelveMonkeys ImageIO |
| WebP | 需插件 | 需插件 | TwelveMonkeys ImageIO |
| HEIC/HEIF | 需插件 | 需插件 | TwelveMonkeys ImageIO |
TwelveMonkeys ImageIO 擴展支持 (推薦生產使用)
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.9.4</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.9.4</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-webp</artifactId>
<version>3.9.4</version>
</dependency>
<!-- 統一入口,自動註冊所有格式 -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-core</artifactId>
<version>3.9.4</version>
</dependency>
生成縮略圖最佳實踐
public static void createThumbnail(File src, File dest, int maxWidth, int maxHeight)
throws IOException {
try (ImageInputStream in = ImageIO.createImageInputStream(src)) {
Iterator readers = ImageIO.getImageReaders(in);
if (!readers.hasNext()) throw new IOException("無讀取器");
ImageReader reader = readers.next();
try {
reader.setInput(in);
// 1. 獲取原始尺寸
int srcWidth = reader.getWidth(0);
int srcHeight = reader.getHeight(0);
// 2. 計算縮放比例
double scale = Math.min(
(double) maxWidth / srcWidth,
(double) maxHeight / srcHeight
);
if (scale >= 1.0) {
Files.copy(src.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
return;
}
// 3. 讀取縮放後圖片 (子采樣)
ImageReadParam param = reader.getDefaultReadParam();
int subsample = (int) Math.ceil(1.0 / scale);
param.setSourceSubsampling(subsample, subsample, 0, 0);
BufferedImage thumb = reader.read(0, param);
// 4. 精細縮放 (如需精確尺寸)
if (thumb.getWidth() > maxWidth || thumb.getHeight() > maxHeight) {
thumb = Scalr.resize(thumb, Scalr.Method.QUALITY, Scalr.Mode.FIT_TO_BOUNDS,
maxWidth, maxHeight); // 需 img-scalr-lib 依賴
}
// 5. 寫入
String format = getFormatName(dest);
ImageIO.write(thumb, format, dest);
} finally {
reader.dispose();
}
}
}
常見問題排查
| 問題 | 原因 | 解決 |
| ImageIO.read 返回 null | 格式不支持/文件損壞/無對應 ImageReader | 引入 TwelveMonkeys、檢查文件完整性 |
| JPEG 顏色失真 | CMYK 色彩空間、ICC 配置文件 | TwelveMonkeys 自動處理、或手動色彩轉換 |
| 大圖 OOM | 解碼後像素數據佔用大量堆內存 | 分塊讀取、子采樣、增加 -Xmx |
| 透明背景變黑 | TYPE_3BYTE_BGR 無 Alpha 通道 | 轉換為 TYPE_INT_ARGB 處理 |
掌握 ImageIO 核心 API、DataBuffer 零拷貝訪問、ImageReader 輕量級元信息讀取、格式擴展庫與縮略圖生成最佳實踐,構建高性能 Java 圖像處理能力。