通過BitmapFactory獲取bitmap

基于Android-29 

1.通過decodeFile獲取bitmap

 decodeFile(String pathName) 
進(jìn)行方法重載的調(diào)用 
decodeFile(String pathName, Options opts) 

然后,會(huì)根據(jù)文件路徑pathName,創(chuàng)建一個(gè)fileInputStream 最終去調(diào)用decodeStream

 stream = new FileInputStream(pathName);
 bm = decodeStream(stream, null, opts);

重點(diǎn)出現(xiàn)了,decodeStream,我們先暫停一下,看一下其他獲取bitmap的方法

2.通過decodeFileDescriptor取bitmap

decodeFileDescriptor(FileDescriptor fd)

接下來會(huì)同樣進(jìn)行方法重載的調(diào)用

 decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts)

在這里面我們先摘取關(guān)鍵代碼看一下

if (nativeIsSeekable(fd)) {
    bm = nativeDecodeFileDescriptor(fd, outPadding, opts,
                                    Options.nativeInBitmap(opts),
                                    Options.nativeColorSpace(opts)); 
                                                    //同樣有重點(diǎn),步驟1,native方法
} else {
    FileInputStream fis = new FileInputStream(fd);
    try {
        bm = decodeStreamInternal(fis, outPadding, opts); //同樣有重點(diǎn),步驟2
    } finally {
        try {
            fis.close();
        } catch (Throwable t) {/* ignore */}
    }
}
setDensityFromOptions(bm, opts);//同樣有重點(diǎn),步驟3

這里是通 過``nativeDecodeFileDescriptor或者decodeStreamInternal步驟獲取到bitmap,然后再通過步驟3給bitmap設(shè)置desity`,

關(guān)鍵方法 nativeDecodeFileDescriptorecodeStreamInternal

3.通過decodeByteArray獲取bitmap

decodeByteArray(byte[] data, int offset, int length)

同樣的會(huì)進(jìn)行方法重載調(diào)用

decodeByteArray(byte[] data, int offset, int length, Options opts)

在這里面我們摘取主要代碼看一下

bm = nativeDecodeByteArray(data, offset, length, opts,
                    Options.nativeInBitmap(opts),
                    Options.nativeColorSpace(opts));//步驟1,調(diào)用native方法獲取bitmap

if (bm == null && opts != null && opts.inBitmap != null) {
    throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);//步驟2,給目標(biāo)bitmap設(shè)置desity

這個(gè)方法里面就比較直接,調(diào)用nativeDecodeByteArray方法獲取到bitmap后,根據(jù)options給bitmap設(shè)置Desity屬性

4.通過decodeResource獲取bitmap

decodeResource(Resources res, int id)

同樣進(jìn)行方法重載

decodeResource(Resources res, int id, Options opts) 

這里面有一處主要的代碼

final TypedValue value = new TypedValue();
InputStream is = null; 
is = res.openRawResource(id, value);//獲取到inputStream,注意

bm = decodeResourceStream(res, value, is, null, opts);
//調(diào)用這個(gè),此時(shí)value.density已經(jīng)有值,會(huì)將資源文件對應(yīng)目錄的dpi設(shè)置給value.density后面會(huì)使用

decodeResourceStream(res, value, is, null, opts);是什么呢,同樣是查看源碼

public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
            @Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
       
        if (opts == null) {
            opts = new Options();
        }

        if (opts.inDensity == 0 && value != null) {
            final int density = value.density;
            if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
            }
        } //這一部分主要是設(shè)置desity來讓bitmap所使用
        
        if (opts.inTargetDensity == 0 && res != null) {
            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
        }//這一部分主要是設(shè)置目標(biāo)desity來讓bitmap所使用
        
        return decodeStream(is, pad, opts);//又到了decodeStream,似曾相識(shí)的感覺
    }

5.通過decodeStream獲取bitmap

decodeStream(InputStream is)

方法重載調(diào)用

decodeStream(@Nullable InputStream is, @Nullable Rect outPadding,
            @Nullable Options opts) 

那我們就仔細(xì)的看一下這個(gè)就去的具體實(shí)現(xiàn)

if (is instanceof AssetManager.AssetInputStream) {
    final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
    bm = nativeDecodeAsset(asset, outPadding, opts,                 Options.nativeInBitmap(opts),                           Options.nativeColorSpace(opts));//方式一,通過asset資源獲取的輸入流
} else {
    bm = decodeStreamInternal(is, outPadding, opts); //方式二,其他情況得到的輸入流
}

if (bm == null && opts != null && opts.inBitmap != null) {
    throw new IllegalArgumentException("Problem decoding into existing bitmap");
}
setDensityFromOptions(bm, opts);//設(shè)置desity

方式一已經(jīng)調(diào)用了native方法,看一下方式二的具體實(shí)現(xiàn)

decodeStreamInternal(@NonNull InputStream is,
            @Nullable Rect outPadding, @Nullable Options opts) 
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
return nativeDecodeStream(is, tempStorage, outPadding, opts,
                          Options.nativeInBitmap(opts),
                          Options.nativeColorSpace(opts));

方式二 也是走到了native方法里面.

我們在進(jìn)入native方法之前先來進(jìn)行一個(gè)簡單地總結(jié):

  1. 通過decodeFile獲取bitmap會(huì)最終走到decodeStream
  2. 通過decodeFileDescriptor獲取bitmap,最終會(huì)走到nativeDecodeFileDescriptor或者decodeStreamInternal
  3. 通過decodeByteArray獲取bitmap,最終會(huì)走到nativeDecodeByteArray
  4. 通過decodeResource獲取bitmap,最終會(huì)走到decodeStream
  5. 通過decodeStream獲取bitmap,最終會(huì)走到nativeDecodeAsset或者decodeStreamInternal
  6. decodeStreamInternal方式最終會(huì)走到nativeDecodeStream

綜上所述,最終獲取bitmap的方法都會(huì)調(diào)用以下四種方式之一來進(jìn)行:

  • nativeDecodeFileDescriptor
  • nativeDecodeByteArray
  • nativeDecodeAsset
  • nativeDecodeStream

優(yōu)秀文章推薦
深入理解Android Bitmap的各種操作
Android中圖片壓縮分析(上)
Android中圖片壓縮分析(下)
Bitmap 在內(nèi)存中的實(shí)際大小

image.png

Android中詳細(xì)的Bitmap
Bitmap 加載耗時(shí)長、占用內(nèi)存高,如何優(yōu)化?
Android一整套圖片解決方案
Android 系統(tǒng)自帶圖片裁剪功能(適配7.0跌帐、8.0楼吃、小米))
Bitmap 質(zhì)量壓縮 以及bitmap保存變大的原因

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羹幸,一起剝皮案震驚了整個(gè)濱河市催束,隨后出現(xiàn)的幾起案子澎现,更是在濱河造成了極大的恐慌铅匹,老刑警劉巖押赊,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異包斑,居然都是意外死亡流礁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門罗丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來神帅,“玉大人,你說我怎么就攤上這事萌抵≌矣” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵绍填,是天一觀的道長霎桅。 經(jīng)常有香客問我,道長讨永,這世上最難降的妖魔是什么滔驶? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮卿闹,結(jié)果婚禮上揭糕,老公的妹妹穿的比我還像新娘。我一直安慰自己锻霎,他們只是感情好插佛,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著量窘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氢拥。 梳的紋絲不亂的頭發(fā)上蚌铜,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天锨侯,我揣著相機(jī)與錄音,去河邊找鬼冬殃。 笑死囚痴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的审葬。 我是一名探鬼主播深滚,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涣觉!你這毒婦竟也來了痴荐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤官册,失蹤者是張志新(化名)和其女友劉穎生兆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膝宁,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸦难,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了员淫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片合蔽。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖介返,靈堂內(nèi)的尸體忽然破棺而出拴事,到底是詐尸還是另有隱情,我是刑警寧澤映皆,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布挤聘,位于F島的核電站,受9級(jí)特大地震影響捅彻,放射性物質(zhì)發(fā)生泄漏组去。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一步淹、第九天 我趴在偏房一處隱蔽的房頂上張望从隆。 院中可真熱鬧,春花似錦缭裆、人聲如沸键闺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辛燥。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挎塌,已是汗流浹背徘六。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留榴都,地道東北人待锈。 一個(gè)月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像嘴高,于是被迫代替她去往敵國和親竿音。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361