Android 虚拟机默认为每个应用分配的堆内存空间是16M,当加载大图片时,加载图片需要的内存空间不是按图片的大小来算的,而是按像素点的多少来算的。图片加载到内存中需要把每一个像素都加载到内存中. 所以对内存的要求非常高, 一不小心就会造成OOM(OutOfMemoryError) 内存溢出致命错误。
假设:
当前有一张图片,大小仅为1M,但是其规格为3648*2736,现在需要加载此图片总像素数=3648*2736=9980928
三种像素单位如下:
ARGB_4444 : 2bytes
ARGB_8888 : 4bytes
RGB_565 : 4bytes
假设现在像素采用ARGB_4444 标准,则其占用的总空间为:图片占用空间=总像素数*像素的单位 = 9980928 * 2bytes = 19961856bytes = 19M>16M OOM 内存溢出
解决方案:Java 代码可以对图片进行比例缩放
假设:图片的宽和高: 3648 * 2736,屏幕的宽和高: 320 * 480
计算缩放比:宽度缩放比例: 3648 / 320 = 11,高度缩放比例: 2736 / 480 = 5
比较宽和高的缩放比例, 哪一个大用哪一个进行缩放
缩放后的图片:3648 / 11 = 331,2736 / 11 = 248
缩放后图片的宽和高: 331* 248,331* 248=882088 * 2bytes=160K
1.1 实现图片的缩放加载:这里只给出核心代码,用于演示加载大图片的原理。
普通方法加载图片代码清单:
假设:
当前有一张图片,大小仅为1M,但是其规格为3648*2736,现在需要加载此图片总像素数=3648*2736=9980928
三种像素单位如下:
ARGB_4444 : 2bytes
ARGB_8888 : 4bytes
RGB_565 : 4bytes
假设现在像素采用ARGB_4444 标准,则其占用的总空间为:图片占用空间=总像素数*像素的单位 = 9980928 * 2bytes = 19961856bytes = 19M>16M OOM 内存溢出
解决方案:Java 代码可以对图片进行比例缩放
假设:图片的宽和高: 3648 * 2736,屏幕的宽和高: 320 * 480
计算缩放比:宽度缩放比例: 3648 / 320 = 11,高度缩放比例: 2736 / 480 = 5
比较宽和高的缩放比例, 哪一个大用哪一个进行缩放
缩放后的图片:3648 / 11 = 331,2736 / 11 = 248
缩放后图片的宽和高: 331* 248,331* 248=882088 * 2bytes=160K
1.1 实现图片的缩放加载:这里只给出核心代码,用于演示加载大图片的原理。
普通方法加载图片代码清单:
public void load(View v) {
String path = etPath.getText().toString().trim();
// 根据路径得到图片对象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 把图片展示到ImageView 控件上.
ivIcon.setImageBitmap(bitmap);
}
public void scaleLoad(View v) {
String path = etPath.getText().toString().trim();
// 得到图片的宽和高
Options opts = new Options();
opts.inJustDecodeBounds = true; // 加载器不加载图片, 而是把图片的out(宽和高)的字段信息取出来
BitmapFactory.decodeFile(path, opts);
int imageWidth = opts.outWidth;
int imageHeight = opts.outHeight;
System.out.println("图片的宽和高: " + imageWidth + " * " + imageHeight);
// 得到屏幕的宽和高
Display display = getWindowManager().getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
System.out.println("屏幕的宽和高: " + screenWidth + " * " + screenHeight);
// 计算缩放比例
int widthScale = imageWidth / screenWidth;
int heightScale = imageHeight / screenHeight;
int scale = widthScale > heightScale ? widthScale : heightScale;
System.out.println("缩放比例为: " + scale);
// 使用缩放比例进行缩放加载图片
opts.inJustDecodeBounds = false; // 加载器就会返回图片了
opts.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, opts);
// 显示在屏幕上
ivIcon.setImageBitmap(bm);
}