BitmapFactory.Options.inSampleSize:解碼縮放因子。值為 N (N>0) 時,解碼器對原圖進行 1/N 采樣,輸出圖寬高約為原圖的 1/N,內存佔用約為 1/N²。
inSampleSize = 1:原尺寸(默認)。inSampleSize = 2:寬高各縮半,像素數 1/4。inSampleSize = 4:寬高各 1/4,像素數 1/16。// 1. 僅獲取尺寸,不分配像素內存
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, opts); // opts.outWidth/outHeight 已填充
// 2. 計算合適的 inSampleSize
opts.inSampleSize = calculateInSampleSize(opts, reqWidth, reqHeight);
// 3. 真正解碼
opts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, opts);
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// 原始尺寸
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// 縮放後的尺寸仍大於需求尺寸時,繼續放大 inSampleSize
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
| 細節 | 說明 |
|---|---|
| 只能是 2 的冪次 | 解碼器實現限制,非 2 的冪次會向下取整到最近的 2 的冪次。 |
| reqWidth/reqHeight 來源 | 通常取 ImageView 的 getMeasuredWidth/Height 或螢幕尺寸。 |
| OOM 仍發生? | 檢查是否重複持有 Bitmap 引用、是否調用 recycle()(API<19)、使用 inBitmap 復用內存(API 19+)。 |
| 圖片旋轉問題 | inSampleSize 不處理 EXIF 旋轉,需配合 ExifInterface 矩正。 |
生產項目建議直接使用成熟圖片庫,內部已封裝最佳策略:
Glide.with(ctx).load(path).override(w,h).into(iv);iv.load(path) { crossfade(true) }理解 inSampleSize 原理是優化內存的基礎,實戰中請站在巨人肩膀上。