導航:首頁 > 文件處理 > android圖片壓縮oom

android圖片壓縮oom

發布時間:2022-11-28 14:08:00

Ⅰ 在android開發中載入的圖片太大,有好幾十兆,應該怎麼辦

如果圖片太大會造成OOM內存溢出的錯誤,需要用Bitmap的壓縮機制。
解決方案:
1.使用BitmapFactory.decodeStream替代createBitmap方法
原因是該方法直讀取圖片位元組,調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap。

2.使用壓縮讀取技術
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageSdUri, options);
final int height = options.outHeight;
final int width = options.outWidth;
options.inSampleSize = 1;
int w = 320;
int h = 480;
h = w*height/width;//計算出寬高等比率
int a = options.outWidth/ w;
int b = options.outHeight / h;
options.inSampleSize = Math.max(a, b);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(imageSdUri, options);

3.及時釋放Bitamp
Bitmap對象在不使用時,我們應該先調用recycle()釋放內存,然後才它設置為null.雖然recycle()從源碼上看,調用它應該能立即釋放Bitmap的主要內存,但是測試結果顯示它並沒能立即釋放內存。但是我它應該還是能大大的加速Bitmap的主要內存的釋放。

Ⅱ Android 高效內存-圖片內存使用優化

內容整理自網路。

在做內存優化的時候,我們發現除了解決內存泄露問題,剩下的就只有想辦法減少真實的內存佔用。而在App中,大部分內存可能被我們圖片佔用了,所以減少圖片的內存佔用可以帶來直接的效果。本文就簡單介紹一張圖片到底佔用多少內存,我們先假設我們有一張圖片時** 600 * 800** 的,圖片佔用空間大小假設是** 100KB**。

圖片內存大小跟佔用空間大小有什麼關系?

佔用空間的大小不是圖片佔用內存的大小,一些初學者可能會誤解一下。佔用空間是在磁碟上佔用的空間,內存大小是載入到內存中佔用的內存大小。兩個只是單位是一樣的,本質不是一個概念。

一張圖片到底佔用多少內存呢?(ARGB_8888編碼)

1. 圖片佔用內存的計算公式: 圖片高度 * 圖片寬度 * 一個像素佔用的內存大小

2. 所以上面的圖片佔用內存是:**800 * 600 * 4 byte = 1875KB = 1.83M **

上面的計算公式中,為什麼是4byte呢?文章後面有總結哦

圖片所在目錄對內存的影響?

在Android中,圖片的存放目錄和手機的屏幕密度影響圖片最終的大小,舉個例子:

假設我們的圖片放到 xhdpi 目錄下,那麼我們本文中的圖片佔用的內存大小如下:

屏幕密度為2的設備:800 * 600 * 4byte = 1.83M

屏幕密度為3的設備:800 * 1.5 * 600 * 1.5 * 4byte = 1.83 * 2.25M =** 4.12M**

所以,計算圖片佔用內存大小的時候,要考慮圖片所在的目錄跟設備密度,這兩個因素其實影響的是圖片的高寬,android會對圖片進行拉升跟壓縮。

總結

1. 圖片確實很佔用內存,內存優化先考慮圖片內存佔用;

2. 一定要避免使用大圖片,這就是.9圖很有用的原因之一;

3. 圖片的大小對內存的影響是正比關系;

4. 本文只是簡單的告知讀者怎麼計算圖片的內存大小。

大圖: 440 * 336    小圖: 220 * 168 資源目錄: xhdpi

小圖的高寬都是大圖的1/2-->小圖是原圖的1/4

界面效果:

測試設備: Coolpad   8676-M01   5.1   density=2.0

測試前准備操作: 同一款設備,設置圖片前後多次調用gc直到內存短時間內保持穩定不再變化

內存使用情況: 下圖依次是 初始內存,大圖內存,小圖內存

大圖佔用內存: 11.23 MB - 10.66 MB = 0.57 MB

小圖佔用內存: 10.81 MB - 10.66 MB = 0.15 MB

大圖小圖內存關系: 0.15 MB * 4 = 0.60 MB 約等於 0.57 MB (這是統計工具的誤差,理論上就是相等的)

同樣的方式在另外一台設備小米4c上得到的結果如下:

測試設備: Xiaomi   Mi-4c   V8.2.1.0.LXKCNDL   5.1.1   density=3.0

大圖佔用內存: 13.22 MB - 11.95 MB = 1.27 MB

小圖佔用內存: 12.27 MB - 11.95 MB = 0.32 MB

大圖小圖內存關系: 0.32 MB * 4 = 1.28 MB 約等於 1.27 MB

結論: 由此可見大圖比小圖佔用更多的內存,圖片大小(解析度)與佔用內存成正比關系

備註: 圖片在硬碟上佔用的磁碟空間大小,與在內存中佔用的內存大小完全不一樣,不是一個概念,不要混淆

根據上文中圖片大小與內存的關系,可以更加深刻的理解Android中.9圖片的作用,它不但能減少apk的體積,還能減少圖片佔用內存。

有些時候我們根本不需要圖片,而是自己繪制背景,可以在自定義View的onDraw中繪制背景,當然最方便的還是使用系統的Drawable,繪制部分交給系統去完成。

下面測試圖片與Drawable的內存佔用對比

原始圖片大小: 482 * 482

界面效果:

測試設備: Xiaomi   Mi-4c   V8.2.1.0.LXKCNDL   5.1.1

測試前准備操作: 同一款設備,設置背景前後多次調用gc直到內存短時間內保持穩定不再變化

內存使用情況: 下圖依次是 初始內存,使用圖片佔用的內存,使用Drawable佔用的內存,使用onDraw繪制佔用的內存

使用圖片佔用內存: 13.97 MB - 11.97 MB = 2.00 MB

使用Drawable佔用內存: 11.97 MB - 11.97 MB = 0.00 MB (不會是0,有誤差,只是很少)

使用onDraw繪制佔用內存: 11.98 MB - 11.97 MB = 0.01 MB

結論: 繪制背景,或者使用系統提供Drawable作為背景,會大大減少內存佔用

Drawable參考資料:

Drawable實戰解析:Android XML shape 標簽使用詳解(apk瘦身,減少內存好幫手)

Android GradientDrawable(shape標簽定義)靜態使用和動態使用(圓角,漸變實現)

「讓你的圖片最小化」一節中描述的方法:使用盡可能小的圖,使用.9,自己繪制背景或者使用Drawable來繪制背景

載入大圖片時需要對圖片進行壓縮,使用等比例壓縮方法直接在內存中處理圖片

這樣做要注意的是,圖片質量會變差,inSampleSize設置的值越大,圖片質量就越差。

有時候我們取得一張圖片,也許只是為了獲得這個圖片的一些信息,比如圖片的width、height等信息,不需要顯示到界面上,這個時候我們可以不把圖片載入到內存中。

由於Android外層是使用java,而底層使用的是C語言為圖片對象分配的內存空間。所以我們的外部雖然看起來釋放了,但里層卻並不一定完全釋放了,我們使用完圖片後最好再釋放掉里層的內存空間。

RGB(ARGB)

RGB色彩模式是工業界的一種顏色標准,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色的,RGB即是代表紅、綠、藍三個通道的顏色,這個標准幾乎包括了人類視力所能感知的所有顏色,是目前運用最廣的顏色系統之一。在Android中還有包含透明度Alpha的顏色模型,即ARGB。

YUV

YUV,分為三個分量,「Y」表示明亮度(Luminance或Luma),也就是灰度值;而「U」和「V」 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用於指定像素的顏色。

YUV的原理是把亮度與色度分離,研究證明,人眼對亮度的敏感超過色度。利用這個原理,可以把色度信息減少一點,人眼也無法查覺這一點。

主要用於電視系統以及模擬視頻領域,它將亮度信息(Y)與色彩信息(UV)分離,沒有UV信息一樣可以顯示完整的圖像,只不過是黑白的,這樣的設計很好地解決了彩色電視機與黑白電視的兼容問題

YUV的存儲中與RGB格式最大不同在於,RGB格式每個點的數據是連繼保存在一起的。即R,G,B是前後不間隔的保存在2-4byte空間中。而YUV的數據中為了節約空間,U,V分量空間會減小。每一個點的Y分量獨立保存,但連續幾個點的U,V分量是保存在一起的,(反正人眼一般也看不出區別).這幾個點合起來稱為macro-pixel, 這種存儲格式稱為Packed格式。另外一種存儲格式是把一幅圖像中Y,U,V分別用三個獨立的數組表示。這種模式稱為planar模式。

CMYK
  CMYK也稱作印刷色彩模式,顧名思義就是用來印刷的。印刷四分色模式是彩色印刷時採用的一種套色模式,利用色料的三原色混色原理,加上黑色油墨,共計四種顏色混合疊加,形成所謂「全彩印刷」。四種標准顏色是:

CMYK和RGB相比有一個很大的不同:RGB模式是一種發光的色彩模式,你在一間黑暗的房間內仍然可以看見屏幕上的內容;CMYK是一種依靠反光的色彩模式,我們是怎樣閱讀報紙的內容呢?是由陽光或燈光照射到報紙上,再反射到我們的眼中,才看到內容。它需要有外界光源,如果你在黑暗房間內是無法閱讀報紙的。只要是在印刷品上看到的圖像,就是CMYK模式表現的。比如期刊、雜志、報紙、宣傳畫等,都是印刷出來的,那麼就是CMYK模式的了。

CMYK原色與疊加之後的顏色對比

在不考慮透明度的情況下,一個像素點的顏色值在計算機中的表示方法有以下3種:

在Java中,float類型的變數佔32位,int類型的變數佔32位,short和char類型的變數都在16位,因此可以看出,用浮點數表示法編碼一個像素的顏色,內存佔用量是96位即12位元組;而用24位整數表示法編碼,只要一個int類型變數,佔用4個位元組(高8位空著,低24位用於表示顏色);用16位整數表示法編碼,只要一個short類型變數,佔2個位元組;因此可以看出採用整數表示法編碼顏色值,可以大大節省內存,當然,顏色質量也會相對低一些。在Android中獲取Bitmap的時候一般也採用整型編碼。

回想一下Android的BitmapConfig類中,有ARGB_8888、ARGB_4444、RGB565等常量,現在可以知道它們分別代表了什麼含義。同時也可以計算一張圖片在內存中可能佔用的大小,比如採用ARGB_8888編碼載入一張1920 1200的圖片,大概就會佔用1920 1200*4/1024/1024=8.79MB的內存。

採用低內存佔用量的編碼方式,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省內存;

1920 1200的圖片:*

ARGB_8888:1920 1200 4/1024/1024=8.79MB

ARGB_4444,RGB565:1920 1200 2/1024/1024=4.39MB

在Android中,對圖片的使用一定要關注,大多數情況下,佔用內存多,OOM發生都是因為圖片資源使用不當。不要盲目加一個大圖到Android項目中,能使用.9進來使用,而且.9圖本身盡可能小,另外能使用繪制實現就不要加一個圖片資源。有些時候,在不影響用戶體驗的情況下,可以降低圖片素材質量,比如不需要透明度的就不要了,有些透明度用肉眼看不出來。

Ⅲ android oom是什麼意思

Android oom 有時出現很頻繁,這一般不是Android設計的問題,一般是我們的問題。
就我的經驗而言,出現oom,無非主要是以下幾個方面:
一、載入對象過大
二、相應資源過多,沒有來不及釋放。
解決這樣的問題,也有一下幾個方面:
一:在內存引用上做些處理,常用的有軟引用、強化引用、弱引用
二:在內存中載入圖片時直接在內存中做處理,如:邊界壓縮.
三:動態回收內存
四:優化Dalvik虛擬機的堆內存分配
五:自定義堆內存大小

Ⅳ 圖片壓縮的三種方式

1、等比壓縮,等比壓縮是保持原圖長寬比例的壓縮,只是圖片變小,展示的還是原圖的所有內容(區別於第二種通過Matrix壓縮,可以選取圖片的一部分,類似於上傳頭像時,讓你在圖上選一塊zoom的形式)。等比壓縮用的的主要是BitmapFactory.Options,通過options縮放比例的設置,來生成縮略圖:

2、通過Matrix進行更加靈活的縮放:這種方式主要是通過構建縮放矩陣和Bitmap.createBitmap方法來實現靈活縮放,寬和高縮放的比例可以不一致,而且通過Bitmap.createBitmap方法創建出來的是新的點陣圖,這個點陣圖可以是選取原圖的一部分,而不是對原圖進行整體縮放!類似於上傳頭像時,讓你在原圖上扣下來一塊的效果,控制非常靈活。
3、無損壓縮,無損壓縮是說圖片大小和清晰度看上去和原圖沒有什麼差別,但是確實size縮小了,這里縮小的原理是犧牲了解析度等其他直觀看不到的東西,看起來和原圖一樣,但是一放大就立馬失真了,不會和原圖一樣放大很多才會逐漸變得不清晰。無損壓縮後的圖片像素並不會減少,而Bitmap佔用內存的定義就是像素點占的內存,所以以Bitmap的方式載入到內存中時,和壓縮前佔用的內存是同樣大的,原來會oom的圖片,質量壓縮後同樣會oom;但是,質量壓縮後將流輸出到文件中,文件的size會大幅度減小,所以質量壓縮特別適合在 Android 端進行圖片上傳的時候進行圖片壓縮,既能保持上傳後的清晰度,又能減小size。另外質量壓縮不是可以無限縮小的,降低到一定程度,就算把quality設置的再小,size也不會再降低了。另外這種方式最好返回保存壓縮後的圖片保存的文件路徑,而不要直接返回Bitmap,示例就懶得改了。

一張圖片處理過程,建議先進行等比壓縮或者Matrix壓縮後,再進行質量壓縮,這樣組合使用,不管是生成縮略圖還是圖片上傳,效果都不錯

Ⅳ Android黑科技,圖片終極壓縮

一、支持自定義配置、不失真和批量處理

二、圖片上傳為什麼要壓縮
1、圖片伺服器空間限制,磁碟昂貴
2、網路不穩定,大文件需要斷點續傳
3、盡可能避免安卓OOM異常
4、後台約定的規則<200KB
5、需要上傳原圖的應用有醫院臨床項目、金融銀行

三、圖片壓縮流程
1、遞歸每張圖片
2、設置圖片格式 Bitmap.CompressFormat.JPG
png, jpg,webp
3、質量壓縮bitmap.compress(format,quality,baos)
由於png是無損壓縮,所以設置quality無效(不適合作為縮略圖)
采樣率壓縮BitmapFactory.Options.inSampleSize
縮小圖片解析度,減少所佔用磁碟空間和內存大小
縮放壓縮canvas.drawBitmap(bitmap, null,rectF,null)
減少圖片的像素,降低所佔用磁碟空間大小和內存大小,可用於緩存縮略圖
JNI調用JPEG庫
Android的圖片引擎使用的是閹割版的skia引擎,去掉了圖片壓縮中的哈夫曼演算法
4、像素修復
5、返回壓縮
6、完成壓縮

demo: https://github.com/ApeCold/Learn_Compress_Sample

參考:
Luban框架 https://github.com/Curzibn/Luban
缺點
1、當沒有設定壓縮路徑時,拋異常無閃退
2、源碼中,壓縮比率固定值60,無法修改
3、壓縮配置,參數不太適應真實項目需求
4、不能指定壓縮大小,比如100KB以內
https://github.com/zettsu/Compressor

Ⅵ android圖片壓縮避免OOM

簡單吹下牛:很多app都會要載入圖片,但是如果不壓縮圖片就很容易OOM,

個人看來OOM 出現原因總的來說分為兩種:

一種是內存溢出(好像在扯淡,OOM本身就是內存溢出)

另一種是:圖片過大,一個屏幕顯示不完全造成,似乎也是一。。 如有錯誤純屬扯淡;

為了避免上面的情況:載入圖片的時候可以進行壓縮,上傳的時候要可以進行壓縮,在圖片不可見的時候進行回收(onDetach()),再吹一句 用了fresco+壓縮之後載入圖片完全沒問題了。

一、質量壓縮方法:

privateBitmap compressImage(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);//質量壓縮方法,這里100表示不壓縮,把壓縮後的數據存放到baos中

intoptions =100;

while( baos.toByteArray().length /1024>100) {//循環判斷如果壓縮後圖片是否大於100kb,大於繼續壓縮

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這里壓縮options%,把壓縮後的數據存放到baos中

options -=10;//每次都減少10

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());//把壓縮後的數據baos存放到ByteArrayInputStream中

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream數據生成圖片

returnbitmap;

}

二、圖片按比例大小壓縮方法(根據Bitmap圖片壓縮)

privateBitmap comp(Bitmap image) {

ByteArrayOutputStream baos =newByteArrayOutputStream();

image.compress(Bitmap.CompressFormat.JPEG,100, baos);

if( baos.toByteArray().length /1024>1024) {//判斷如果圖片大於1M,進行壓縮避免在生成圖片(BitmapFactory.decodeStream)時溢出

baos.reset();//重置baos即清空baos

image.compress(Bitmap.CompressFormat.JPEG,50, baos);//這里壓縮50%,把壓縮後的數據存放到baos中

}

ByteArrayInputStream isBm =newByteArrayInputStream(baos.toByteArray());

BitmapFactory.Options newOpts =newBitmapFactory.Options();

//開始讀入圖片,此時把options.inJustDecodeBounds 設回true了

newOpts.inJustDecodeBounds =true;

Bitmap bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

newOpts.inJustDecodeBounds =false;

intw = newOpts.outWidth;

inth = newOpts.outHeight;

//現在主流手機比較多是800*480解析度,所以高和寬我們設置為

floathh = 800f;//這里設置高度為800f

floatww = 480f;//這里設置寬度為480f

//縮放比。由於是固定比例縮放,只用高或者寬其中一個數據進行計算即可

intbe =1;//be=1表示不縮放

if(w > h && w > ww) {//如果寬度大的話根據寬度固定大小縮放

be = (int) (newOpts.outWidth / ww);

}elseif(w < h && h > hh) {//如果高度高的話根據寬度固定大小縮放

be = (int) (newOpts.outHeight / hh);

}

if(be <=0)

be =1;

newOpts.inSampleSize = be;//設置縮放比例

//重新讀入圖片,注意此時已經把options.inJustDecodeBounds 設回false了

isBm =newByteArrayInputStream(baos.toByteArray());

bitmap = BitmapFactory.decodeStream(isBm,null, newOpts);

returncompressImage(bitmap);//壓縮好比例大小後再進行質量壓縮

}

Ⅶ 圖片壓縮那些事

我們在項目開發過程中,可能或多或少的都會有對圖片操作,而且一般情況在app當中涉及到內存泄露、或者apk體積增大等方面,絕大部分原因就是圖片的問題,要麼圖片體積比較大、或者一次載入圖片比較多等等,所以個人覺得,只要想對app瘦身、減小app體積、避免內存泄露等等這些問題,同時,為了避免OOM內存泄露,幾乎所有的app都會對大圖片進行壓縮的,這點是毋庸置疑的,所以說只要把圖片處理好,可以說就已經解決了絕大部分的問題,那麼這篇文章就來針對圖片壓縮的原因、常見圖片壓縮方法做一個簡單的總結。

文件和流的形式對圖片體積大小沒影響,也就是說,如果手機SD卡上的是100k,以流的形式讀到內存中也是100k,如果圖片以Bitmap形式存在,內存會瞬間增大;

文件形式:file.length()
流的形式:將圖片文件讀到 內存輸入流中,看它的byte數;
Bitmap:bitmap.getByteCount()

如果圖片是要上傳的,那麼 幾M大小肯定不行,所以就必須得壓縮;

如果圖片要顯示在android 設備上,ImageView最終是要載入bitmap對象的,所以就要考慮單個 Bitmap對象佔用多少內存;

bitmap內存大小 = 圖片長度 * 圖片寬度 * 單位像素佔用位元組數
bitmap常見有2種編碼方式,ARGB_8888、RGB——565,前者每個像素點是4byte(位元組),後者是2個byte(位元組),ARGB_8888比較常用。

1080 * 1920 * 4 = 7.9M

保持原圖長寬比例的壓縮,只是圖片變小,展示的還是原圖的所有內容,用的是BitmapFactory.Options,通過options設置縮放比例,生成縮略圖;
inSimpleSize(采樣率):
優點:效率較高,解析速度快;
缺點:inSimpleSize取值只能是 2的次方數,不能精確指定圖片大小;

寬高縮放比例可以不一致,通過Bitmap.createBitmap()方法創建出新的點陣圖,這個點陣圖可以選取圖片一部分,而不是整體壓縮,類似於QQ上傳頭像,讓你在圖片上選擇任何一塊 zoom的形式,控制非常靈活;

意思就是圖片大小、清晰度和原圖看上去沒什麼區別,但是大小縮小了,縮小原理就是犧牲了解析度等其他直觀看不到的東西,看上去和原圖一樣,但是放大立馬失真,不像原圖只有放大後才會不清晰

Ⅷ 說說在 Android 中如何壓縮圖片

目前存在兩種壓縮圖片方式:

而圖片有三種存在形式:

bigmap 在內存中的大小是按像素計算的,也就是width * height,所以如果需要在 Android 中顯示照片,那麼就必須進行按比例壓縮,避免因為內存消耗過大,導致 APP 退出。

是不是很簡單呀 O(∩_∩)O哈哈~

Ⅸ Android圖片壓縮-大小與質量壓縮以及圖片保存

一、前言:

2.質量壓縮
注意:

第二次壓縮之前都要先清空 baos.reset(); 再進行壓縮 image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
有時候我們採用質量壓縮沒有效果,有可能是每次壓縮的質量過小,所以我們可以嘗試修改壓縮質量(quality)是10;
quality壓縮機提示,0-100。0表示壓縮
小尺寸,100意味著最大質量的壓縮。一些
格式,如無損的PNG,將忽略質量設定;

3.混合方式壓縮

鏈接: https://www.jianshu.com/p/12835d5ebc72

閱讀全文

與android圖片壓縮oom相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:757
蘋果郵件無法連接伺服器地址 瀏覽:962
phpffmpeg轉碼 瀏覽:671
長沙好玩的解壓項目 瀏覽:144
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:736
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:302
PDF分析 瀏覽:484
h3c光纖全工半全工設置命令 瀏覽:143
公司法pdf下載 瀏覽:381
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:349
風翼app為什麼進不去了 瀏覽:778
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:150
伊克塞爾文檔怎麼進行加密 瀏覽:892
app轉賬是什麼 瀏覽:163