最近弄一个在画板上签名然后保存成图片保存在本地,压缩图片(要求:压缩后的图片大小小于5kb,宽高130*78)
我的压缩办法是按比例大小压缩+缩放压缩+质量压缩
byte[] bs=Const.compressScale(newBitmap);//按比例大小压缩+缩放压缩+质量压缩 newBitmap为bitmap
/**
* 图片按比例大小压缩方法
* @param image
* (根据Bitmap图片压缩)
*
* @return byte[]
*/
public static byte[] compressScale(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, baos);
// 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
if (baos.toByteArray().length / 1024 > 1024) {
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.PNG, 80, baos);// 这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
// 开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
Log.i("Const", w + "---------------" + h);
// inSampleSize比1小的话会被当做1(为1表示不缩放),任何inSampleSize的值会被取接近2的幂值。
newOpts.inSampleSize = calculateInSampleSize(newOpts, 130, 78);// 设置缩放比例
// newOpts.inPreferredConfig = Config.RGB_565;//降低图片从ARGB888到RGB565
// 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return scale(bitmap, (int) Const.width, (int) Const.height, true);// 缩放压缩(130*78)
}
/**
* (按比例大小压缩) 压缩比例 inSampleSize
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
Log.e("url", "inSampleSize==" + inSampleSize);
return inSampleSize;
}
/**
* /** 缩放图片
*
* @param src
* 源图片
* @param newWidth
* 新宽度
* @param newHeight
* 新高度
* @param recycle
* 是否回收
* @return 缩放后的图片的字节数组
*/
public static byte[] scale(Bitmap src, int newWidth, int newHeight, boolean recycle) {
Bitmap ret = Bitmap.createScaledBitmap(src, newWidth, newHeight, true);
if (recycle && !src.isRecycled())
src.recycle();
return compressImage(ret);//质量压缩图片(大小小于5kb)
}
/**
* 质量压缩方法
*
* @param image
* @return byte[]
*/
public static byte[] compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 90;
Log.e("url", "baos.toByteArray().length压缩前==" + baos.toByteArray().length);
while (baos.toByteArray().length / 1024 > 4) { // 循环判断如果压缩后图片是否大于5kb,大于继续压缩
baos.reset(); // 重置baos即清空baos
image.compress(Bitmap.CompressFormat.PNG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 5;// 每次都减少10
if (options <= 0) {
options = 0;
break;
}
Log.e("url", "options==" + options);
}
Log.e("url", "baos.toByteArray().length压缩后==" + baos.toByteArray().length);
return baos.toByteArray();
}
if (buffer != null) {
File file = new File(path);
if (file.exists()) {
if (file.delete()) {
System.out.println("file delete success!");
} else {
System.out.println("file delete fail!");
}
}
file = new File(path);
OutputStream outputStream = new FileOutputStream(file);
outputStream.write(buffer);
outputStream.close();
scanMediaFile(file);
if (newBitmap != null && !newBitmap.isRecycled()) {
// 回收并且置为null
newBitmap.recycle();
}
}
1、调用质量压缩的时候,网上很多方法是:质量压缩后byte数组转成bitmap,然后bitmap在转成byte数组写入file,这样的图片大小并没有压缩。我的解决办法就是:质量压缩后byte数组直接返回,然后写入file,这样图片就能压缩到自己所限制的大小;
2、图片压缩,如果图片大小很大,还是需要先按比例压缩一下,在进行质量压缩,不然有时候直接质量压缩,当options=0(0~100)的时候,就无法再压缩了。也就无法达到我们所要压缩的大小
3、按比例大小压缩:
newOpts.inSampleSize = be; // 设置缩放比例
inSampleSize比1小的话会被当做1(为1表示不缩放),任何inSampleSize的值会被取接近2的幂值。
4、如果是画布上签名形成图片的,然后要注意画笔的粗细,如果画笔太细,可能导致像素太低,也就导致字体断断续续的
5、(IE上打不开)压缩图片的时候,图片保存格式是.png,压缩图片的时候,也要用对应的PNGimage.compress(Bitmap.CompressFormat.PNG, options, baos);
有错误或者更好方法欢迎指出,谢谢