RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Android端:優(yōu)化Bitmap內(nèi)存的幾種方法

張康康 ? 2019-07-29 18:27 ? 次閱讀

作者 | Video++極鏈科技移動端Team秦鵬程

整理 | 包包

初識

Bitmap是圖像處理的最重要類之一。用它可以獲取圖像文件信息,進(jìn)行圖像顏色變換、剪切、旋轉(zhuǎn)、縮放等操作,并可以指定格式保存圖像文件。

許多 Android 開發(fā)者都對 Bitmap 不陌生,其作為顯示圖片的載體,會經(jīng)常接觸。而在日常開發(fā)中對圖片的處理通常會用到第三方的開源庫:Glide、Fresco、Picasso...,這些已經(jīng)足夠完善的工具不需要讓我們考慮處理 Bitmap 的細(xì)節(jié),這使得我們對其不是那么熟悉。

Bitmap 實(shí)實(shí)在在是內(nèi)存使用的“大客戶”。如何更好的使用 Bitmap,減少其對App內(nèi)存的使用,是 Android 優(yōu)化方面不可回避的問題,因此,本文從常規(guī)的 Bitmap 使用,到 Bitmap 內(nèi)存計算,最后分析如何更有效的使用 Bitmap。

了解

Bitmap 占用了多大的內(nèi)存

Bitmap 用來處理位圖,每一張圖片的每個像素點(diǎn)都會被讀取,每個像素點(diǎn)的大小決定了 Bitmap 的內(nèi)存大小。

所以計算內(nèi)存大小的公式為:

占用的內(nèi)存大小 = 像素總數(shù)量(寬x高)x 每個像素的字節(jié)大小

單個像素的字節(jié)大小

單個像素的字節(jié)大小由Bitmap的一個可配置的參數(shù)Config來決定。Bitmap中,存在一個枚舉類Config,定義了Android中支持的Bitmap配置:

dd10223e3e0a41f3ba4e5857adf086e1


Android系統(tǒng)中,默認(rèn)Bitmap加載圖片,使用ARGB_8888模式。

Bitmap 占用內(nèi)存大小實(shí)例

我們準(zhǔn)備一張分辨率為 1920x1080,大小為 273KB 的 jpg 圖片,放在手機(jī)SD 卡中,調(diào)用 BitmatFactory.decodeFile() 加載并顯示到一個大小為 640x320 的 ImageView 中,占用的內(nèi)存如下:


從計算內(nèi)存大小的公式可以得到加載這張圖片使用了大約 7m 的內(nèi)存,即使是手機(jī)內(nèi)存普遍上漲的今天,這樣的開銷也是法接受的。

在剛才的實(shí)例中,我們是將圖片放在了手機(jī)的外置 SD 卡中,現(xiàn)在,我們將圖片分別放到項(xiàng)目工程的 mipmap-xhdpi, mipmap-xxhdpi, mipmap-xxxhdpi 這三個資源目錄中,調(diào)用 BitmatFactory.decodeResource() 加載到同樣的 ImageView 中看看加載的情況:


我們發(fā)現(xiàn),圖片放在不同的資源目錄中、使用不同的方法加載,占用的內(nèi)存也會不同,為了探究這其中原理,需要通過觀察 Bitmap.decode 的源碼,這一過程是有 native 來完成的,所以我們找到 BitmapFactory.cpp#nativeDecode 開始跟蹤,省略了其他不相關(guān)的代碼:

1b627a3bc6b94c8da34fdf0b6a806f5d


上述代碼中,最終 bitmap 是通過 canvas 繪制出來,而 canvas 繪制前有 scale 的操作 scale = (float) targetDensity / density; 這一行代碼決定,即縮放的倍率和 targetDensity 和 density 相關(guān),而這兩個參數(shù)都是從傳入的 options 中獲取到的,再到 Bitmap.Options 中找到相關(guān)的參數(shù):

? inDensity:Bitmap 位圖自身的密度、分辨率

? inTargetDensity: Bitmap 最終繪制的目標(biāo)位置的分辨率

其中 inDensity 和圖片存放的資源文件的目錄有關(guān),同一張圖片放置在不同目錄下會有不同的值:

a4a77501595a4a0ca17ea7fad53a2faa


通過以上兩個實(shí)例,我們得出了 decodeResource() 和 decodeFile() 的區(qū)別:

?decodeResource 用于讀取Res、Raw等資源,得到的是圖片的原始尺寸 * 縮放系數(shù)(inDensity)

?decodeFile 用于讀取SD卡上的圖,得到的是圖片的原始尺寸

手動設(shè)置縮放系數(shù)

在 Bitmap.Options 中還有一個為 inScaled 的屬性,如果設(shè)置為 false,則不進(jìn)行縮放,如果設(shè)置為 true 或者不設(shè)置,則根據(jù) inDensity 和 inTargetDensity 計算縮放系數(shù)。 如果你不想依賴于這個系統(tǒng)本身的 density,你可以手動設(shè)置 inDensity 和 inTargetDensity 來控制縮放系數(shù):

168ca8c69c4b432e92b3f6eac127cc07


壓縮方式 inSampleSize & quality

inSampleSize 指的是壓縮分辨率,取值必須為 2 的冪(當(dāng)不為2的冪時,解碼器會取與該值最接近的2的冪),例如,當(dāng) inSampleSize = 2 時,一張 1920x1080 的圖片,將會被縮小為 960x540,相應(yīng)的它的像素數(shù)和內(nèi)存占用都被縮小為原來的 1/4。

quality 正如字面意思指的是圖片品質(zhì),在代碼中對應(yīng)的 api 為:

5c6276611390424d8bb176604c582155


CompressFormat 為 Bitmap 中的枚舉類,有三個可用值:

? JPEG:表示以 JPEG 壓縮算法進(jìn)行圖像壓縮,壓縮后的格式可以是 “.jpg” 或者 “.jpeg” ,是一種有損壓縮。

? PNG:表示以 PNG 壓縮算法進(jìn)行圖像壓縮,壓縮后的格式可以是 “.png” ,是一種無損壓縮。

? WEBP:表示以 WebP 壓縮算法進(jìn)行圖像壓縮,壓縮后的格式可以是 “.webp” ,是一種有損壓縮,質(zhì)量相同的情況下,WebP 格式圖像的體積要比 JPEG 格式圖像小40%。美中不足的是,WebP格式圖像的編碼時間“比JPEG格式圖像長8倍”。

quality 為圖片的品質(zhì),取值為 0-100,100 代表最高品質(zhì),不被壓縮。另外,類似 PNG 這種無損格式會忽略 quality 的設(shè)置 stream 為圖片被壓縮后被保存在的輸出流。

然而 Bitmap.compress 方法確實(shí)可以壓縮圖片,但壓縮的是存儲大小,即放到 disk 上的大小。

調(diào)試

現(xiàn)在我們通過幾個實(shí)例,來驗(yàn)證一下以上的結(jié)論,首先來看一下兩種壓縮方式占用內(nèi)存的影響:

inSampleSize

45aa8fc9b5214936bcaf103256312559


顯示結(jié)果 :


以上 ImageView 的大?。?40x320),用來加載 1920x1080 的圖片確實(shí)有些浪費(fèi),所以經(jīng)過計算,將原圖壓縮后發(fā)現(xiàn)圖片占用內(nèi)存的大小減少到原圖的 1/10,如果原圖本身與控件的大小相差不多,這時候還要縮放的話就會影響到圖片顯示的質(zhì)量。

降低圖片品質(zhì)

0b74cd8226bd4e15819acd14b12b53dd


顯示結(jié)果 :


使用降低圖片質(zhì)量的方式壓縮圖片,可以發(fā)現(xiàn)盡管已經(jīng)降低了 90% 的品質(zhì),圖片也變得模糊,但其占用的內(nèi)存與直接加載還是一樣的。

改變 Bitmap.Config

我們已經(jīng)知道, Bitmap 加載圖片默認(rèn)使用的 config 為 ARGB_8888,而且 ALPHA_8 是只有透明度的, 所以我們來看看改為 ARGB_4444 和 RGB_565 所顯示的結(jié)果,只需要在 decode 的時候傳入設(shè)置好的 options 參數(shù),所以這里直接給出顯示結(jié)果:


可以看到將 config 改為 ARGB_4444,所占用的內(nèi)存與原圖一樣,而 RGB_565,變得是原圖的 1/2,所以結(jié)論也不言而喻了,另外 ARGB_4444,已被官方標(biāo)記為廢棄。

總結(jié)

在上面,我們將一張 1920x1080 的圖片,不做任何處理解析到內(nèi)存中,將近占用的 7M,想象一下這樣的開銷發(fā)生在一個圖片列表中,內(nèi)存占用將達(dá)到非??鋸埖牡夭?。從之前Bitmap占用內(nèi)存的計算公式來看,減少內(nèi)存主要可以通過以下幾種方式:

? 使用低色彩的解析模式,如RGB565,減少單個像素的字節(jié)大小。這樣大約能減少一半的內(nèi)存開銷。Android 默認(rèn)是使用 ARGB_8888 配置來處理色彩,占用4字節(jié),改用RGB_565,將只占用2字節(jié),代價是顯示的色彩將相對少,適用于對色彩豐富程度要求不高的場景。

? 資源文件合理放置,高分辨率圖片可以放到高分辨率目錄下。和圖片的具體分辨率有關(guān),建議開發(fā)中,高分辨率的圖像應(yīng)該放置到合理的資源目錄下,注意到Android默認(rèn)放置的資源目錄是對應(yīng)于160dpi,目前手機(jī)屏幕分辨率越來越高,此處能節(jié)省下來的開銷也是很可觀的。理論上,圖片放置的資源目錄分辨率越高,其占用內(nèi)存會越小,但是低分辨率圖片會因此被拉伸,顯示上出現(xiàn)失真。另一方面,高分辨率圖片也意味著其占用的本地儲存也變大。

? 圖片縮小,減少尺寸。理論上根據(jù)適用的環(huán)境,是可以減少十幾倍的內(nèi)存使用的,它基于這樣一個事實(shí):源圖片尺寸一般都大于目標(biāo)需要顯示的尺寸,因此可以通過縮放的方式,來減少顯示時的圖片寬高,從而大大減少占用的內(nèi)存。


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Android
    +關(guān)注

    關(guān)注

    12

    文章

    3935

    瀏覽量

    127339
  • BITMAP
    +關(guān)注

    關(guān)注

    0

    文章

    4

    瀏覽量

    6375
收藏 人收藏

    評論

    相關(guān)推薦

    android手機(jī)上emulate應(yīng)用程序的方法

    Android手機(jī)上模擬(emulate)應(yīng)用程序的方法通常涉及到使用Android模擬器(Emulator)或類似的工具來模擬Android環(huán)境,以便在沒有實(shí)際物理設(shè)備的情況下運(yùn)行
    的頭像 發(fā)表于 12-05 15:33 ?243次閱讀

    如何優(yōu)化RAM內(nèi)存使用

    優(yōu)化RAM內(nèi)存使用是一個重要的任務(wù),特別是對于那些擁有有限內(nèi)存資源的用戶。以下是一些優(yōu)化RAM內(nèi)存使用的策略,這些策略可以幫助您更有效地使用
    的頭像 發(fā)表于 11-11 09:58 ?309次閱讀

    DRA7xx器件上的Android啟動優(yōu)化

    電子發(fā)燒友網(wǎng)站提供《DRA7xx器件上的Android啟動優(yōu)化.pdf》資料免費(fèi)下載
    發(fā)表于 10-11 09:41 ?0次下載
    DRA7xx器件上的<b class='flag-5'>Android</b>啟動<b class='flag-5'>優(yōu)化</b>

    環(huán)路測試方法有哪幾種

    。環(huán)路測試的目的是確保循環(huán)能夠正確地開始、執(zhí)行和終止,以及在循環(huán)內(nèi)部的邏輯是否正確。 環(huán)路測試通常包括以下幾種方法: 基本路徑測試 :這是最基礎(chǔ)的環(huán)路測試方法,它關(guān)注于測試循環(huán)的基本執(zhí)行路徑。測試者會創(chuàng)建測試用例,確保循環(huán)能夠按照預(yù)期執(zhí)行,包括循
    的頭像 發(fā)表于 09-12 14:35 ?567次閱讀

    直流無刷電機(jī)調(diào)速有幾種方法及應(yīng)用

    多種多樣,每種方法都有其特定的應(yīng)用場景和優(yōu)缺點(diǎn)。 1. 電壓控制調(diào)速 電壓控制調(diào)速是通過改變電機(jī)供電電壓的大小來實(shí)現(xiàn)調(diào)速的方法。這種方法簡單易行,但效率較低,因?yàn)殡妷旱淖兓瘯?dǎo)致電機(jī)的磁通量變化,從而影響電機(jī)的性能。 1.
    的頭像 發(fā)表于 09-03 10:43 ?1634次閱讀

    stm32程序燒錄的幾種方法?

    STM32是一款由STMicroelectronics公司推出的32位微控制器,廣泛應(yīng)用于嵌入式系統(tǒng)開發(fā)。燒錄STM32程序是開發(fā)過程中的重要環(huán)節(jié)。本文將介紹幾種常見的STM32程序燒錄方法,包括
    的頭像 發(fā)表于 08-22 09:35 ?4075次閱讀

    測量串聯(lián)電路的Q值有幾種方法

    。 1. 共振法 共振法是一種常用的測量Q值的方法,它基于諧振電路在諧振頻率下的特性。在這種方法中,我們首先需要確定電路的諧振頻率,然后測量電路在該頻率下的阻抗。 原理: 當(dāng)電路達(dá)到諧振頻率時,電感和電容的感抗相互抵消
    的頭像 發(fā)表于 08-09 17:10 ?1806次閱讀

    如何檢測內(nèi)存泄漏

    檢測內(nèi)存泄漏是軟件開發(fā)過程中一項(xiàng)至關(guān)重要的任務(wù),它有助于識別和解決那些導(dǎo)致程序占用過多內(nèi)存資源,從而影響程序性能甚至導(dǎo)致程序崩潰的問題。以下將詳細(xì)闡述幾種常見的內(nèi)存泄漏檢測
    的頭像 發(fā)表于 07-30 11:50 ?1796次閱讀

    產(chǎn)生脈沖信號有幾種方法

    脈沖信號是一種在特定時間間隔內(nèi)具有特定幅度的信號,它在電子學(xué)、通信、控制等領(lǐng)域有著廣泛的應(yīng)用。產(chǎn)生脈沖信號的方法有很多種,下面將介紹幾種常見的方法。 555定時器產(chǎn)生脈沖信號 555定時器是一種
    的頭像 發(fā)表于 07-15 10:35 ?1344次閱讀
    產(chǎn)生脈沖信號有<b class='flag-5'>幾種方法</b>

    mesh的內(nèi)存占用能否優(yōu)化?

    余110kb可用。 請問,mesh的內(nèi)存占用問題能否優(yōu)化?為何系統(tǒng)剩余大概60K0內(nèi)存以下的時候系統(tǒng)會因內(nèi)存不足重啟?
    發(fā)表于 06-28 15:32

    接地電阻的測量有哪幾種方法

    接地電阻的測量對于確保電氣系統(tǒng)的安全性和可靠性至關(guān)重要。存在幾種不同的方法來測量接地電阻,每種方法都有其特定的應(yīng)用場景和技術(shù)要求。
    的頭像 發(fā)表于 05-07 14:17 ?1.3w次閱讀

    改變異步電動機(jī)的轉(zhuǎn)速的幾種方法

    改變異步電動機(jī)的轉(zhuǎn)速可以通過以下幾種方法實(shí)現(xiàn):調(diào)節(jié)輸入電壓、改變動態(tài)電阻、更換極數(shù)、調(diào)整定子電阻、調(diào)整轉(zhuǎn)子電阻和改變電源頻率等。下面將對這些方法進(jìn)行詳細(xì)介紹。 ? 1. 調(diào)節(jié)輸入電壓 異步電動機(jī)
    的頭像 發(fā)表于 02-23 08:41 ?1948次閱讀

    改變異步電動機(jī)的轉(zhuǎn)速有幾種方法

    改變異步電動機(jī)的轉(zhuǎn)速有幾種方法? 改變異步電動機(jī)的轉(zhuǎn)速可以通過以下幾種方法實(shí)現(xiàn):調(diào)節(jié)輸入電壓、改變動態(tài)電阻、更換極數(shù)、調(diào)整定子電阻、調(diào)整轉(zhuǎn)子電阻和改變電源頻率等。下面將對這些方法進(jìn)行詳細(xì)介紹。 1.
    的頭像 發(fā)表于 02-20 11:43 ?1490次閱讀

    電阻應(yīng)變片的溫度補(bǔ)償方法幾種?

    電阻應(yīng)變片的溫度補(bǔ)償方法幾種? 電阻應(yīng)變片的溫度補(bǔ)償方法有以下幾種: 1. 溫度傳感器補(bǔ)償方法 溫度傳感器補(bǔ)償
    的頭像 發(fā)表于 02-04 18:14 ?5502次閱讀

    PWM產(chǎn)生的幾種方法總結(jié)

    PWM產(chǎn)生的方法有很多種,小編將常用的幾種產(chǎn)生方法作了一個整理以及分類,下面我們來了解一下。
    的頭像 發(fā)表于 01-11 09:15 ?2962次閱讀
    PWM產(chǎn)生的<b class='flag-5'>幾種方法</b>總結(jié)
    RM新时代网站-首页