在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Android端:優化Bitmap內存的幾種方法

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

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

整理 | 包包

初識

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

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

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

了解

Bitmap 占用了多大的內存

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

所以計算內存大小的公式為:

占用的內存大小 = 像素總數量(寬x高)x 每個像素的字節大小

單個像素的字節大小

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

dd10223e3e0a41f3ba4e5857adf086e1


Android系統中,默認Bitmap加載圖片,使用ARGB_8888模式。

Bitmap 占用內存大小實例

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


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

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


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

1b627a3bc6b94c8da34fdf0b6a806f5d


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

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

? inTargetDensity: Bitmap 最終繪制的目標位置的分辨率

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

a4a77501595a4a0ca17ea7fad53a2faa


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

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

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

手動設置縮放系數

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

168ca8c69c4b432e92b3f6eac127cc07


壓縮方式 inSampleSize & quality

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

quality 正如字面意思指的是圖片品質,在代碼中對應的 api 為:

5c6276611390424d8bb176604c582155


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

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

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

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

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

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

調試

現在我們通過幾個實例,來驗證一下以上的結論,首先來看一下兩種壓縮方式占用內存的影響:

inSampleSize

45aa8fc9b5214936bcaf103256312559


顯示結果 :


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

降低圖片品質

0b74cd8226bd4e15819acd14b12b53dd


顯示結果 :


使用降低圖片質量的方式壓縮圖片,可以發現盡管已經降低了 90% 的品質,圖片也變得模糊,但其占用的內存與直接加載還是一樣的。

改變 Bitmap.Config

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


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

總結

在上面,我們將一張 1920x1080 的圖片,不做任何處理解析到內存中,將近占用的 7M,想象一下這樣的開銷發生在一個圖片列表中,內存占用將達到非常夸張的地步。從之前Bitmap占用內存的計算公式來看,減少內存主要可以通過以下幾種方式:

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

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

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


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3946

    瀏覽量

    128013
  • BITMAP
    +關注

    關注

    0

    文章

    4

    瀏覽量

    6396
收藏 人收藏

    評論

    相關推薦

    hyper 內存,Hyper內存:如何監控與優化hyper-v虛擬機的內存使用

    :如何監控與優化hyper-v虛擬機的內存使用。 ? ?在虛擬化環境中,合理監控和優化Hyper-V虛擬機的內存使用對于提升性能和資源利用率至關重要。本文將詳細介紹如何監控Hyper-
    的頭像 發表于 01-24 14:15 ?194次閱讀
    hyper <b class='flag-5'>內存</b>,Hyper<b class='flag-5'>內存</b>:如何監控與<b class='flag-5'>優化</b>hyper-v虛擬機的<b class='flag-5'>內存</b>使用

    焊接技術流程優化方法

    焊接方法的選擇對焊接質量有著直接影響。常見的焊接方法包括電弧焊、氣體保護焊、激光焊等。每種方法都有其特點和適用范圍,選擇合適的焊接方法可以提高焊接效率和質量。 1.2
    的頭像 發表于 01-19 13:52 ?374次閱讀

    android手機上emulate應用程序的方法

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

    如何優化RAM內存使用

    優化RAM內存使用是一個重要的任務,特別是對于那些擁有有限內存資源的用戶。以下是一些優化RAM內存使用的策略,這些策略可以幫助您更有效地使用
    的頭像 發表于 11-11 09:58 ?643次閱讀

    DRA7xx器件上的Android啟動優化

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

    環路測試方法有哪幾種

    。環路測試的目的是確保循環能夠正確地開始、執行和終止,以及在循環內部的邏輯是否正確。 環路測試通常包括以下幾種方法: 基本路徑測試 :這是最基礎的環路測試方法,它關注于測試循環的基本執行路徑。測試者會創建測試用例,確保循環能夠按照預期執行,包括循
    的頭像 發表于 09-12 14:35 ?868次閱讀

    直流無刷電機調速有幾種方法及應用

    多種多樣,每種方法都有其特定的應用場景和優缺點。 1. 電壓控制調速 電壓控制調速是通過改變電機供電電壓的大小來實現調速的方法。這種方法簡單易行,但效率較低,因為電壓的變化會導致電機的磁通量變化,從而影響電機的性能。 1.
    的頭像 發表于 09-03 10:43 ?2317次閱讀

    stm32程序燒錄的幾種方法?

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

    測量串聯電路的Q值有幾種方法

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

    如何檢測內存泄漏

    檢測內存泄漏是軟件開發過程中一項至關重要的任務,它有助于識別和解決那些導致程序占用過多內存資源,從而影響程序性能甚至導致程序崩潰的問題。以下將詳細闡述幾種常見的內存泄漏檢測
    的頭像 發表于 07-30 11:50 ?2303次閱讀

    產生脈沖信號有幾種方法

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

    mesh的內存占用能否優化

    余110kb可用。 請問,mesh的內存占用問題能否優化?為何系統剩余大概60K0內存以下的時候系統會因內存不足重啟?
    發表于 06-28 15:32

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

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

    改變異步電動機的轉速的幾種方法

    改變異步電動機的轉速可以通過以下幾種方法實現:調節輸入電壓、改變動態電阻、更換極數、調整定子電阻、調整轉子電阻和改變電源頻率等。下面將對這些方法進行詳細介紹。 ? 1. 調節輸入電壓 異步電動機
    的頭像 發表于 02-23 08:41 ?2251次閱讀

    改變異步電動機的轉速有幾種方法

    改變異步電動機的轉速有幾種方法? 改變異步電動機的轉速可以通過以下幾種方法實現:調節輸入電壓、改變動態電阻、更換極數、調整定子電阻、調整轉子電阻和改變電源頻率等。下面將對這些方法進行詳細介紹。 1.
    的頭像 發表于 02-20 11:43 ?1709次閱讀
    主站蜘蛛池模板: 爱爱的免费视频 | 久久国产精品99精品国产987 | 中文字幕色婷婷在线精品中 | 色综合色 | 久久综合欧美 | 伊人久久大香线蕉综合bd高清 | 男校霸把男校草玩出水男男 | 美女一级a毛片免费观看 | 性做久久久久久免费观看 | 欧美亚洲另类在线观看 | 26uuu影院亚洲欧美综合 | 欧美卡一卡二卡新区网站 | 精品在线一区二区 | 欧美人交性视频在线香蕉 | 大美女久久久久久j久久 | 四虎海外在线永久免费看 | 视频一区在线观看 | 艹逼免费视频 | 在线免费看污视频 | 成在线人视频免费视频 | 好男人www社区影视在线 | 精品卡1卡2卡三卡免费视频 | 亚洲午夜精品久久久久久成年 | 中文字幕第二区 | 免费视频色 | 六月婷婷综合激情 | 色偷偷网| 天天av天天翘天天综合网 | 精品人人| 欧美性受xxxx | 日韩一级片免费观看 | 国产香蕉75在线播放 | 特级毛片a级毛免费播放 | 欧美一级鲁丝片 | 狠狠色噜噜狠狠狠狠色综合久 | 激情五月深爱五月 | 俄罗斯毛片基地 | 户外露出精品视频国产 | 亚洲涩综合 | 91大神免费视频 | 成人a区|