随笔-1  评论-68  文章-98  trackbacks-0

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

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

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

  1. public Bitmap getZoomImage(Bitmap src, int desW, int desH)  
  2. {  
  3.     Bitmap desImg = null;  
  4.     int srcW = src.getWidth(); // 原始图像宽  
  5.     int srcH = src.getHeight(); // 原始图像高  
  6.     int[] srcBuf = new int[srcW * srcH]; // 原始图片像素信息缓存  
  7.       
  8.     src.getPixels(srcBuf, 0, srcW, 00, srcW, srcH);  
  9.       
  10.     // 计算插值表  
  11.     int[] tabY = new int[desH];  
  12.     int[] tabX = new int[desW];  
  13.       
  14.     int sb = 0;  
  15.     int db = 0;  
  16.     int tems = 0;  
  17.     int temd = 0;  
  18.     int distance = srcH > desH ? srcH : desH;  
  19.     for (int i = 0; i <= distance; i++)  
  20.     {/* 垂直方向 */  
  21.         tabY[db] = sb;  
  22.         tems += srcH;  
  23.         temd += desH;  
  24.         if (tems > distance)  
  25.         {  
  26.             tems -= distance;  
  27.             sb++;  
  28.         }  
  29.         if (temd > distance)  
  30.         {  
  31.             temd -= distance;  
  32.             db++;  
  33.         }  
  34.     }  
  35.       
  36.     sb = 0;  
  37.     db = 0;  
  38.     tems = 0;  
  39.     temd = 0;  
  40.     distance = srcW > desW ? srcW : desW;  
  41.       
  42.     for (int i = 0; i <= distance; i++)  
  43.     {/* 水平方向 */  
  44.         tabX[db] = (short) sb;  
  45.         tems += srcW;  
  46.         temd += desW;  
  47.         if (tems > distance)  
  48.         {  
  49.             tems -= distance;  
  50.             sb++;  
  51.         }  
  52.         if (temd > distance)  
  53.         {  
  54.             temd -= distance;  
  55.             db++;  
  56.         }  
  57.     }  
  58.       
  59.     // 生成放大缩小后图形像素  
  60.     int[] desBuf = new int[desW * desH];  
  61.     int dx = 0;  
  62.     int dy = 0;  
  63.     int sy = 0;  
  64.     int oldy = -1;  
  65.       
  66.     for (int i = 0; i < desH; i++)  
  67.     {  
  68.         if (oldy == tabY[i])  
  69.         {  
  70.             System.arraycopy(desBuf, dy - desW, desBuf, dy, desW);  
  71.         }  
  72.         else  
  73.         {  
  74.             dx = 0;  
  75.             for (int j = 0; j < desW; j++)  
  76.             {  
  77.                 desBuf[dy + dx] = srcBuf[sy + tabX[j]];  
  78.                 dx++;  
  79.             }  
  80.             sy += (tabY[i] - oldy) * srcW;  
  81.         }  
  82.         oldy = tabY[i];  
  83.         dy += desW;  
  84.     }  
  85.     // 生成图片  
  86.     desImg = Bitmap.createBitmap(desBuf, desW, desH, Bitmap.Config.ARGB_8888);  
  87.       
  88.     return desImg;  
  89. }  
 

 

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

  1. ContentResolver cr = this.getContentResolver();  
  2. try  
  3. {  
  4.     InputStream in = cr.openInputStream(uri);  
  5.     Bitmap bitmap = BitmapFactory.decodeStream(in);  
  6.     try  
  7.     {  
  8.         in.close();  
  9.     }  
  10.     catch (IOException e)  
  11.     {  
  12.         e.printStackTrace();  
  13.     }  
  14.     if(null  == bitmap)  
  15.     {  
  16.         Toast.makeText(this"Head is not set successful,Decode bitmap failure"2000);  
  17.     }  
  18.     //原始图片的尺寸  
  19.     int bmpWidth  = bitmap.getWidth();  
  20.     int bmpHeight = bitmap.getHeight();  
  21.       
  22.     //缩放图片的尺寸  
  23.     float scaleWidth  = (float40 / bmpWidth;  
  24.     float scaleHeight = (float40 / bmpHeight;  
  25.     Matrix matrix = new Matrix();  
  26.     matrix.postScale(scaleWidth, scaleHeight);  
  27.       
  28.     //产生缩放后的Bitmap对象  
  29.     Bitmap resizeBitmap = Bitmap.createBitmap(  
  30.         bitmap, 00, bmpWidth, bmpHeight, matrix, false);  
  31.     bitmap.recycle();  
  32.     //Bitmap to byte[]  
  33.     byte[] photoData = Bitmap2Bytes(resizeBitmap);  
  34.       
  35.     //save file  
  36.     String fileName = "/sdcard/test.jpg";  
  37.     FileUtil.writeToFile(fileName, photoData);  
  38.       
  39.     //save photo check sum to db  
  40.     DataCenter.GetInstance().ModifyIMMUser();  
  41.     //refresh ImageView  
  42. }  
  43. catch (FileNotFoundException exp)  
  44. {  
  45.     exp.printStackTrace();  
  46. }  
 

 

如果图片非常大,在执行BitmapFactory.decodeStream的时候就会抛出OOM异常。

我们来看看系统应用MMS是如何处理的,SMS添加了多媒体附件后就作MMS处理了,当附加文件原图超过300K,也会做个缩放处理,具体参考:com.android.mms.ui/.UriImage:

  1. package com.android.mms.ui;  
  2. public class UriImage  
  3. {  
  4.     private int mWidth;  
  5.     private int mHeight;  
  6.     ... ...  
  7.     //  
  8.     private void decodeBoundsInfo()  
  9.     {  
  10.         InputStream input = null;  
  11.         try  
  12.         {  
  13.             input = mContext.getContentResolver().openInputStream(mUri);  
  14.             BitmapFactory.Options opt = new BitmapFactory.Options();  
  15.             opt.inJustDecodeBounds = true;//只描边,不读取数据  
  16.             BitmapFactory.decodeStream(input, null, opt);  
  17.             mWidth = opt.outWidth;  
  18.             mHeight = opt.outHeight;  
  19.         }  
  20.         catch (FileNotFoundException e)  
  21.         {  
  22.             // Ignore  
  23.             Log.e(TAG, "IOException caught while opening stream", e);  
  24.         }  
  25.         finally  
  26.         {  
  27.             if (null != input) {  
  28.                 try {  
  29.                     input.close();  
  30.                 } catch (IOException e) {  
  31.                     // Ignore  
  32.                     Log.e(TAG, "IOException caught while closing stream", e);  
  33.                 }  
  34.             }  
  35.         }  
  36.     }  
  37.     private byte[] getResizedImageData(int widthLimit, int heightLimit)  
  38.     {  
  39.         int outWidth = mWidth;  
  40.         int outHeight = mHeight;  
  41.         int s = 1;  
  42.         while ((outWidth / s > widthLimit) || (outHeight / s > heightLimit))  
  43.         {  
  44.             s *= 2;  
  45.         }  
  46.         //先设置选项  
  47.         BitmapFactory.Options options = new BitmapFactory.Options();  
  48.         //returning a smaller image to save memory.  
  49.         options.inSampleSize = s;  
  50.         InputStream input = null;  
  51.         try  
  52.         {  
  53.             input = mContext.getContentResolver().openInputStream(mUri);  
  54.             Bitmap b = BitmapFactory.decodeStream(input, null, options);//注意看options的用法  
  55.             if (b == null) {  
  56.                 return null;  
  57.             }  
  58.             ByteArrayOutputStream os = new ByteArrayOutputStream();  
  59.             b.compress(CompressFormat.JPEG, MessageUtils.IMAGE_COMPRESSION_QUALITY, os);  
  60.             return os.toByteArray();  
  61.         } catch (FileNotFoundException e) {  
  62.             Log.e(TAG, e.getMessage(), e);  
  63.             return null;  
  64.         } finally {  
  65.             if (input != null) {  
  66.                 try {  
  67.                     input.close();  
  68.                 } catch (IOException e) {  
  69.                     Log.e(TAG, e.getMessage(), e);  
  70.                 }  
  71.             }  
  72.         }  
  73.     }  
  74.     ... ...  
  75. }  
 

 

可以看出,MMS应用的方法是:先设置缩放选项,再读取缩放的图片数据到内存,规避了内存引起的OOM。

修改后的代码:

  1.     ContentResolver cr = this.getContentResolver();  
  2.     try  
  3.     {  
  4.         InputStream in = cr.openInputStream(uri);  
  5.            BitmapFactory.Options options = new BitmapFactory.Options();  
  6.            options.inJustDecodeBounds = true;  
  7.            BitmapFactory.decodeStream(in, null, options);  
  8.         try  
  9.         {  
  10.     in.close();  
  11. }  
  12.         catch (IOException e)  
  13.         {  
  14.     e.printStackTrace();  
  15. }  
  16.            int mWidth = options.outWidth;  
  17.            int mHeight = options.outHeight;  
  18.              
  19.            int sWidth  = 40;  
  20.            int sHeight = 40;  
  21.              
  22.         int s = 1;  
  23.         while ((mWidth / s > sWidth * 2) || (mHeight / s > sHeight * 2))  
  24.         {  
  25.             s *= 2;  
  26.         }  
  27.            options = new BitmapFactory.Options();  
  28.         options.inSampleSize = s;  
  29.         in = cr.openInputStream(uri);  
  30.         Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);  
  31.         try  
  32.         {  
  33.     in.close();  
  34. }  
  35.         catch (IOException e)  
  36.         {  
  37.     e.printStackTrace();  
  38. }  
  39.         if(null  == bitmap)  
  40.         {  
  41.             Toast.makeText(this"Head is not set successful,Decode bitmap failure"2000);  
  42.             return ;  
  43.         }  
  44.         //原始图片的尺寸  
  45.         int bmpWidth  = bitmap.getWidth();  
  46.         int bmpHeight = bitmap.getHeight();  
  47.           
  48.         //缩放图片的尺寸  
  49.         float scaleWidth  = (float) sWidth / bmpWidth;  
  50.         float scaleHeight = (float) sHeight / bmpHeight;  
  51.         Matrix matrix = new Matrix();  
  52.         matrix.postScale(scaleWidth, scaleHeight);  
  53.           
  54.         //产生缩放后的Bitmap对象  
  55.         Bitmap resizeBitmap = Bitmap.createBitmap(  
  56.             bitmap, 00, bmpWidth, bmpHeight, matrix, false);  
  57.         bitmap.recycle();  
  58.                 Bitmap resizeBitmap = bitmap;  
  59.         //Bitmap to byte[]  
  60.         byte[] photoData = bitmap2Bytes(resizeBitmap);  
  61.           
  62.         //save file  
  63.         String fileName = "/sdcard/test.jpg";  
  64.         FileUtil.writeToFile(fileName, photoData);  
 

 

  1. private byte[] bitmap2Bytes(Bitmap bm)  
  2. {  
  3.     ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  4.     bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
  5.     return baos.toByteArray();  
  6. }  
 

 

OVER!

posted on 2010-12-14 23:10 Xu Jianxiang 阅读(4039) 评论(0)  编辑  收藏 所属分类: Android

只有注册用户登录后才能发表评论。


网站导航: