一:图片OOM异常:
代码示例:
public class MainActivity extends Activity { private ImageView iv_imageView; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv_imageView = (ImageView) findViewById(R.id.Iv_imageView); } public void load(View view){ Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/1.jpg"); iv_imageView.setImageBitmap(bitmap); } }
出现问题:
解析问题:
一:图片明明就:1.37MB(1,444,582字节),为什么vm为16MB还会报错-->OOM?
1.图片要想被加载到内存中显示,在内在中是以数组的方式保存的,用数组表示图片中的每一个像素,
2.这个图片虽然只有1.37MB,但其分辨率为:2592*1944=5038848,即在内存中要表示这么多个点!
3.每个点都是有颜色的,RGB,所以每表示一个颜色,至少需要3个Byte来表示!
4.图片支持都有透明度的,图片的每个点都有一个参数&(0-255),1个字节,所以要表示一个点,需要四个Byte!
5.5038848*4=20155392Byte ---> 20155392/1024=19683KB ---> 19638/1024=19.2216796875MB,即要将那个1.37MB的图片表示在计算机内存中,需要19.2216796875MB的内存,大于VM Heap:16MB,故OOM!
6.所以图片要显示在手机内存中要进行相应的处理,不能直接显示原图!一般所建的模拟器屏幕也就320*480,即只能表示这么多的像素。所以原图的每个点不能完全显示在手机的屏幕上!所以将图片依据手机屏幕做相应的缩放
二:对图片进行缩放的算法:
1.获取手机屏幕的分辨率:宽,高:320*480
2.获取图片的宽高信息:2592*1944
3.计算图片的缩放比例:
水平方向:2592/320=8.1
竖直方向:1944/480=4.05
4.确定显示的缩放比例:取大的一方(否则显示不全!)9.1
5.缩放完毕后,加载显示图片
详细代码:
public class MainActivity extends Activity { private ImageView iv_imageView; private int windowWidth; private int windowHeight; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv_imageView = (ImageView) findViewById(R.id.Iv_imageView); //1.获取手机屏幕的分辨率 宽高 Display display = getWindowManager().getDefaultDisplay(); windowWidth = display.getWidth(); windowHeight = display.getHeight(); System.out.println("屏幕的宽度:" + windowHeight); System.out.println("屏幕的高度:" + windowHeight); } public void load(View view){ // Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/1.jpg"); // iv_imageView.setImageBitmap(bitmap); Options opts = new Options(); //2.0设置解析器不去真正的解析这个位图,而是解析这个图片的out输出信息(宽度,高度),不会为图片的每个点申请内在空间 opts.inJustDecodeBounds = true; //2.得到图片的宽高信息 BitmapFactory.decodeFile("/sdcard/1.jpg",opts); int picHeight = opts.outHeight; int picWidth = opts.outWidth; System.out.println("图片的宽度:" + picWidth); System.out.println("图片的高度:" + picHeight); //3.得到缩放比例 int scaleX = picWidth/windowWidth; int scaleY = picHeight/windowHeight; System.out.println("水平缩放比例:" + scaleX); System.out.println("竖直缩放比例:" + scaleY); //3.2. 确定缩放比例: int scale = 1; if(scaleX > scaleY && scaleY>1){ scale = scaleX; } if(scaleY > scaleX && scaleX>1){ scale = scaleY; } System.out.println("最终确定的缩放比例:" + scale); //4.真正的解析这个图片 opts.inJustDecodeBounds = false; opts.inSampleSize = scale; Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/1.jpg",opts); iv_imageView.setImageBitmap(bitmap); } }
运行时log:
09-29 16:05:37.715: I/System.out(23786): 屏幕的宽度:480
09-29 16:05:37.715: I/System.out(23786): 屏幕的高度:480
09-29 16:07:12.085: I/System.out(23786): 图片的宽度:2592
09-29 16:07:12.085: I/System.out(23786): 图片的高度:1944
09-29 16:07:12.105: I/System.out(23786): 水平缩放比例:8
09-29 16:07:12.115: I/System.out(23786): 竖直缩放比例:4
09-29 16:07:12.115: I/System.out(23786): 最终确定的缩放比例:8
此时图片能正确显示:
09-29 16:17:26.475: I/System.out(23786): 屏幕的宽度:320
09-29 16:17:26.475: I/System.out(23786): 屏幕的高度:320
09-29 16:17:33.336: I/System.out(23786): 图片的宽度:1280
09-29 16:17:33.336: I/System.out(23786): 图片的高度:1024
09-29 16:17:33.345: I/System.out(23786): 水平缩放比例:2
09-29 16:17:33.345: I/System.out(23786): 竖直缩放比例:3
09-29 16:17:33.345: I/System.out(23786): 最终确定的缩放比例:3