编写:徐建祥(netpirate@gmail.com)
日期:2010/12/06
网址:http://www.anymobile.org

传输文件,或者设置头像,我们一般都会检查原始图片的大小,作缩放处理。

常用的Java版缩放图片代码:

view plaincopy to clipboardprint?

public Bitmap getZoomImage(Bitmap src, int desW, int desH)
{
Bitmap desImg = null;
int srcW = src.getWidth(); // 原始图像宽
int srcH = src.getHeight(); // 原始图像高
int[] srcBuf = new int[srcW * srcH]; // 原始图片像素信息缓存

src.getPixels(srcBuf, 0, srcW, 0, 0, srcW, srcH);

// 计算插值表
int[] tabY = new int[desH];
int[] tabX = new int[desW];

int sb = 0;
int db = 0;
int tems = 0;
int temd = 0;
int distance = srcH > desH ? srcH : desH;
for (int i = 0; i <= distance; i++)
{/* 垂直方向 */
tabY[db] = sb;
tems += srcH;
temd += desH;
if (tems > distance)
{
tems -= distance;
sb++;
}
if (temd > distance)
{
temd -= distance;
db++;
}
}

sb = 0;
db = 0;
tems = 0;
temd = 0;
distance = srcW > desW ? srcW : desW;

for (int i = 0; i <= distance; i++)
{/* 水平方向 */
tabX[db] = (short) sb;
tems += srcW;
temd += desW;
if (tems > distance)
{
tems -= distance;
sb++;
}
if (temd > distance)
{
temd -= distance;
db++;
}
}

// 生成放大缩小后图形像素
int[] desBuf = new int[desW * desH];
int dx = 0;
int dy = 0;
int sy = 0;
int oldy = -1;

for (int i = 0; i < desH; i++)
{
if (oldy == tabY[i])
{
System.arraycopy(desBuf, dy - desW, desBuf, dy, desW);
}
else
{
dx = 0;
for (int j = 0; j < desW; j++)
{
desBuf[dy + dx] = srcBuf[sy + tabX[j]];
dx++;
}
sy += (tabY[i] - oldy) * srcW;
}
oldy = tabY[i];
dy += desW;
}
// 生成图片
desImg = Bitmap.createBitmap(desBuf, desW, desH, Bitmap.Config.ARGB_8888);

return desImg;
}



常用的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();
}



OVER!

更多相关文章

  1. 以android实际开发为背景整理学习资料
  2. ViewPager实现无限循环切换和手势滑动效果
  3. webview 设定和使用缓存来获取网页中的js,css和图片资源
  4. Android(安卓)WebView加载Html文本不能适配,以及图片中间有空白的
  5. Android(安卓)Glide4.0以上版本保存Gif文件方法
  6. Android(安卓)解决BitmapFactory.decodeFile(file) 报OOM问题
  7. android显示大图片的一些技巧
  8. android minui fb显示相关函数
  9. Android(安卓)Glide图片缓存原理及手写实现

随机推荐

  1. 【Android(安卓)多媒体开发】 MediaPlaye
  2. Android弹出菜单的灵活运用(自定义AlertD
  3. Android实现检测耳机插入和拔出
  4. Android:Actionbar的显示和隐藏
  5. Android CTS 问题分析
  6. 360加固保加固的安卓/Android包,重金求APP
  7. Qt on Android Episode 2(翻译)
  8. Android 快速开发框架 ThinkAndroid
  9. Android完整的app项目
  10. 《Android》Lesson08-Activity的生命周期