近期在改舊版微信分享圖片 ,因爲微信官方限制分享小程序的縮略圖大小爲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
}
}
}