最近在项目中碰到图片的问题,相册的照片大概普遍在4M往上,项目中需要用低功耗蓝牙(BLE)传输,要求把图片压缩到10K左右,但是我尝试了很多方法,压缩100倍之后(40kb)左右就不能压缩了,再低的话,基本就看不清图片了(很模糊,跟马赛克一样),尺寸也压缩到了要求的最小值,我现在尺寸压缩,质量压缩,jni底层压缩全部用上了,最多压到40K左右就不能再往下了,不然完全看不清,但是BLE的传输带宽实在有限,40K的图片估计得十分钟往上了,有没有对图片的压缩比较精通的老哥给帮忙指教一下还有什么办法?不胜感激
解决方案 »
- 求助官网下载的Android SDK安装后用SDK Manager安装没反应。。。求助。。求助
- android
- 既然service跟Ui线程在同一个线程,那为什么在service播放音乐的时候不会阻塞UI线程呢
- 新手向大家请教几个问题
- android串口通信 接收数据问题
- [Android]从TXT导入到SQLite中的中文乱码
- 求救!关于天气预报的问题
- sundy Android高级应用开发
- 跳转至系统收件箱,出现java.lang.SecurityException: 异常
- 有没有做过安卓电视上开发客户端的
- 应用权限的问题!
- android socket发送数据报Error parsing HTTP request header Note: further occurrence
* 根据路径获得图片信息并按比例压缩,返回bitmap
*/
public static Bitmap getSmallbitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 只解析图片边缘,获取宽高
BitmapFactory.decodeFile(filePath, options);
// 计算缩放比
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// 完整解析图片返回bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}
/**
* 质量压缩方法
*
* @param image
* @return
*/
public static Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 90; while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset(); // 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
options -= 10;// 每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
return bitmap;
}
/**
* 图片按比例大小压缩方法
*
* @param image (根据Bitmap图片压缩)
* @return
*/
public static Bitmap compressScale(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos); // 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
if (baos.toByteArray().length / 1024 > 1024) {
baos.reset();// 重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 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;
// 现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
// float hh = 800f;// 这里设置高度为800f
// float ww = 480f;// 这里设置宽度为480f
float hh = 512f;
float ww = 512f;
// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;// be=1表示不缩放
if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) { // 如果高度高的话根据高度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be; // 设置缩放比例
// newOpts.inPreferredConfig = Config.RGB_565;//降低图片从ARGB888到RGB565 // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts); return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩 //return bitmap;
}
/**
* 计算压缩比
* @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;
}
return inSampleSize;
}