Android大图、高清图片处理
Android中,系统分配给手机app的内存是有限的,现阶段根据不同的手机分配的最大内存也不一样,少的只有几十M。当我们以Bitmap的形式把高清的大图加载到内存当中时,它占用的内存会成倍数的增加。占用的内存超过了系统能够提供给app的内存时,会产生OOM。
1、图片占用内存的估计计算(并非实际值):
占用的内存 = 图片长度 * 图片宽度 * 单位像素占用的字节数
图片格式:
ALPHA_8 : 1byte 只存储alpha
ARGB_4444: 2byte 图片有可能会被破坏,效果差
ARGB_8888: 4byte 主流的存储方式
RGB_565: 2byte 不考虑alpha时推荐使用
2、png和jpg图片的选择
png:能用png最好是用png,32位的png颜色过渡平滑且支持透明。
jpg:是像素化压缩过的图片,质量已经下降了,一般不拿来做.9path的平铺拉伸的控件。
对于颜色繁杂的,比如照片墙纸,启动页面之类的图片,可用jpg。如果保存成png体积将是jpg的几倍甚至几十倍,严重浪费体积。其他的资源文件使用png。
3、像素压缩法
可以按照当前view的大小进行压缩,压缩成缩略图显示在view中,减少内存的消耗,防止OOM,同时保证图片不失真。
设置opts.inJustDecodeBounds= true时,图片的读取不会写入内存,可以获取图片的大小,从而设置需要压缩的Optios参数;opts.inJustDecodeBounds= false时图片的读取会写入内存中。
/**
* 对资源中的大图片进行分辨率大小的压缩
* @param context
* @param resourceId 资源的id
* @param view 显示图片的控件Imageview
*/
public static void setImageResource(Context context, int resourceId, ImageView view)
{
BitmapFactory.Options opts = new BitmapFactory.Options();
// 不读取像素数组到内存中,仅读取图片的信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(context.getResources(), resourceId,opts);
// 从Options中获取图片的分辨率
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
int scaleX;
int scaleY;
// 计算采样率
if(view.getWidth() > 0 && view.getHeight() > 0)
{
//采用view的尺寸对应得大小进行压缩
scaleX = imageWidth / view.getWidth();
scaleY = imageHeight / view.getHeight();
}
else
{
//view未初始化完成,获得的宽高为0,采用屏幕的分辨率尺寸来进行压缩
WindowManager wm = (WindowManager) context.getSystemService(context.WINDOW_SERVICE);
scaleX = imageWidth / wm.getDefaultDisplay().getWidth();
scaleY = imageHeight / wm.getDefaultDisplay().getHeight();
}
int scale = 1;
// 采样率依照最大的方向为准
if (scaleX > scaleY && scaleY >= 1) {
scale = scaleX;
}
if (scaleX < scaleY && scaleX >= 1) {
scale = scaleY;
}
Log.e("measure","scale = "+scale);
// false表示读取图片像素数组到内存中,依照设定的采样率
opts.inJustDecodeBounds = false;
// 采样率
opts.inSampleSize = scale;
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.larg,opts);
view.setImageBitmap(bitmap);
}
opts.inSampleSize= scale;为设置采样率,scale的最终等级为2的n次方,如1,2,4,8....;如果是scale为2,3,最终系统都会取2作为采样率;如果是4,5,6,7系统会自动取4作为采样率....
如上图所示,opts.inSampleSize设置为2则占用内存约为未压缩前的1/4,设置为4则为未压缩前的1/16 ..... 对应的压缩率最好是通过view在手机上的显示大小进行计算,这样可以更好的适配到手机上,不影响显示效果。
2、质量压缩法
用于压缩后保存在disk下,会破坏图片的质量,不会改变图片的大小尺寸。但占用的内存不会减少,通常用于压缩上传服务器的图片。
/**
* 质量压缩方法
*
* @param image
* @return
*/
private static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
int options = 100;
while (baos.toByteArray().length / 1024 > 100 && options > 50) {
baos.reset();
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
options -= 10;
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
return bitmap;
}
图片上传服务器:
1、图片进行像素压缩
2、图片进行质量压缩
3、本地保存
4、上传服务器
5、上传成功后删除本地图片