|
原文鏈接:微信分享圖片壓縮問題解決方案 作者:李青
概述 在進行微信分享時,遇到微信分享失敗的情況,微信分享對于圖片的大小有32k的限制,如果大于的話就會導致失敗。所以對于圖片的壓縮進行了調(diào)研,最后得出如下解決方案:
1、統(tǒng)一了圖片的質(zhì)量參數(shù)為RGB_565; 問題背景在某些頁面調(diào)起微信分享時會直接返回失敗,但并不是所有的頁面都會失敗,所以排除是微信分享API的問題。 術語解釋
問題分析
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,所以猜測這里應該是參數(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ù)來進行壓縮,所以最后計算出來的inSampleSize必然不能很精確的將圖片壓縮到我們期望的大小,所以當一張圖片太大時,可能第一次壓縮并沒有達到效果,然后再經(jīng)過第二次壓縮之后還是可能會超過32k,這就導致了最終的微信分享失敗。 在我們處理圖片的時候發(fā)現(xiàn),會給圖片設置質(zhì)量參數(shù),如下
public static Bitmap makeNormalBitmap(String nativeImagePath,int minSideLength, int maxNumOfPixels){
return makeNormalBitmap(nativeImagePath, minSideLength, maxNumOfPixels,Bitmap.Config.ARGB_4444);
}
目前這里設置成了ARGB_4444,那為什么要設置成這個格式呢?應該設置成什么格式呢?還有第二次壓縮bmp.compress(CompressFormat.PNG, 100, output);這里為什么設置成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)過前兩次壓縮都能達到要求,為保證微信分享成功,在第二次壓縮后進行判斷,如果小于32k就直接分享,如果大于的話就壓縮成JPEG格式,通過改變option參數(shù)來不斷進行壓縮,直到滿足要求,該方案經(jīng)過測試已經(jīng)解決了微信分享失敗的問題。 注意點:在最后一步轉(zhuǎn)換成JPEG格式時會不斷修改option參數(shù)來進行壓縮,圖片的質(zhì)量最后可能會影響,在這種情況下需要server配合換掉該圖,從客戶端的角度來考慮該方案可以保證分享成功,如果圖片失真嚴重的話就需要考慮換圖了。 |