寫(xiě)文章的目的
- 靜下心來(lái)學(xué)習(xí)
- 知識(shí)點(diǎn)的積累
- 總結(jié)胞锰,做筆記
導(dǎo)讀
解決上一篇留下的問(wèn)題:
獲取了這么大的圖片并顯示,內(nèi)存肯定消耗很大兢榨,有什么優(yōu)化嗎嗅榕?
需求
調(diào)用系統(tǒng)相機(jī)捕獲圖片,并合理顯示圖片吵聪。
代碼解構(gòu)
-
調(diào)用系統(tǒng)相機(jī)捕獲圖片
前面幾篇已解決凌那,此處不表。 -
合理顯示圖片
:主要是內(nèi)存上優(yōu)化吟逝。
1.回顧一下帽蝶,上一篇中我們是如何加載拍照后的圖片:直接通過(guò)BitmapFactory
去解碼圖片路徑。
Bitmap bitmap = BitmapFactory.decodeFile(mImageFilePath);
Log.i("--bitmap1--", bitmap1.getHeight() + "<===>" + bitmap1.getWidth());
//I/--bitmap1--: 4608<===>3456
imageView.setImageBitmap(bitmap);
2.快速加載大圖块攒,獲取采樣后的圖片励稳。decodeFile()
還有一個(gè)重載方法佃乘,多一個(gè)參數(shù)BitmapFactory.Options
,通過(guò)Options.inSampleSize
的值去設(shè)置采樣比例驹尼。比如:Options.inSampleSize = 8
表示獲取后的bitmap寬高均縮小了8倍趣避,面積縮小了8*8倍。
//1.快速加載大圖扶欣,獲取采樣后的圖片 1/8比例 對(duì)比打印:其實(shí)是寬高都縮小8倍
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap2 = BitmapFactory.decodeFile(mImageFilePath, options);
Log.i("--bitmap2--", bitmap2.getHeight() + "<===>" + bitmap2.getWidth());
//I/--bitmap2--: 576<===>432
imageView.setImageBitmap(bitmap2);
3.了解了簡(jiǎn)單的采樣方法后千扶,接下來(lái)我們按照具體環(huán)境配置比例料祠,盡可能地填充顯示范圍:比如顯示屏寬高。
大部分應(yīng)該是此種需求澎羞,需要去計(jì)算采樣的比例髓绽。這個(gè)時(shí)候我們需要
Options
的另一個(gè)屬性inJustDecodeBounds
:如果設(shè)置為true,解碼器會(huì)返回null妆绞,不會(huì)返回bitmap顺呕,但是BitmapFactory.Options.outxxx屬性會(huì)被設(shè)置值,運(yùn)行解碼器去查詢bitmap括饶,不會(huì)將bitmap加載進(jìn)內(nèi)存株茶。
//2.按照具體環(huán)境配置比例赫编,盡可能地填充顯示范圍:比如顯示屏寬高
//接收屏幕寬高 x==width;y==height
Point disPlayer = new Point();
//獲取屏幕寬高
getWindowManager().getDefaultDisplay().getSize(disPlayer);
//創(chuàng)建解碼圖像的Options
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
//inJustDecodeBounds如果設(shè)置為true点弯,解碼器會(huì)返回null,不會(huì)返回bitmap葛家,
// 但是BitmapFactory.Options.outxxx屬性會(huì)被設(shè)置值技羔,運(yùn)行解碼器去查詢bitmap僵闯,不會(huì)將bitmap加載進(jìn)內(nèi)存。
bitmapOptions.inJustDecodeBounds = true;
//讓解碼器去查詢?cè)搱D片(返回bitmap為null藤滥,但是給BitmapFactory.Options.outxxx屬性設(shè)置值)
BitmapFactory.decodeFile(mImageFilePath, bitmapOptions);
//顯示屏寬高與圖片寬高對(duì)比
//屏幕高 disPlayer.y
//屏幕寬disPlayer.x
//圖片高 bitmapOptions.outHeight
//圖片寬 bitmapOptions.outWidth
//高之比
int heightRatio = (int) Math.ceil(bitmapOptions.outHeight / ((float) disPlayer.y));
//寬之比
int widthRatio = (int) Math.ceil(bitmapOptions.outWidth / ((float) disPlayer.x));
//解釋下Math.round(),Math.ceil(),Math.floor()
//1鳖粟,Math.round():round是附近的意思,取四舍五入
//2拙绊,Math.ceil():ceil是天花板的意思向图,取上限值
//3,Math.floor():floor是地板的意思标沪,取下限值
//比如我打印的屏幕高: 2034张漂;圖片高: 4608;比值大概是2.+谨娜,ceil之后的值就是3航攒。
Log.i("--屏幕高 ", disPlayer.y + "");
Log.i("--屏幕寬 ", disPlayer.x + "");
Log.i("--圖片高 ", bitmapOptions.outHeight + "");
Log.i("--圖片寬 ", bitmapOptions.outWidth + "");
Log.i("--高之比", heightRatio + "");
Log.i("--寬之比", widthRatio + "");
//I/--屏幕高: 2034
//I/--屏幕寬: 1080
//I/--圖片高: 4608
//I/--圖片寬: 3456
//I/--高之比: 3
//I/--寬之比: 4
if (heightRatio > 1 && widthRatio > 1) {
//兩個(gè)比例都大于1
//采樣的比例取heightRatio和widthRatio中的最大值
bitmapOptions.inSampleSize = Math.max(heightRatio, widthRatio);
}
//設(shè)置為false取解碼圖片
bitmapOptions.inJustDecodeBounds = false;
//獲取縮小之后的圖片
Bitmap bitmap = BitmapFactory.decodeFile(mImageFilePath, bitmapOptions);
imageView.setImageBitmap(bitmap);
Log.i("--縮小后寬:",bitmap.getWidth()+"");
Log.i("--縮小后高:",bitmap.getHeight()+"");
//I/--縮小后寬:: 864
//I/--縮小后高:: 1152
4.結(jié)果顯示。(根據(jù)屏幕寬高采樣.jpg)(直接縮小8倍采樣.jpg)
總結(jié)
- 該篇文章解決的問(wèn)題:減少顯示圖片時(shí)的內(nèi)存消耗
- 兩個(gè)重載函數(shù)
BitmapFactory.decodeFile(String pathName, Options opts)
和BitmapFactory.decodeFile(String pathName)
-
Options
中兩個(gè)重要的屬性inSampleSize
采樣比例和inJustDecodeBounds
趴梢。
代碼樣例
1.源碼地址
2.在上一篇的代碼基礎(chǔ)上修改onActivityResult()
即可漠畜。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
if (requestCode == IMAGE_RESULT) {
//這里不能通過(guò)Intent對(duì)象去獲取"data"币他,
// 因?yàn)樵诖蜷_(kāi)相機(jī)時(shí)已經(jīng)通過(guò)MediaStore.EXTRA_OUTPUT告訴相機(jī):你把圖片放在我傳給你的Uri中
//所以可以直接通過(guò)BitmapFactory在存儲(chǔ)路徑中獲取圖片
/*Bitmap bitmap1 = BitmapFactory.decodeFile(mImageFilePath);
Log.i("--bitmap1--", bitmap1.getHeight() + "<===>" + bitmap1.getWidth());
//I/--bitmap1--: 4608<===>3456*/
/* //1.快速加載大圖,獲取采樣后的圖片 1/8比例 對(duì)比打鱼灸:其實(shí)是寬高都縮小8倍
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap2 = BitmapFactory.decodeFile(mImageFilePath, options);
Log.i("--bitmap2--", bitmap2.getHeight() + "<===>" + bitmap2.getWidth());
//I/--bitmap2--: 576<===>432
imageView.setImageBitmap(bitmap2);*/
//2.按照具體環(huán)境配置比例蝴悉,盡可能地填充顯示范圍:比如顯示屏寬高
//接收屏幕寬高 x==width;y==height
Point disPlayer = new Point();
//獲取屏幕寬高
getWindowManager().getDefaultDisplay().getSize(disPlayer);
//創(chuàng)建解碼圖像的Options
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
//inJustDecodeBounds如果設(shè)置為true,解碼器會(huì)返回null瘾敢,不會(huì)返回bitmap拍冠,
// 但是BitmapFactory.Options.outxxx屬性會(huì)被設(shè)置值,運(yùn)行解碼器去查詢bitmap簇抵,不會(huì)將bitmap加載進(jìn)內(nèi)存庆杜。
bitmapOptions.inJustDecodeBounds = true;
//讓解碼器去查詢?cè)搱D片(返回bitmap為null,但是給BitmapFactory.Options.outxxx屬性設(shè)置值)
BitmapFactory.decodeFile(mImageFilePath, bitmapOptions);
//顯示屏寬高與圖片寬高對(duì)比
//屏幕高 disPlayer.y
//屏幕寬disPlayer.x
//圖片高 bitmapOptions.outHeight
//圖片寬 bitmapOptions.outWidth
//高之比
int heightRatio = (int) Math.ceil(bitmapOptions.outHeight / ((float) disPlayer.y));
//寬之比
int widthRatio = (int) Math.ceil(bitmapOptions.outWidth / ((float) disPlayer.x));
//解釋下Math.round(),Math.ceil(),Math.floor()
//1碟摆,Math.round():round是附近的意思晃财,取四舍五入
//2,Math.ceil():ceil是天花板的意思典蜕,取上限值
//3断盛,Math.floor():floor是地板的意思,取下限值
//比如我打印的屏幕高: 2034愉舔;圖片高: 4608钢猛;比值大概是2.+,ceil之后的值就是3轩缤。
Log.i("--屏幕高 ", disPlayer.y + "");
Log.i("--屏幕寬 ", disPlayer.x + "");
Log.i("--圖片高 ", bitmapOptions.outHeight + "");
Log.i("--圖片寬 ", bitmapOptions.outWidth + "");
Log.i("--高之比", heightRatio + "");
Log.i("--寬之比", widthRatio + "");
//I/--屏幕高: 2034
//I/--屏幕寬: 1080
//I/--圖片高: 4608
//I/--圖片寬: 3456
//I/--高之比: 3
//I/--寬之比: 4
if (heightRatio > 1 && widthRatio > 1) {
//兩個(gè)比例都大于1
//采樣的比例取heightRatio和widthRatio中的最大值
bitmapOptions.inSampleSize = Math.max(heightRatio, widthRatio);
}
//設(shè)置為false取解碼圖片
bitmapOptions.inJustDecodeBounds = false;
//獲取縮小之后的圖片
Bitmap bitmap = BitmapFactory.decodeFile(mImageFilePath, bitmapOptions);
imageView.setImageBitmap(bitmap);
Log.i("--縮小后寬:",bitmap.getWidth()+"");
Log.i("--縮小后高:",bitmap.getHeight()+"");
//I/--縮小后寬:: 864
//I/--縮小后高:: 1152
}
}