Android 性能優(yōu)化系列之bitmap圖片優(yōu)化_第1頁
Android 性能優(yōu)化系列之bitmap圖片優(yōu)化_第2頁
Android 性能優(yōu)化系列之bitmap圖片優(yōu)化_第3頁
Android 性能優(yōu)化系列之bitmap圖片優(yōu)化_第4頁
Android 性能優(yōu)化系列之bitmap圖片優(yōu)化_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第Android性能優(yōu)化系列之bitmap圖片優(yōu)化Android開發(fā)中,加載圖片過多、過大很容易引起OutOfMemoryError異常,即我們常見的內(nèi)存溢出。因為Android對單個應(yīng)用施加內(nèi)存限制,默認(rèn)分配的內(nèi)存只有幾M(具體視不同系統(tǒng)而定)。而載入的圖片如果是JPG之類的壓縮格式(JPG支持最高級別的壓縮,不過該壓縮是有損的),在內(nèi)存中展開會占用大量的內(nèi)存空間,也就容易形成內(nèi)存溢出。那么高效的加載Bitmap是很重要的事情。Bitmap在Android中指的是一張圖片,圖片的格式有.jpg.jpg.webp等常見的格式。

如何選擇圖片格式

一個原則:在保證圖片視覺不失真前提下,盡可能的縮小體積

Android目前常用的圖片格式有jpg,jpeg和webp

png:無損壓縮圖片格式,支持Alpha通道,Android切圖素材多采用此格式

jpeg:有損壓縮圖片格式,不支持背景透明,適用于照片等色彩豐富的大圖壓縮,不適合logo

webp:是一種同時提供了有損壓縮和無損壓縮的圖片格式,派生自視頻編碼格式VP8,從谷歌官網(wǎng)來看,無損webp平均比jpg小26%,有損的webp平均比jpeg小25%~34%,無損webp支持Alpha通道,有損webp在一定的條件下同樣支持,有損webp在Android4.0(API14)之后支持,無損和透明在Android4.3(API18)之后支持

采用webp能夠在保持圖片清晰度的情況下,可以有效減小圖片所占有的磁盤空間大小

圖片壓縮可以從三個方面去考慮:

質(zhì)量壓縮并不會改變圖片在內(nèi)存中的大小,僅僅會減小圖片所占用的磁盤空間的大小,因為質(zhì)量壓縮不會改變圖片的分辨率,而圖片在內(nèi)存中的大小是根據(jù)widthheight一個像素的所占用的字節(jié)數(shù)計算的,寬高沒變,在內(nèi)存中占用的大小自然不會變,質(zhì)量壓縮的原理是通過改變圖片的位深和透明度來減小圖片占用的磁盤空間大小,所以不適合作為縮略圖,可以用于想保持圖片質(zhì)量的同時減小圖片所占用的磁盤空間大小。另外,由于jpg是無損壓縮,所以設(shè)置quality無效,

*質(zhì)量壓縮

*@paramformat圖片格式j(luò)peg,png,webp

*@paramquality圖片的質(zhì)量,0-100,數(shù)值越小質(zhì)量越差

publicstaticvoidcompress(Bitmap.CompressFormatformat,intquality){

FilesdFile=Environment.getExternalStorageDirectory();

FileoriginFile=newFile(sdFile,originImg.jpg

BitmaporiginBitmap=BitmapFactory.decodeFile(originFile.getAbsolutePath());

ByteArrayOutputStreambos=newByteArrayOutputStream();

originBpress(format,quality,bos);

try{

FileOutputStreamfos=newFileOutputStream(newFile(sdFile,resultImg.jpg));

fos.write(bos.toByteArray());

fos.flush();

fos.close();

}catch(FileNotFoundExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

2.采樣率

采樣率壓縮是通過設(shè)置BitmapFactory.Options.inSampleSize,來減小圖片的分辨率,進(jìn)而減小圖片所占用的磁盤空間和內(nèi)存大小。

設(shè)置的inSampleSize會導(dǎo)致壓縮的圖片的寬高都為1/inSampleSize,整體大小變?yōu)樵紙D片的inSampleSize平方分之一,當(dāng)然,這些有些注意點:

inSampleSize小于等于1會按照1處理

inSampleSize只能設(shè)置為2的平方,不是2的平方則最終會減小到最近的2的平方數(shù),如設(shè)置7會按4進(jìn)行壓縮,設(shè)置15會按8進(jìn)行壓縮。

*@paraminSampleSize可以根據(jù)需求計算出合理的inSampleSize

publicstaticvoidcompress(intinSampleSize){

FilesdFile=Environment.getExternalStorageDirectory();

FileoriginFile=newFile(sdFile,originImg.jpg

BitmapFactory.Optionsoptions=newBitmapFactory.Options();

//設(shè)置此參數(shù)是僅僅讀取圖片的寬高到options中,不會將整張圖片讀到內(nèi)存中,防止oom

options.inJustDecodeBounds=true;

BitmapemptyBitmap=BitmapFactory.decodeFile(originFile.getAbsolutePath(),options);

options.inJustDecodeBounds=false;

options.inSampleSize=inSampleSize;

BitmapresultBitmap=BitmapFactory.decodeFile(originFile.getAbsolutePath(),options);

ByteArrayOutputStreambos=newByteArrayOutputStream();

resultBpress(Bitmap.CompressFormat.JPEG,100,bos);

try{

FileOutputStreamfos=newFileOutputStream(newFile(sdFile,resultImg.jpg));

fos.write(bos.toByteArray());

fos.flush();

fos.close();

}catch(FileNotFoundExceptione){

e.printStackTrace();

}catch(IOExceptione){

e.printStackTrace();

通過減少圖片的像素來降低圖片的磁盤空間大小和內(nèi)存大小,可以用于緩存縮略圖

*縮放bitmap

*@paramcontext

*@paramid

*@parammaxW

*@parammaxH

*@return

publicstaticBitmapresizeBitmap(Contextcontext,intid,intmaxW,intmaxH,booleanhasAlpha,Bitmapreusable){

Resourcesresources=context.getResources();

BitmapFactory.Optionsoptions=newBitmapFactory.Options();

//只解碼出outxxx參數(shù)比如寬、高

options.inJustDecodeBounds=true;

BitmapFactory.decodeResource(resources,id,options);

//根據(jù)寬、高進(jìn)行縮放

intw=options.outWidth;

inth=options.outHeight;

//設(shè)置縮放系數(shù)

options.inSampleSize=calcuteInSampleSize(w,h,maxW,maxH);

if(!hasAlpha){

options.inPreferredConfig=Bitmap.Config.RGB_565;

options.inJustDecodeBounds=false;

//設(shè)置成能復(fù)用

options.inMutable=true;

options.inBitmap=reusable;

returnBitmapFactory.decodeResource(resources,id,options);

*計算縮放系數(shù)

*@paramw

*@paramh

*@parammaxW

*@parammaxH

*@return縮放的系數(shù)

privatestaticintcalcuteInSampleSize(intw,inth,intmaxW,intmaxH){

intinSampleSize=1;

if(wmaxWhmaxH){

inSampleSize=2;

//循環(huán)使寬、高小于最大的寬、高

while(w/inSampleSizemaxWh/inSampleSizemaxH){

inSampleSize*=2;

returninSampleSize;

使用JPEG庫,在jni層使用哈夫曼算法去壓縮圖片

Android的圖片引擎使用的是閹割版的skia引擎,去掉了圖片壓縮中的哈夫曼算法

voidwrite_JPEG_file(uint8_t*data,intw,inth,jintq,constchar*path){

//3.1、創(chuàng)建jpeg壓縮對象

jpeg_compress_structjcs;

//錯誤回調(diào)

jpeg_error_mgrerror;

jcs.err=jpeg_std_error(error);

//創(chuàng)建壓縮對象

jpeg_create_compress(jcs);

//3.2、指定存儲文件writebinary

FILE*f=fopen(path,wb

jpeg_stdio_dest(jcs,f);

//3.3、設(shè)置壓縮參數(shù)

jcs.image_width=w;

jcs.image_height=h;

//bgr

jcs.input_components=3;

jcs.in_color_space=JCS_RGB;

jpeg_set_defaults(jcs);

//開啟哈夫曼功能

jcs.optimize_coding=true;

jpeg_set_quality(jcs,q,1);

//3.4、開始壓縮

jpeg_start_compress(jcs,1);

//3.5、循環(huán)寫入每一行數(shù)據(jù)

introw_stride=w*3;//一行的字節(jié)數(shù)

JSAMPROWrow[1];

while(jcs.next_scanlinejcs.image_height){

//取一行數(shù)據(jù)

uint8_t*pixels=data+jcs.next_scanline*row_stride;

row[0]=pixels;

jpeg_write_scanlines(jcs,row,1);

//3.6、壓縮完成

jpeg_finish_compress(jcs);

//3.7、釋放jpeg對象

fclose(f);

jpeg_destroy_compress(jcs);

因為涉及到j(luò)ni部分,暫時只貼一下使用的代碼,后面會寫一些jni部分的博客與大家分享。

設(shè)置圖片可以復(fù)用

圖片復(fù)用主要就是指的復(fù)用內(nèi)存塊,不需要在重新給這個bitmap申請一塊新的內(nèi)存,避免了一次內(nèi)存的分配和回收,從而改善了運行效率。

需要注意的是inBitmap只能在3.0以后使用。2.3上,bitmap的數(shù)據(jù)是存儲在native的內(nèi)存區(qū)域,并不是在Dalvik的內(nèi)存堆上。

使用inBitmap,在4.4之前,只能重用相同大小的bitmap的內(nèi)存區(qū)域,而4.4之后你可以重用任何bitmap的內(nèi)存區(qū)域,只要這塊內(nèi)存比將要分配內(nèi)存的bitmap大就可以。這里最好的方法就是使用LRUCache來緩存bitmap,后面來了新的bitmap,可以從cache中按照api版本找到最適合重用的bitmap,來重用它的內(nèi)存區(qū)域。

BitmapFactory.Optionsoptions=newBitmapFactory.Options();

//只解碼出outxxx參數(shù)比如寬、高

options.inJustDecodeBounds=true;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論