Android Bitmap详解

转载自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,体积更大

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容