Android Bitmap壓縮方法的選擇詳解
剛剛修改Bug碰到了一個(gè)問(wèn)題,先描述一下問(wèn)題。
1.測(cè)試說(shuō)分享文章到微信失敗,QQ成功。
定位到微信分享接口。
2.分享其它文章到微信成功。
接口有問(wèn)題!差點(diǎn)就找接口了,還好沒(méi)
3.斷點(diǎn)微信分享,發(fā)現(xiàn)突然壓縮失敗。
代碼寫(xiě)法問(wèn)題,下面會(huì)分解
4.找到原因,微信對(duì)分享縮略圖大小有32k的限制,代碼是對(duì)文章的第一張圖片進(jìn)行壓縮,圖片太大,壓縮代碼也有問(wèn)題。
開(kāi)始解決問(wèn)題
這里有兩種解決方法:
1.接口提供文章對(duì)應(yīng)的分享內(nèi)容,在編輯人員編輯文章的時(shí)候就對(duì)這些數(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)在的水平來(lái)說(shuō),個(gè)人覺(jué)得這種是最好的,不是說(shuō)Android省事,而是對(duì)于今后的擴(kuò)展和整體項(xiàng)目的擴(kuò)展規(guī)劃來(lái)說(shuō)都是比較好的,當(dāng)然,水平有限,也許我看得還不夠遠(yuǎn),希望指教。
2.對(duì)獲取的文章圖片進(jìn)行壓縮。
當(dāng)前項(xiàng)目無(wú)法對(duì)接口進(jìn)行修改(駱駝太大了),所以只能對(duì)圖片進(jìn)行壓縮了,這就談到上面的坑了。先看原來(lái)寫(xiě)的壓縮代碼:
----可能出錯(cuò)的代碼----
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的值,但是出問(wèn)題的地方也就是這個(gè)options的值,當(dāng)圖片非常大的時(shí)候,即使options為0的時(shí)候,圖片還是大于32K,這個(gè)時(shí)候在while中option就為負(fù)數(shù)了,再進(jìn)行compress()操作就會(huì)拋出throw new IllegalArgumentException("quality must be 0..100");的錯(cuò)誤。
原因:
使用compress()方法的options值進(jìn)行壓縮的方法是不會(huì)丟失像素的,只是通過(guò)修改圖片的其它比如透明度等屬性,使得圖片大小變化而已,所以它就無(wú)法無(wú)限壓縮,到達(dá)一個(gè)值之后就不會(huì)繼續(xù)變小了。
解決:
第一時(shí)間想到的是進(jìn)行質(zhì)量壓縮后,當(dāng)options為0的時(shí)候,還是大于32K的話,就進(jìn)行采樣率壓縮。
BitmapFactory.Options newOpts = new BitmapFactory.Options(); newOpts.inSampleSize = 2; bitmap = BitmapFactory.decodeFile(picturePath, newOpts);
每次判斷bitmap的大小,對(duì)BitmapFactory.Options的inSampleSize進(jìn)行+1或者-1(不能小于1)操作就好。但是inSampleSize的值為int類(lèi)型,當(dāng)圖片很大的時(shí)候,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; }
至此,暫時(shí)補(bǔ)上了這個(gè)一開(kāi)始不規(guī)范導(dǎo)致的問(wèn)題。當(dāng)然,以上的解釋都是從書(shū)本和我大互聯(lián)網(wǎng)中獲取的方法,我進(jìn)行了一些整合,如果你也遇到的這個(gè)問(wèn)題,也有幸這篇文章被你看到,能幫到一二,就是我的本意了。
通過(guò)此文希望能幫助到有需要的同學(xué),謝謝大家對(duì)本站的支持!
相關(guān)文章
Android利用Sensor(傳感器)實(shí)現(xiàn)指南針小功能
這篇文章主要為大家詳細(xì)介紹了Android利用Sensor(傳感器)實(shí)現(xiàn)指南針小功能的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02AndroidStudio項(xiàng)目制作倒計(jì)時(shí)模塊的方法
本篇文章主要介紹了AndroidStudio項(xiàng)目制作倒計(jì)時(shí)模塊的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-04-04Android Studio用genymotion運(yùn)行后小圖標(biāo)無(wú)法顯示問(wèn)題
這篇文章主要介紹了Android Studio用genymotion運(yùn)行后小圖標(biāo)無(wú)法顯示的問(wèn)題,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Android獲取點(diǎn)擊屏幕的位置坐標(biāo)
這篇文章主要為大家詳細(xì)介紹了Android獲取點(diǎn)擊屏幕的位置坐標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android使用Intent隱式實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
這篇文章主要為大家詳細(xì)介紹了Android使用Intent隱式來(lái)實(shí)現(xiàn)向上跳轉(zhuǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08Android編程基礎(chǔ)之簡(jiǎn)單Button事件響應(yīng)綜合提示控件Toast應(yīng)用示例
這篇文章主要介紹了Android編程基礎(chǔ)之簡(jiǎn)單Button事件響應(yīng)綜合提示控件Toast應(yīng)用,結(jié)合實(shí)例形式分析了Button事件響應(yīng)與Toast提醒的相關(guān)操作技巧,需要的朋友可以參考下2016-10-10Android打賞功能實(shí)現(xiàn)代碼(支付寶轉(zhuǎn)賬)
這篇文章主要介紹了Android打賞功能之支付寶轉(zhuǎn)賬 ,需要的朋友可以參考下2017-12-12Android開(kāi)發(fā)注解排列組合出啟動(dòng)任務(wù)ksp
這篇文章主要為大家介紹了Android開(kāi)發(fā)注解排列組合出啟動(dòng)任務(wù)ksp示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android中g(shù)oogle Zxing實(shí)現(xiàn)二維碼與條形碼掃描
這篇文章主要介紹了Android中g(shù)oogle Zxing實(shí)現(xiàn)二維碼與條形碼掃描的相關(guān)資料,需要的朋友可以參考下2017-05-05