多媒体指的就是 文字、图片、音频、视频
一、图片篇
1.图片大小的计算
图片大小 = 分辨率 * 位深/8 (以字节为单位)
分辨率:就是图片的长*宽,单位是相素。
位深:就是每个相素所占的二进制位数。(右击图片的属性可以查看图片的位深)
对于BMP图片,有以下几种存储格式:
1)单色:每个像素最多能够表示2种颜色, 2 = 2的1次方,只要使用长度为1的二进制位来表示
位深为1,那么一个像素占1/8个byte,也就是Log22 / 8。
2)16色:每个像素最多能够表示16种颜色,16=2的4次方,只要使用长度为4的二进制位来表示
示,位深为4,那么一个像素占4/8个byte ,也就是Log216 / 8。
3)256色:每个像素最多能够表示256种颜色,256=2的8次方,只要使用长度为8的二进制位来
表示,位深为8,那么一个像素占8/8个byte ,也就是Log2256 / 8。
4) 24位:每个像素最多能够表示1600多万多种颜色,16777216 = 2的24次方,只要使用长度
为24的二进制位来表示,位深就为24,那么一个像素占 24 / 8个byte,也就是
Log216777216 / 8。
下面这个是我截的图:
对于其它常见格式的图片,如PNG、 JPG等,图片采用了压缩算法进行了压缩,所以图片像素的
大小不能轻易的算出来,此处暂不花费过多的时间去研究。
2.Android下图片大小的计算
在Android系统下,通常用BitmapFactory来加载图片。
Android中
Bitmap的默认加载使用ARGB_8888色彩模式,每个像素会占用4byte。
比如:一个512*512的图片,无论什么格式,加载进入内存都占用512*512*4=1MB,所
以,Android图片占用内存大小,只与图片的分辨率(像素)以及加载使用的色彩模式有关)
补充参考链接: http://www.cnblogs.com/fengzhblog/p/3227471.html
http://my.oschina.net/u/1389206/blog/324731
3.Android下加载大图片
1)oom异常
我利用Android提供的ImageView控件来直接加载一张2400*3200相素的图片
ImageView iv = (ImageView) findViewById(R.id.iv); Bitmap srcBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getPath() + "/bigpic.bmp"); iv.setImageBitmap(srcBitmap);
然后报了下面这个异常:
上面我用红色矩形标记的那一行,意思就是说30720012字节分配超过了heap size的最大值
16777216字节。那么这两个数字是怎么来的呢?
在创建AVD的时候,我给heap size分配的内存为16MB = 16777216字节,所以16777216
指的是AVD的heap size,这个参数是虚拟机给每个应用程序分配的最大内存空间。
在上面图片大小的计算中,已经说到了 Android中图片大小计算的方法,我的代码是采用
Bitmap来加载图片的,所以图片的大小为2400*3200*4 = 30720000(与30720012相比少了12
个字节???)
可见,Android在加载图片的时候,图片的分辨率如果过大的话,就会发生内存溢出异常
out of memory。那么下面就介绍Android中如何避免这个异常出现。
2)缩放加载大图片
图片分辨率(尺寸)过大,那么加载的时候就把图片尺寸变小,那么应该怎么变小呢?一般
情况就是根据手机的屏幕分辨率来加载图片的。步骤如下:
第1步:获取手机分辨率
第2步:获取图片分辨率
第3步:计算绽放比
第4步:按绽放比去加载图片
代码如下:
//[1]获取手机分辨率 通过WindowManager这个类去实现。 //得到WindowManager对象 WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); //得到display对象 Display display = windowManager.getDefaultDisplay(); int screen_width = display.getWidth(); int screen_height = display.getHeight(); //[2]获取图片的分辨率 File file = new File(Environment.getExternalStorageDirectory().getPath() + "/dog.bmp"); BitmapFactory.Options opts = new Options(); opts.inJustDecodeBounds = true; //表示不会为图片的像素分配内存空间 BitmapFactory.decodeFile(file.getPath(), opts); //当opts的上面这个属性设为true时,这个方法会返回null,但是会将 //图片的size信息存放到opts对象里。关于这个方法的使用,API说得很明白。 int pic_width = opts.outWidth; int pic_height = opts.outHeight; //[3]计算缩放比 int scale = 1; //最终用的缩放比 //我个人认为严密的计算缩放比应该是向上取舍 int scale_x = (int) Math.ceil(pic_width * 1.0 / screen_width); int scale_y = (int) Math.ceil(pic_height * 1.0 / screen_height); scale = scale_x > scale_y ? scale_x:scale_y ; //如果缩放比小于或等于1,就没有必要缩放了。 scale = scale > 1 ? scale:1; //[4]按绽放比去加载图片 opts.inSampleSize = scale; //指定加载图片时的缩放比,如果为4,图片的大小会变成原来的1/16。 //关于这个属性,API说得很明白。 opts.inJustDecodeBounds = false; Bitmap scaledBitmap = BitmapFactory.decodeFile(file.getPath(), opts); iv.setImageBitmap(scaledBitmap);