原文地址:http://www.blogjava.net/anymobile/articles/340722.html
传输文件,或者设置头像,我们一般都会检查原始图片的大小,作缩放处理。
常用的Android版缩放图片代码:
view plaincopy to clipboardprint?
ContentResolver cr = this.getContentResolver();
try
{
InputStream in = cr.openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(in);
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
if(null == bitmap)
{
Toast.makeText(this, "Head is not set successful,Decode bitmap failure", 2000);
}
//原始图片的尺寸
int bmpWidth = bitmap.getWidth();
int bmpHeight = bitmap.getHeight();
//缩放图片的尺寸
float scaleWidth = (float) 40 / bmpWidth;
float scaleHeight = (float) 40 / bmpHeight;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
//产生缩放后的Bitmap对象
Bitmap resizeBitmap = Bitmap.createBitmap(
bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);
bitmap.recycle();
//Bitmap to byte[]
byte[] photoData = Bitmap2Bytes(resizeBitmap);
//save file
String fileName = "/sdcard/test.jpg";
FileUtil.writeToFile(fileName, photoData);
//save photo check sum to db
DataCenter.GetInstance().ModifyIMMUser();
//refresh ImageView
}
catch (FileNotFoundException exp)
{
exp.printStackTrace();
}
如果图片非常大,在执行BitmapFactory.decodeStream的时候就会抛出OOM异常。
我们来看看系统应用MMS是如何处理的,SMS添加了多媒体附件后就作MMS处理了,当附加文件原图超过300K,也会做个缩放处理,具体参考:com.android.mms.ui/.UriImage:
view plaincopy to clipboardprint?
package com.android.mms.ui;
public class UriImage
{
private int mWidth;
private int mHeight;
... ...
//
private void decodeBoundsInfo()
{
InputStream input = null;
try
{
input = mContext.getContentResolver().openInputStream(mUri);
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;//只描边,不读取数据
BitmapFactory.decodeStream(input, null, opt);
mWidth = opt.outWidth;
mHeight = opt.outHeight;
}
catch (FileNotFoundException e)
{
// Ignore
Log.e(TAG, "IOException caught while opening stream", e);
}
finally
{
if (null != input) {
try {
input.close();
} catch (IOException e) {
// Ignore
Log.e(TAG, "IOException caught while closing stream", e);
}
}
}
}
private byte[] getResizedImageData(int widthLimit, int heightLimit)
{
int outWidth = mWidth;
int outHeight = mHeight;
int s = 1;
while ((outWidth / s > widthLimit) || (outHeight / s > heightLimit))
{
s *= 2;
}
//先设置选项
BitmapFactory.Options options = new BitmapFactory.Options();
//returning a smaller image to save memory.
options.inSampleSize = s;
InputStream input = null;
try
{
input = mContext.getContentResolver().openInputStream(mUri);
Bitmap b = BitmapFactory.decodeStream(input, null, options);//注意看options的用法
if (b == null) {
return null;
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
b.compress(CompressFormat.JPEG, MessageUtils.IMAGE_COMPRESSION_QUALITY, os);
return os.toByteArray();
} catch (FileNotFoundException e) {
Log.e(TAG, e.getMessage(), e);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
}
}
}
... ...
}
可以看出,MMS应用的方法是:先设置缩放选项,再读取缩放的图片数据到内存,规避了内存引起的OOM。
修改后的代码:
view plaincopy to clipboardprint?
ContentResolver cr = this.getContentResolver();
try
{
InputStream in = cr.openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
int mWidth = options.outWidth;
int mHeight = options.outHeight;
int sWidth = 40;
int sHeight = 40;
int s = 1;
while ((mWidth / s > sWidth * 2) || (mHeight / s > sHeight * 2))
{
s *= 2;
}
options = new BitmapFactory.Options();
options.inSampleSize = s;
in = cr.openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
if(null == bitmap)
{
Toast.makeText(this, "Head is not set successful,Decode bitmap failure", 2000);
return ;
}
//原始图片的尺寸
int bmpWidth = bitmap.getWidth();
int bmpHeight = bitmap.getHeight();
//缩放图片的尺寸
float scaleWidth = (float) sWidth / bmpWidth;
float scaleHeight = (float) sHeight / bmpHeight;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
//产生缩放后的Bitmap对象
Bitmap resizeBitmap = Bitmap.createBitmap(
bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);
bitmap.recycle();
Bitmap resizeBitmap = bitmap;
//Bitmap to byte[]
byte[] photoData = bitmap2Bytes(resizeBitmap);
//save file
String fileName = "/sdcard/test.jpg";
FileUtil.writeToFile(fileName, photoData);
view plaincopy to clipboardprint?
private byte[] bitmap2Bytes(Bitmap bm)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
return baos.toByteArray();
}