当需要往服务器上传图片的时候,越小越好,既节省流量也节省时间,同时也节省内存。
今天我遇到的问题就是这样,我最初的解决办法是动态的设置BitmapFactory.Options的inSampleSize的值,方法如下:
private void compressImageFromFile(String srcPath) {
long s = System.currentTimeMillis();
try {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
Bitmap btemp = BitmapFactory.decodeFile(srcPath, newOpts);
Log.i(TAG, "w=" + newOpts.outWidth);
Log.i(TAG, "h=" + newOpts.outHeight);
Log.i(TAG, "w*h=" + newOpts.outWidth * newOpts.outHeight);
newOpts.inJustDecodeBounds = false;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
newOpts.inSampleSize = 7;// 设置采样率
newOpts.inPreferredConfig = Config.RGB_565;
Bitmap bmp = BitmapFactory.decodeFile(srcPath, newOpts);
Log.i(TAG, "bmp.getByteCount()=" + bmp.getByteCount());
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bytes = stream.toByteArray();
Log.i(TAG, "first--bytes.length=" + bytes.length);
while (bytes.length > (5 * 1024 * 1024)) {
int sample_size = (int) Math.ceil((float) bytes.length
/ (5 * 1024 * 1024));
Log.i(TAG, "sample_size=" + sample_size);
newOpts.inSampleSize = sample_size;
bmp = BitmapFactory.decodeFile(srcPath, newOpts);
stream.reset();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
bytes = stream.toByteArray();
Log.i(TAG, "bytes.length=" + bytes.length);
}
Log.i(TAG, "bytes.length=" + bytes.length);
Log.i(TAG, "bmp.getWidth()=" + bmp.getWidth());
Log.i(TAG, "bmp.getHeight()=" + bmp.getHeight());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i(TAG,
"System.currentTimeMillis()-s="
+ (System.currentTimeMillis() - s));
}
问题是速度很慢,每次耗时是近40秒,我的要求是压缩的图片大小要小于5M,压缩后的大小,即bytes流的大小都在2M左右,符合要求。
在这个里面我没有使用质量压缩,原因是对于一张太大的图片质量压缩达不到最后要求,但是这个尺寸的压缩,由于inSimpleSize是进行一次compress之后,计算出来的所以耗时太多,也有部分人用的是指定压缩后的宽高,一步到位。但是在选择固定值时我由于知识不完备不知道该指定多大的,最后查资料,找到一个较新的统计:http://blog.sina.com.cn/s/blog_541bdbb80102v2km.html 最后选定的大小是:1136*640
方法如下:
private Bitmap compressImageFromFileFaster(String srcPath) {
long s = System.currentTimeMillis();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcPath, newOpts);// 打开空图片获取分辨率
newOpts.inSampleSize = getinSampleSize(newOpts);// 设置缩放倍数
newOpts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
Log.i(TAG, "压缩后分辨率:" + newOpts.outWidth + "*" + newOpts.outHeight);
Log.i(TAG, "分辨率压缩后的大小:" + (baos.toByteArray().length / (1024 * 1024))
+ "");
Log.i(TAG, "耗时=" + (System.currentTimeMillis() - s));
return bitmap;
}
/**
* 获取图片压缩的比率
*
* @param options
* @return
*/
public static int getinSampleSize(BitmapFactory.Options options) {
final int height = options.outHeight;
final int width = options.outWidth;
float reqHeight = 1136.0f;
float reqWidth = 640.0f;
int inSampleSize = 1;
if (height > width && height > reqHeight) {
inSampleSize = (int) Math.ceil(height / reqHeight);
} else if (height <= width && width > reqWidth) {
inSampleSize = (int) Math.ceil(width / reqWidth);
}
return inSampleSize;
}
耗时在2000到3000毫秒。