簡(jiǎn)單吹下牛:很多app都會(huì)要加載圖片,但是如果不壓縮圖片就很容易OOM,
目前成都創(chuàng)新互聯(lián)公司已為近千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、網(wǎng)站托管、服務(wù)器租用、企業(yè)網(wǎng)站設(shè)計(jì)、南充網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
個(gè)人看來(lái)OOM 出現(xiàn)原因總的來(lái)說(shuō)分為兩種:
一種是內(nèi)存溢出(好像在扯淡,OOM本身就是內(nèi)存溢出)
另一種是:圖片過(guò)大,一個(gè)屏幕顯示不完全造成,似乎也是一。。 如有錯(cuò)誤純屬扯淡;
為了避免上面的情況:加載圖片的時(shí)候可以進(jìn)行壓縮,上傳的時(shí)候要可以進(jìn)行壓縮,在圖片不可見(jiàn)的時(shí)候進(jìn)行回收(onDetach()),再吹一句 用了fresco+壓縮之后加載圖片完全沒(méi)問(wèn)題了。
一、質(zhì)量壓縮方法:
privateBitmap compressImage(Bitmap image) {
ByteArrayOutputStream?baos?=newByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,100,?baos);//質(zhì)量壓縮方法,這里100表示不壓縮,把壓縮后的數(shù)據(jù)存放到baos中
intoptions?=100;
while(?baos.toByteArray().length?/1024100)?{//循環(huán)判斷如果壓縮后圖片是否大于100kb,大于繼續(xù)壓縮
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG,?options,?baos);//這里壓縮options%,把壓縮后的數(shù)據(jù)存放到baos中
options?-=10;//每次都減少10
}
ByteArrayInputStream?isBm?=newByteArrayInputStream(baos.toByteArray());//把壓縮后的數(shù)據(jù)baos存放到ByteArrayInputStream中
Bitmap?bitmap?=?BitmapFactory.decodeStream(isBm,null,null);//把ByteArrayInputStream數(shù)據(jù)生成圖片
returnbitmap;
}
二、圖片按比例大小壓縮方法(根據(jù)Bitmap圖片壓縮)
privateBitmap comp(Bitmap image) {
ByteArrayOutputStream?baos?=newByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,100,?baos);
if(?baos.toByteArray().length?/10241024)?{//判斷如果圖片大于1M,進(jìn)行壓縮避免在生成圖片(BitmapFactory.decodeStream)時(shí)溢出
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG,50,?baos);//這里壓縮50%,把壓縮后的數(shù)據(jù)存放到baos中
}
ByteArrayInputStream?isBm?=newByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options?newOpts?=newBitmapFactory.Options();
//開(kāi)始讀入圖片,此時(shí)把options.inJustDecodeBounds?設(shè)回true了
newOpts.inJustDecodeBounds?=true;
Bitmap?bitmap?=?BitmapFactory.decodeStream(isBm,null,?newOpts);
newOpts.inJustDecodeBounds?=false;
intw?=?newOpts.outWidth;
inth?=?newOpts.outHeight;
//現(xiàn)在主流手機(jī)比較多是800*480分辨率,所以高和寬我們?cè)O(shè)置為
floathh?=?800f;//這里設(shè)置高度為800f
floatww?=?480f;//這里設(shè)置寬度為480f
//縮放比。由于是固定比例縮放,只用高或者寬其中一個(gè)數(shù)據(jù)進(jìn)行計(jì)算即可
intbe?=1;//be=1表示不縮放
if(w??h??w??ww)?{//如果寬度大的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outWidth?/?ww);
}elseif(w??h??h??hh)?{//如果高度高的話根據(jù)寬度固定大小縮放
be?=?(int)?(newOpts.outHeight?/?hh);
}
if(be?=0)
be?=1;
newOpts.inSampleSize?=?be;//設(shè)置縮放比例
//重新讀入圖片,注意此時(shí)已經(jīng)把options.inJustDecodeBounds?設(shè)回false了
isBm?=newByteArrayInputStream(baos.toByteArray());
bitmap?=?BitmapFactory.decodeStream(isBm,null,?newOpts);
returncompressImage(bitmap);//壓縮好比例大小后再進(jìn)行質(zhì)量壓縮
}
目前存在兩種壓縮圖片方式:
而圖片有三種存在形式:
bigmap 在內(nèi)存中的大小是按像素計(jì)算的,也就是width * height,所以如果需要在 Android 中顯示照片,那么就必須進(jìn)行按比例壓縮,避免因?yàn)閮?nèi)存消耗過(guò)大,導(dǎo)致 APP 退出。
是不是很簡(jiǎn)單呀 O(∩_∩)O哈哈~
一、前言:
2.質(zhì)量壓縮
注意:
第二次壓縮之前都要先清空 baos.reset(); 再進(jìn)行壓縮 image.compress(Bitmap.CompressFormat.JPEG, quality, baos);
有時(shí)候我們采用質(zhì)量壓縮沒(méi)有效果,有可能是每次壓縮的質(zhì)量過(guò)小,所以我們可以嘗試修改壓縮質(zhì)量(quality)是10;
quality壓縮機(jī)提示,0-100。0表示壓縮
小尺寸,100意味著最大質(zhì)量的壓縮。一些
格式,如無(wú)損的PNG,將忽略質(zhì)量設(shè)定;
3.混合方式壓縮
鏈接:
一、支持自定義配置、不失真和批量處理
二、圖片上傳為什么要壓縮
1、圖片服務(wù)器空間限制,磁盤昂貴
2、網(wǎng)絡(luò)不穩(wěn)定,大文件需要斷點(diǎn)續(xù)傳
3、盡可能避免安卓OOM異常
4、后臺(tái)約定的規(guī)則200KB
5、需要上傳原圖的應(yīng)用有醫(yī)院臨床項(xiàng)目、金融銀行
三、圖片壓縮流程
1、遞歸每張圖片
2、設(shè)置圖片格式 Bitmap.CompressFormat.JPG
png, jpg,webp
3、質(zhì)量壓縮bitmap.compress(format,quality,baos)
由于png是無(wú)損壓縮,所以設(shè)置quality無(wú)效(不適合作為縮略圖)
采樣率壓縮BitmapFactory.Options.inSampleSize
縮小圖片分辨率,減少所占用磁盤空間和內(nèi)存大小
縮放壓縮canvas.drawBitmap(bitmap, null,rectF,null)
減少圖片的像素,降低所占用磁盤空間大小和內(nèi)存大小,可用于緩存縮略圖
JNI調(diào)用JPEG庫(kù)
Android的圖片引擎使用的是閹割版的skia引擎,去掉了圖片壓縮中的哈夫曼算法
4、像素修復(fù)
5、返回壓縮
6、完成壓縮
demo:
參考:
Luban框架
缺點(diǎn)
1、當(dāng)沒(méi)有設(shè)定壓縮路徑時(shí),拋異常無(wú)閃退
2、源碼中,壓縮比率固定值60,無(wú)法修改
3、壓縮配置,參數(shù)不太適應(yīng)真實(shí)項(xiàng)目需求
4、不能指定壓縮大小,比如100KB以內(nèi)