Android图片压缩有多种压缩方式,常用的有质量压缩、尺寸压缩(采样率压缩)、通过JNI调用libjpeg库来进行压缩(最后一种请移步blog.csdn.net/chenliguan/…
1.质量压缩
保持像素的前提下改变图片的位深及透明度,现在常见的压缩方式。
/**
* 质量压缩
* 设置options 属性0-100,来实现压缩(因为png是无损压缩,所以该属性对png效果较弱)
*
* @param bitmap 需要压缩的图片
* @param file 压缩后的输入文件
* @param quality 图片质量 0-100 100为不压缩
*/
fun qualityCompress(bitmap: Bitmap?, file: File?, quality: Int) {
val outputStream = ByteArrayOutputStream()
// 把压缩后的数据存放到baos中
bitmap?.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
try {
val fos = FileOutputStream(file)
fos.write(outputStream.toByteArray())
fos.flush()
fos.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
2.尺寸压缩(采样率压缩)
设置图片的采样率,降低图片像素
好处:是不会先将大图片读入内存,大大减少了内存的使用,也不必考虑将大图片读入内存后的释 放事宜。
问题:因为采样率是整数,所以不能很好的保证图片的质量。如我们需要的是在2和3采样率之间,用2的话图片就大了一点,但是用3的话图片质量就会有很明显的下降,这样也无法完全满足我的需要。
/**
* 质量压缩
* 设置options 属性0-100,来实现压缩(因为png是无损压缩,所以该属性对png效果较弱)
*
* @param filePath 需要压缩的图片路径
* @param file 压缩后的输入文件
* @param inSampleSize 图片质量 1为不压缩
*/
fun inSampleSizeCompress(filePath: String?, file: File?, inSampleSize: Int) {
val options = BitmapFactory.Options()
options.inSampleSize = inSampleSize
val outputStream = ByteArrayOutputStream()
// 把压缩后的数据存放到baos中
val bitmap = BitmapFactory.decodeFile(filePath, options)
bitmap?.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
try {
val fos = FileOutputStream(file)
fos.write(outputStream.toByteArray())
fos.flush()
fos.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
3.luban压缩 尺寸压缩+质量压缩
动态计算压缩比例,建议修改源码 以支持自定义quality
private fun computeSize(): Int {
srcWidth = if (srcWidth % 2 == 1) srcWidth + 1 else srcWidth
srcHeight = if (srcHeight % 2 == 1) srcHeight + 1 else srcHeight
val longSide: Int = Math.max(srcWidth, srcHeight)
val shortSide: Int = Math.min(srcWidth, srcHeight)
val scale = shortSide.toFloat() / longSide
val result: Int
result = if (scale <= 1 && scale > 0.5625) {
// longSide % 1920 > (1920 * 0.8) 则 result++
(longSide / 1920.0 + if (longSide % 1920 > 1920 * 0.8) 1 else 0).toInt()
} else if (scale <= 0.5625 && scale > 0.5) {
longSide / 1920
} else {
Math.ceil(shortSide / 1920.0).toInt()
}
// 压缩极限 1/(4*4)
return Math.min(Math.max(result, 1), 4)
}
@Throws(IOException::class)
fun compress(): File? {
val options = BitmapFactory.Options()
options.inSampleSize = computeSize()
var tagBitmap = BitmapFactory.decodeStream(srcImg.open(), null, options)
val stream = ByteArrayOutputStream()
if (Checker.SINGLE.isJPG(srcImg.open())) {
tagBitmap = rotatingImage(tagBitmap, Checker.SINGLE.getOrientation(srcImg.open()))
}
tagBitmap!!.compress(
if (focusAlpha) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG,
mQuality,
stream
)
tagBitmap.recycle()
val fos = FileOutputStream(tagImg)
fos.write(stream.toByteArray())
fos.flush()
fos.close()
stream.close()
return tagImg
}