原文鏈接:微信分享圖片壓縮問題解決方案 作者:李青
概述 在進(jìn)行微信分享時,遇到微信分享失敗的情況,微信分享對于圖片的大小有32k的限制,如果大于的話就會導(dǎo)致失敗。所以對于圖片的壓縮進(jìn)行了調(diào)研,最后得出如下解決方案:
1、統(tǒng)一了圖片的質(zhì)量參數(shù)為RGB_565; 問題背景在某些頁面調(diào)起微信分享時會直接返回失敗,但并不是所有的頁面都會失敗,所以排除是微信分享API的問題。 術(shù)語解釋
問題分析private void sendReq(IWXAPI iwxapi, BaseReq req) { boolean result = iwxapi.sendReq(req); if(!result) { this.mCallBack.onShareError(this.mActivity, ""); this.mActivity.finish(); } }
由分析可知以上result返回false,在這里是將分享的數(shù)據(jù)傳入分享的API,所以猜測這里應(yīng)該是參數(shù)傳入有誤,下面是在官網(wǎng)上查看的常見問題(雖然結(jié)果返回true,但還是具有參考價值的信息),我們可以看到第三條,檢查發(fā)送時的縮略圖大小是否超過32K,所以微信分享對于圖片的大小是有限制的,重新?lián)Q了一張小點的圖,最后分享成功了。
目前的分享流程
從以上流程可以看出來,圖片是經(jīng)過了兩次壓縮,為什么最后還會有超出大小的情況呢?下面我們來分析一下具體的壓縮過程是如何實現(xiàn)的。 /** * 圖片壓縮比例計算 * * @param options BitmapFactory.Options * @param minSideLength 小邊長,單位為像素,如果為-1,則不按照邊來壓縮圖片 * @param maxNumOfPixels 這張片圖片最大像素值,單位為byte,如100*1024 * @return 壓縮比例,必須為2的次冪 */ public static int computeSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) { int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels); int roundedSize; if (initialSize <= 8) { roundedSize = 1; while (roundedSize < initialSize) { roundedSize <<= 1; } } else { roundedSize = (initialSize + 7) / 8 * 8; } return roundedSize; } /** * 計算圖片的壓縮比例,用于圖片壓縮 * @param options BitmapFactory.Options * @param minSideLength 小邊長,單位為像素,如果為-1,則不按照邊來壓縮圖片 * @param maxNumOfPixels 這張片圖片最大像素值,單位為byte,如100*1024 * @return 壓縮比例 */ private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength,int maxNumOfPixels) { double w = options.outWidth; double h = options.outHeight; int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math .sqrt(w * h / maxNumOfPixels)); int upperBound = (minSideLength == -1) ? 128 : (int) Math.min( Math.floor(w / minSideLength), Math.floor(h / minSideLength)); if (upperBound < lowerBound) { return lowerBound; } if ((maxNumOfPixels == -1) && (minSideLength == -1)) { return 1; } else if (minSideLength == -1) { return lowerBound; } else { return upperBound; } } 以上的方法是安卓源碼中處理縮略圖大小的計算方法,我們知道圖片的inSampleSize必須為2的冪次,如果不是2的冪次,會以接近2的冪次這個數(shù)來進(jìn)行壓縮,所以最后計算出來的inSampleSize必然不能很精確的將圖片壓縮到我們期望的大小,所以當(dāng)一張圖片太大時,可能第一次壓縮并沒有達(dá)到效果,然后再經(jīng)過第二次壓縮之后還是可能會超過32k,這就導(dǎo)致了最終的微信分享失敗。 在我們處理圖片的時候發(fā)現(xiàn),會給圖片設(shè)置質(zhì)量參數(shù),如下 public static Bitmap makeNormalBitmap(String nativeImagePath,int minSideLength, int maxNumOfPixels){ return makeNormalBitmap(nativeImagePath, minSideLength, maxNumOfPixels,Bitmap.Config.ARGB_4444); } 目前這里設(shè)置成了ARGB_4444,那為什么要設(shè)置成這個格式呢?應(yīng)該設(shè)置成什么格式呢?還有第二次壓縮bmp.compress(CompressFormat.PNG, 100, output);這里為什么設(shè)置成PNG,換成JPEG可以嗎? 針對以上問題,我做了一番測試,分為ARGB_8888(PNG) ARGB_4444(PNG) RGB_565(PNG) ARGB_8888(JPEG) ARGB_4444(JPEG) RGB_565(JPEG) 分別對圖片大小和質(zhì)量有什么影響。 調(diào)研數(shù)據(jù)分析結(jié)果如下:
優(yōu)化后的解決方案
大部分圖片經(jīng)過前兩次壓縮都能達(dá)到要求,為保證微信分享成功,在第二次壓縮后進(jìn)行判斷,如果小于32k就直接分享,如果大于的話就壓縮成JPEG格式,通過改變option參數(shù)來不斷進(jìn)行壓縮,直到滿足要求,該方案經(jīng)過測試已經(jīng)解決了微信分享失敗的問題。 注意點:在最后一步轉(zhuǎn)換成JPEG格式時會不斷修改option參數(shù)來進(jìn)行壓縮,圖片的質(zhì)量最后可能會影響,在這種情況下需要server配合換掉該圖,從客戶端的角度來考慮該方案可以保證分享成功,如果圖片失真嚴(yán)重的話就需要考慮換圖了。 |
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)