小程序模板網(wǎng)

微信分享圖片壓縮問題解決方案

發(fā)布時間:2018-04-23 12:07 所屬欄目:小程序開發(fā)教程

原文鏈接:微信分享圖片壓縮問題解決方案

作者:李青

 

概述

在進(jìn)行微信分享時,遇到微信分享失敗的情況,微信分享對于圖片的大小有32k的限制,如果大于的話就會導(dǎo)致失敗。所以對于圖片的壓縮進(jìn)行了調(diào)研,最后得出如下解決方案:

1、統(tǒng)一了圖片的質(zhì)量參數(shù)為RGB_565;
2、先利用32*1024計算出圖片采樣率,進(jìn)行一次長寬比壓縮;
3、然后利用compress( CompressFormat format, int quality,OutputStream stream)壓縮成PNG格式;
4、計算此時大小,如果超過32k,則換成JPEG格式進(jìn)行壓縮,通過循環(huán)修改quality參數(shù)來進(jìn)行壓縮,直到最后圖片小于32k結(jié)束。

問題背景

在某些頁面調(diào)起微信分享時會直接返回失敗,但并不是所有的頁面都會失敗,所以排除是微信分享API的問題。

術(shù)語解釋

  • A : 透明度
  • R : 紅色
  • G : 綠色
  • B : 藍(lán)色
  • Bitmap.Config ARGB_4444:每個像素占四位,即A=4,R=4,G=4,B=4,那么一個像素點占4+4+4+4=16位
  • Bitmap.Config ARGB_8888:每個像素占四位,即A=8,R=8,G=8,B=8,那么一個像素點占8+8+8+8=32位
  • Bitmap.Config RGB_565:每個像素占四位,即R=5,G=6,B=5,沒有透明度,那么一個像素點占5+6+5=16位

問題分析

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é)果如下:

  • 首先用ARGB_8888 PNG的格式去解析圖片,所做實驗中,圖片最終大小超過32KB的較多,分享失敗率較高;
  • 用ARGB_4444 PNG格式去解析時,圖片最終大小得到很大減少,但是圖片的質(zhì)量比上面的較差,用肉眼能分辨出來;
  • 用RGB_565 PNG格式去解析,圖片大小與ARGB_4444一樣,但是圖片的質(zhì)量明顯比ARGB_4444較好,與ARGB_8888的效果基本一樣;
  • JPEG解析時,圖片大小比PNG的較小,正常的圖片都顯示的效果很好,但不支持透明背景屬性,所以對于像58logo這樣四周圓弧的圖片來說,用JPEG的效果就比PNG的差。

優(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)重的話就需要考慮換圖了。



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://22321a.com/wxmini/doc/course/23930.html 復(fù)制鏈接 如需定制請聯(lián)系易優(yōu)客服咨詢:800182392 點擊咨詢
QQ在線咨詢