關於微信分享圖片一二事

近期在改舊版微信分享圖片 ,因爲微信官方限制分享小程序的縮略圖大小爲128K,大部分情況下需要進行圖片壓縮;

可是,使用了下搜索引擎查看了下,一堆寫質量壓縮的代碼都是有問題的,比如此類有問題的寫法:


錯誤示範代碼: 

/**
     * Bitmap轉換成byte[]並且進行壓縮,壓縮到不大於maxkb
     * @param bitmap
     * @param IMAGE_SIZE
     * @return
     */
 public static byte[] bitmap2Bytes(Bitmap bitmap, int maxkb) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
        int options = 100;
        while (output.toByteArray().length > maxkb&& options != 10) {
            output.reset(); //清空output
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);//這裏壓縮options%,把壓縮後的數據存放到output中
            options -= 10;
        }
        return output.toByteArray();
    }
    

看似沒毛病,卻可能會進入死循環; 哎,很多人都會轉載他人的博客,其他大部分人也是一知半解,導致網上一搜都是半成品的代碼誤人子弟;

可參考下寫的比較負責的博客, 如
微信分享大圖遇到的問題

最終提供縮略圖壓縮的方法: (爲微信內置工具類獲取縮略圖)

//微信分享工具類;
class WxUtils {
    companion object {
        val TAG = "WxUtils"

        private val MAX_DECODE_PICTURE_SIZE = 1920 * 1440
        
		//獲取縮略圖
        fun extractThumbNail(path: String?, height: Int, width: Int, crop: Boolean): Bitmap? {
            if (path == null || path == "" || height <= 0 || width <= 0) {
                return null
            }

            var options: BitmapFactory.Options? = BitmapFactory.Options()

            try {
                options!!.inJustDecodeBounds = true
                var tmp = BitmapFactory.decodeFile(path, options)
                if (tmp != null) {
                    tmp!!.recycle()
                    tmp = null
                }

                LogUtils.e(TAG, "extractThumbNail: round=" + width + "x" + height + ", crop=" + crop)
                val beY = options!!.outHeight * 1.0 / height
                val beX = options!!.outWidth * 1.0 / width
                LogUtils.e(TAG, "extractThumbNail: extract beX = $beX, beY = $beY")
                options!!.inSampleSize = (if (crop) if (beY > beX) beX else beY else if (beY < beX) beX else beY).toInt()
                if (options!!.inSampleSize <= 1) {
                    options!!.inSampleSize = 1
                }

                // NOTE: out of memory error
                while (options!!.outHeight * options!!.outWidth / options!!.inSampleSize > MAX_DECODE_PICTURE_SIZE) {
                    options!!.inSampleSize++
                }

                var newHeight = height
                var newWidth = width
                if (crop) {
                    if (beY > beX) {
                        newHeight = (newWidth * 1.0 * options!!.outHeight / options!!.outWidth).toInt()
                    } else {
                        newWidth = (newHeight * 1.0 * options!!.outWidth / options!!.outHeight).toInt()
                    }
                } else {
                    if (beY < beX) {
                        newHeight = (newWidth * 1.0 * options!!.outHeight / options!!.outWidth).toInt()
                    } else {
                        newWidth = (newHeight * 1.0 * options!!.outWidth / options!!.outHeight).toInt()
                    }
                }

                options!!.inJustDecodeBounds = false

                LogUtils.e(TAG, "bitmap required size=" + newWidth + "x" + newHeight + ", orig=" + options!!.outWidth + "x" + options!!.outHeight + ", sample=" + options!!.inSampleSize)
                var bm = BitmapFactory.decodeFile(path, options)
                if (bm == null) {
                    LogUtils.e(TAG, "bitmap decode failed")
                    return null
                }

                LogUtils.e(TAG, "bitmap decoded size=" + bm!!.getWidth() + "x" + bm!!.getHeight())
                val scale = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true)
                if (scale != null) {
                    bm!!.recycle()
                    bm = scale
                }

                if (crop) {
                    val cropped = Bitmap.createBitmap(bm, (bm!!.getWidth() - width) shr 1, (bm!!.getHeight() - height) shr 1, width, height)
                            ?: return bm

                    bm!!.recycle()
                    bm = cropped
                    LogUtils.e(TAG, "bitmap croped size=" + bm!!.getWidth() + "x" + bm!!.getHeight())
                }
                return bm

            } catch (e: OutOfMemoryError) {
                LogUtils.e(TAG, "decode bitmap failed: " + e.message)
                options = null
            }

            return null
        }

		//bitmap -> ByteArray;
        fun bmpToByteArray(bmp: Bitmap, needRecycle: Boolean): ByteArray {
            val output = ByteArrayOutputStream()
            bmp.compress(Bitmap.CompressFormat.PNG, 100, output)
            if (needRecycle) {
                bmp.recycle()
            }

            val result = output.toByteArray()
            try {
                output.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }

            return result
        }
    }

}
發佈了46 篇原創文章 · 獲贊 3 · 訪問量 5088
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章