Android Bitmap壓縮方法的選擇詳解
剛剛修改Bug碰到了一個問題,先描述一下問題。
1.測試說分享文章到微信失敗,QQ成功。
定位到微信分享接口。
2.分享其它文章到微信成功。
接口有問題!差點(diǎn)就找接口了,還好沒
3.斷點(diǎn)微信分享,發(fā)現(xiàn)突然壓縮失敗。
代碼寫法問題,下面會分解
4.找到原因,微信對分享縮略圖大小有32k的限制,代碼是對文章的第一張圖片進(jìn)行壓縮,圖片太大,壓縮代碼也有問題。
開始解決問題
這里有兩種解決方法:
1.接口提供文章對應(yīng)的分享內(nèi)容,在編輯人員編輯文章的時候就對這些數(shù)據(jù)進(jìn)行了限制。
{
"title":"how to begain Android?",
"content":"do it, do it, do it",
"picture":"http://192.168.0.1/pic/2015/09/02/share_thumb.jpg"
...
...
}
picture字段是<32K的縮略圖。
ps:就我現(xiàn)在的水平來說,個人覺得這種是最好的,不是說Android省事,而是對于今后的擴(kuò)展和整體項(xiàng)目的擴(kuò)展規(guī)劃來說都是比較好的,當(dāng)然,水平有限,也許我看得還不夠遠(yuǎn),希望指教。
2.對獲取的文章圖片進(jìn)行壓縮。
當(dāng)前項(xiàng)目無法對接口進(jìn)行修改(駱駝太大了),所以只能對圖片進(jìn)行壓縮了,這就談到上面的坑了。先看原來寫的壓縮代碼:
----可能出錯的代碼----
int options = 100;
ByteArrayOutputStream outputs = new ByteArrayOutputStream();
oBitmap.compress(Bitmap.CompressFormat.JPEG, options, outputs); //
while ( outputs.toByteArray().length / 1024 > 32 ) {
outputs.reset();
oBitmap.compress(Bitmap.CompressFormat.JPEG, options, outputs);
options -= 10 ;
}
ByteArrayInputStream inputs = new ByteArrayInputStream(outputs.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(inputs, null , null );
這里用了bitmap的compress()方法進(jìn)行了所謂的'質(zhì)量壓縮',控制參數(shù)就是options的值,但是出問題的地方也就是這個options的值,當(dāng)圖片非常大的時候,即使options為0的時候,圖片還是大于32K,這個時候在while中option就為負(fù)數(shù)了,再進(jìn)行compress()操作就會拋出throw new IllegalArgumentException("quality must be 0..100");的錯誤。
原因:
使用compress()方法的options值進(jìn)行壓縮的方法是不會丟失像素的,只是通過修改圖片的其它比如透明度等屬性,使得圖片大小變化而已,所以它就無法無限壓縮,到達(dá)一個值之后就不會繼續(xù)變小了。
解決:
第一時間想到的是進(jìn)行質(zhì)量壓縮后,當(dāng)options為0的時候,還是大于32K的話,就進(jìn)行采樣率壓縮。
BitmapFactory.Options newOpts = new BitmapFactory.Options(); newOpts.inSampleSize = 2; bitmap = BitmapFactory.decodeFile(picturePath, newOpts);
每次判斷bitmap的大小,對BitmapFactory.Options的inSampleSize進(jìn)行+1或者-1(不能小于1)操作就好。但是inSampleSize的值為int類型,當(dāng)圖片很大的時候,1/2, 1/3, 1/4的差距還是有些大。所以只能放棄,最后采用了縮放的方法,先上代碼:
public static byte[] WeChatBitmapToByteArray(Bitmap bmp, boolean needRecycle) {
// 首先進(jìn)行一次大范圍的壓縮
ByteArrayOutputStream output = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, output);
float zoom = (float)Math.sqrt(32 * 1024 / (float)output.toByteArray().length); //獲取縮放比例
// 設(shè)置矩陣數(shù)據(jù)
Matrix matrix = new Matrix();
matrix.setScale(zoom, zoom);
// 根據(jù)矩陣數(shù)據(jù)進(jìn)行新bitmap的創(chuàng)建
Bitmap resultBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
output.reset();
resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
// 如果進(jìn)行了上面的壓縮后,依舊大于32K,就進(jìn)行小范圍的微調(diào)壓縮
while(output.toByteArray().length > 32 * 1024){
matrix.setScale(0.9f, 0.9f);//每次縮小 1/10
resultBitmap = Bitmap.createBitmap(
resultBitmap, 0, 0,
resultBitmap.getWidth(), resultBitmap.getHeight(), matrix,true);
output.reset();
resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
}
return result;
}
至此,暫時補(bǔ)上了這個一開始不規(guī)范導(dǎo)致的問題。當(dāng)然,以上的解釋都是從書本和我大互聯(lián)網(wǎng)中獲取的方法,我進(jìn)行了一些整合,如果你也遇到的這個問題,也有幸這篇文章被你看到,能幫到一二,就是我的本意了。
通過此文希望能幫助到有需要的同學(xué),謝謝大家對本站的支持!
相關(guān)文章
Android IPC機(jī)制ACtivity綁定Service通信代碼實(shí)例
這篇文章主要介紹了Android IPC機(jī)制ACtivity綁定Service通信代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
用xutils3.0進(jìn)行下載項(xiàng)目更新
這篇文章主要介紹了用xutils3.0進(jìn)行下載項(xiàng)目更新的相關(guān)資料,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08
使用Android Studio 開發(fā)自己的SDK教程
很多時候我們要將自己開發(fā)一個類庫打包成jar包以供他調(diào)用,這個jar包也叫你自己的SDK或者叫l(wèi)ibrary。android studio生成jar包的方法與eclipse有所不同。在studio中l(wèi)ibrary其實(shí)是module的概念。2017-10-10
Flutter實(shí)現(xiàn)倒計(jì)時秒數(shù)轉(zhuǎn)時分秒然后倒計(jì)時功能
有一個需求,需要在頁面進(jìn)行顯示倒計(jì)時,倒計(jì)時結(jié)束后,做相應(yīng)的邏輯處理,這篇文章主要介紹了Flutter實(shí)現(xiàn)倒計(jì)時功能,秒數(shù)轉(zhuǎn)時分秒,然后倒計(jì)時,需要的朋友可以參考下2023-08-08
詳解Android .9.png “點(diǎn)九”圖片的使用
這篇文章主要為大家詳細(xì)介紹了Android .9.png “點(diǎn)九”圖片的使用方法,感興趣的小伙伴們可以參考一下2016-09-09
淺談Android Studio 4.1 更新內(nèi)容
這篇文章主要介紹了淺談Android Studio 4.1 更新內(nèi)容,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Android MotionEvent中g(shù)etX()和getRawX()的區(qū)別實(shí)例詳解
這篇文章主要介紹了Android MotionEvent中g(shù)etX()和getRawX()的區(qū)別實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03
android 監(jiān)聽網(wǎng)絡(luò)狀態(tài)的變化及實(shí)戰(zhàn)的示例代碼
本篇文章主要介紹了android 監(jiān)聽網(wǎng)絡(luò)狀態(tài)的變化及實(shí)戰(zhàn)的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01

