转载自http://www.cnblogs.com/winter-is-coming/p/9112192.html
获取图片尺寸https://blog.csdn.net/shb2058/article/details/71107774
Android Bitmap详解
Google Developer:Bitmap
一、基本信息
Bitmap位图包括像素以及长、宽、颜色等描述信息。长宽和像素位数是用来描述图片的,可以通过这些信息计算出图片的像素占用内存的大小。
位图可以理解为一个画架,把图放到上面然后可以对图片做一些列的处理。
位图文件图像显示效果好,但是非压缩格式,需要占用较大的存储空间。
1. Config:表示图片像素类型,包括ALPHA_8、RGB_565、ARGB_4444、ARGB_8888 A:透明度;RGB分别是Red、Green、Blue,三种原色
ARGB_8888:四个通道都是8位,每个像素占用4个字节,图片质量是最高的,但是占用的内存也是最大的;
ARGB_4444:四个通道都是4位,每个像素占用2个字节,图片的失真比较严重;
RGB_565:没有A通道,每个像素占用2个字节,图片失真小,但是没有透明度;
ALPHA_8:只有A通道,每个像素占用1个字节大大小,只有透明度,没有颜色值。
使用场景总结:ARGB_4444失真严重,基本不用;ALPHA_8使用场景特殊,比如设置遮盖效果等;不需要设置透明度,RGB_565是个不错的选择;既要设置透明度,对图片质量要求又高,就用ARGB_8888。
2. CompressFormat:Bitmap.CompressFormat.JPEG、Bitmap.CompressFormat.PNG、Bitmap.CompressFormat.WEBP三种压缩格式
JPEG:一种有损压缩(JPEG2000既可以有损也可以无损),".jpg"或者".jpeg"; 优点:采用了直接色,有丰富的色彩,适合存储照片和生动图像效果;缺点:有损,不适合用来存储logo、线框类图。
PNG: 一种无损压缩,".png"; 优点:支持透明、无损,主要用于小图标,透明背景等;缺点:若色彩复杂,则图片生成后文件很大;
WEBP:以WebP算法进行压缩;Google开发的新的图片格式,同时支持无损和有损压缩,使用直接色。无损压缩,相同质量的webp比PNG小大约26%;有损压缩,相同质量的webp比JPEG小25%-34% 支持动图,基本取代gif
详细介绍参见【转】WebP原理和支持现状
二、加载
BitmapFactory提供了四类方法:decodeFile、decodeResource、decodeStream、decodeByteArray
1. 从文件中读取
try {
FileInputStream in =newFileInputStream("/sdcard/Download/sample.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(in);
Bitmap bm = BitmapFactory.decodeFile(sd_path); // 间接调用 BitmapFactory.decodeStream
2. 从资源中读取
Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sample); // 间接调用 BitmapFactory.decodeStream
3. 从字节序列里读取
// InputStream转换成byte[]Bitmap bm = BitmapFactory.decodeByteArray(myByte,0,myByte.length);
巨图加载:BitmapRegionDecoder,可以按照区域进行加载
高效加载:核心其实也很简单,主要是采样压缩、缓存策略、异步加载等
1. 采样压缩 (->【自】高斯模糊)
BitmapFactory.Options options =new BitmapFactory.Options(); //inJustDecodeBounds为true,不返回bitmap,只返回这个bitmap的尺寸 options.inJustDecodeBounds =true;
BitmapFactory.decodeResource(getResources(), images[position], options);
//利用返回的原图片的宽高,我们就可以计算出缩放比inSampleSize(只能是2的整数次幂)
options.inSampleSize = caluelateInSampleSize(options, reqWidth, reqHeight);//使用RGB_565减少图片大小 options.inPreferredConfig = Bitmap.Config.RGB_565; //释放内存,共享引用(21版本后失效) options.inPurgeable =true;
options.inInputShareable =true;
//inJustDecodeBounds为false,返回bitmap options.inJustDecodeBounds =false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), images[position], options);
privateintcalculateSampleSize(BitmapFactory.Options options,intreqWidth,int reqHeight){intwidth = options.outWidth;
intheight =options.outHeight;intinSampleSize = 1;
inthalfWidth = width / 2;
inthalfHeight = height / 2;
while((halfWidth / inSampleSize) >= reqWidth && (halfHeight / inSampleSize) >=reqHeight){
inSampleSize *= 2;
}
return inSampleSize;
}
2. 缓存策略
LRU(最近最少使用) -> LruCache和DiskLruCache,LruCache用于内存缓存、DiskLruCache用户存储设备缓存
【转】Fresco缓存分析三级缓存:Bitmap -> 未解码图片缓存 -> 磁盘缓存 ->网络
md5 ->【自】密码学基础
3. 异步加载
【转】Fresco异步加载:线程池、Handler等
三、存储
根据android sdk版本有所不同。
2.3以前:图片像素存储在native内存中。缺点是虚拟机无法自动进行垃圾回收,必须手动使用recycle,很容易导致内存泄露。也不方便调试等;
3.0以后:图片像素存储在Java堆中,垃圾回收能够自动进行,内存占用也能方便的展示在monitor中;
4.0以后:传输方式发生变化,大数据会通过ashmem(匿名共享内存)来传递(不占用Java内存),小数据通过直接拷贝的方式(在内存中操作),放宽了图片大小的限制;
【转】Android4.0 Bitmap Parcel传输源码分析
6.0以后:加强了ashmen存储图片的方式
【转】Android6.0 Bitmap存储以及Parcel传输源码分析
enumclass PixelStorageType {
Invalid,
External,
Java,
Ashmem,
};
Fresco 5.0以前将图片存储在Ashmen中,不会自动GC,因为不在Java堆中,也不会造成OOM,很大的一个优势。5.0以后系统默认启用了Ashmen模式。
四、转换
// 定义矩阵Matrix matrix =new Matrix(); // 【缩放图像】matrix.postScale(0.8f, 0.9f); // 【向左旋转】matrix.postRotate(-90); // 【移动图像】matrix.postTranslate(100, 100);// 【裁减图像】Bitmap.createBitmap(Bitmap source,intx,inty,intwidth,intheight, Matrix m,booleanfilter)
// 【圆角】
//
准备画笔Paint paint =new Paint();
paint.setAntiAlias(true);
// 准备裁剪的矩阵Rect rect =newRect(0, 0, originBitmap.getWidth(), originBitmap.getHeight());
RectF rectF =newRectF(newRect(0, 0, originBitmap.getWidth(), originBitmap.getHeight()));
Bitmap roundBitmap = Bitmap.createBitmap(originBitmap.getWidth(), originBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas =new Canvas(roundBitmap);// 圆角矩阵,radius为圆角大小canvas.drawRoundRect(rectF, radius, radius, paint);
paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN));// 这个比较有意思,混合模式 SRC_IN:显示交汇SRC图canvas.drawBitmap(originBitmap, rect, rect, paint);
【转】ndroid图像处理-Paint之Xfermode
//【图片灰阶处理】Bitmap grayBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas =new Canvas(grayBitmap);
Paint mPaint =new Paint();
//创建颜色变换矩阵 ColorMatrix colorMatrix =new ColorMatrix(); //设置饱和度为0,实现灰阶效果colorMatrix.setSaturation(0); //创建颜色过滤矩阵 ColorMatrixColorFilter colorFilter =new ColorMatrixColorFilter(colorMatrix); //设置画笔的颜色过滤矩阵 paint.setColorFilter(colorFilter); //使用处理后的画笔绘制图像 canvas.drawBitmap(bitmap, 0, 0, paint);
// 【Alpha位图】// 【倒影】// 【图像合成】// 无穷无尽啊...
五、内存优化
基于前面的原理来进行各方面的优化处理,缩放、Config、Compress选择、内存管理、缓存方式等等方面入手
六、开源框架
ImageLoader、Glide(google)、Fresco(FaceBook)、Picasso(Square)
Picasso包体积小、清晰,但功能有局限不能加载gif、只能缓存全尺寸;
Glide功能全面,擅长大型图片流,提交较大;
Fresco内存优化,减少oom,体积更大