(1)常用屬性
BitmapFactory.Options options = new BitmapFactory.Options();
//默認(rèn)值為false酬凳,如果設(shè)置成true,那么在解碼的時(shí)候就不會返回bitmap,即bitmap = null不皆。
options.inJustDecodeBounds = false;
//可以復(fù)用之前用過的bitmap
options.inBitmap = null;
//是該bitmap緩存是否可變,如果設(shè)置為true熊楼,將可被inBitmap復(fù)用
options.inMutable = true;
DisplayMetrics dm = getResources().getDisplayMetrics();
//表示這個(gè)bitmap的像素密度霹娄,當(dāng)inDensity為0時(shí),系統(tǒng)默認(rèn)賦值為屏幕當(dāng)前像素密度
options.inDensity = dm.densityDpi;
//表示要被畫出來時(shí)的目標(biāo)像素密度鲫骗,當(dāng)inTargetDensity為0時(shí)犬耻,系統(tǒng)默認(rèn)賦值為屏幕當(dāng)前像素密度
options.inTargetDensity = options.inDensity;
//表示實(shí)際設(shè)備的像素密度
options.inScreenDensity = 0;
//這個(gè)參數(shù)可以改變bitmap分辨率大小,inSampleSize >= 1执泰。
//當(dāng)inSampleSize < 1時(shí)枕磁,inSampleSize就默認(rèn)是1。
//假如:圖片的寬和高分別是width术吝、height透典,那么圖片解碼生成的bitmap的寬度是:width / inSampleSize,高度是:height / inSampleSize
//inSampleSize影響bitmap的分辨率顿苇,從而影響bitmap占用內(nèi)存的大小峭咒。
options.inSampleSize = 1;
//設(shè)置這個(gè)Bitmap是否可以被縮放,默認(rèn)值是true纪岁,表示可以被縮放凑队。
options.inScaled = true;
(2)圖片加載之前先計(jì)算圖片大小
Bitmap bitmap = BitmapFactory.decodeFile(FileDirUtil.getInstance().getExternalStorageDirectory() + File.separator + "temp.jpg");
我們看一下上面的代碼,那是解碼一張本地圖片,解碼之后bitmap
將占用內(nèi)存空間漩氨,如果bitmap太大導(dǎo)致app性能降低西壮,甚至導(dǎo)致OOM發(fā)生,為了防止這種現(xiàn)象叫惊,我們可以先計(jì)算本地圖片的分辨率:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(FileDirUtil.getInstance().getExternalStorageDirectory() + File.separator + "temp.jpg", options );
int imageHeight = options.outHeight;
Log.d("aaa", "圖片的高度:"+imageHeight);
int imageWidth = options.outWidth;
Log.d("aaa", "圖片的寬度:"+imageWidth);
當(dāng)inJustDecodeBounds
設(shè)置true時(shí)款青,本地圖片解碼之后bitmap為null,只計(jì)算圖片的寬度和高度霍狰。拿到圖片寬度和高度之后可以根據(jù)我們自己的策略是否放大或縮小圖片分辨率抡草。
(3)使用inBitmap復(fù)用bitmap
將inMutable
設(shè)置成true,可以使當(dāng)前bitmap對空間可被復(fù)用蔗坯。
(4)像素密度分析
BitmapFactory.Options中與像素密度有關(guān)的主要有三個(gè)參數(shù):inDensity
康震、inTargetDensity
、inScreenDensity
配合inScaled
參數(shù)可以控制圖像縮放宾濒。
我們先看一下源碼
/**
* Set the newly decoded bitmap's density based on the Options.
*/
private static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
if (outputBitmap == null || opts == null) return;
final int density = opts.inDensity;
if (density != 0) {
outputBitmap.setDensity(density);
final int targetDensity = opts.inTargetDensity;
if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
return;
}
byte[] np = outputBitmap.getNinePatchChunk();
final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
if (opts.inScaled || isNinePatch) {
outputBitmap.setDensity(targetDensity);
}
} else if (opts.inBitmap != null) {
// bitmap was reused, ensure density is reset
outputBitmap.setDensity(Bitmap.getDefaultDensity());
}
}
inDensity的默認(rèn)值為0腿短,會執(zhí)行
outputBitmap.setDensity(Bitmap.getDefaultDensity());
bitmap的像素密度為屏幕默認(rèn)像素密度,相當(dāng)于
DisplayMetrics dm = getResources().getDisplayMetrics();
//表示這個(gè)bitmap的像素密度绘梦,當(dāng)inDensity為0時(shí)橘忱,系統(tǒng)默認(rèn)賦值為屏幕當(dāng)前像素密度
options.inDensity = dm.densityDpi;
當(dāng)我們給inDensity取值時(shí),就會走另一個(gè)分支卸奉,接下來才是重點(diǎn)
當(dāng)inTargetDensity=0或者inDensity=inTargetDensity或者inDensity=inScreenDensity時(shí)钝诚,圖像的像素密度是inDensity,否則择卦,當(dāng)inScaled = true或者圖像為9Path圖片時(shí),最終圖像的像素密度為inTargetDensity郎嫁。
inDensity
秉继、inTargetDensity
、inScreenDensity
泽铛、inScaled
配合使用可以對圖片進(jìn)行縮放尚辑,縮放的比例是targetDensity / density
(5)inSampleSize
修改像素密度只能修改圖像的分辨率,但不能改變bitmap大小盔腔。
而inSampleSize不僅可以修改分辨率杠茬,而且bitmap的大小也隨便變化。
假如默認(rèn)情況(inSampleSize = 1)下弛随,圖像的分辨率是205x205瓢喉,占用內(nèi)存0.16031265M,那么如果將inSampleSize 設(shè)置成2舀透,那么分辨率的寬和高分別除以2栓票,占用的內(nèi)存也會變小,最終圖像的分辨率是103x103愕够,占用內(nèi)存為0.040470123M走贪,bitmap大小整整縮小了4倍佛猛。
(6)設(shè)置彩色模式
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
比較簡單,只有一句話坠狡。
ARGB_8888:
圖像默認(rèn)模式继找,有A
、R
逃沿、G
婴渡、B
四個(gè)顏色通道,每個(gè)通道占8位感挥。
ARGB_4444:
已被棄用缩搅,有A
、R
触幼、G
硼瓣、B
四個(gè)顏色通道,每個(gè)通道占4位置谦。
RGB_565:
屏幕默認(rèn)顏色模式堂鲤,有R
、G
媒峡、B
三個(gè)顏色通道瘟栖。
ALPHA_8:
單通道,只有透明度通道谅阿。
RGBA_F16
和HARDWARE
是Android 8.0新增的半哟,目前用的比較少。
(7)獲取圖像的Mime類型
options.outMimeType
(8)設(shè)置緩沖區(qū)大小
//設(shè)置緩存區(qū),如果不設(shè)置默認(rèn)為16M
options.inTempStorage = new byte[1024 * 1024 * 16];
如果不設(shè)置签餐,那么默認(rèn)為16M寓涨。
(9)其他方法
//這個(gè)值和抖動(dòng)解碼有關(guān),默認(rèn)值為false氯檐,表示不采用抖動(dòng)解碼戒良。在Android N 之后已被廢棄。
options.inDither = true;
//這個(gè)值表示是否在解碼時(shí)圖片有更高的品質(zhì)冠摄,僅用于JPEG格式糯崎。如果設(shè)置為true,則圖片會有更高的品質(zhì)河泳,但是會解碼速度會很慢沃呢。
//在Android N 之后已被廢棄。
options.inPreferQualityOverSpeed = true;
//設(shè)置為true時(shí)拆挥,表示空間不夠是否可以被釋放樟插。和inInputShareable一起使用。在Android5.0后被棄用。
options.inPurgeable = false;
//設(shè)置為true時(shí)黄锤,后者表示是否可以共享引用搪缨。和inPurgeable一起使用。在Android5.0后被棄用鸵熟。
options.inInputShareable = false;
//在Android N 之后已被廢棄
options.mCancel = false;
以上這些方法在高版本API上已被棄用副编,所以就不用研究了。