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

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

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

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

view plain copy to clipboard print ?
  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. float scaleWidth = (float) 40 / bmpWidth;
  23. float scaleHeight = (float) 40 / bmpHeight;
  24. Matrix matrix = new Matrix();
  25. matrix.postScale(scaleWidth, scaleHeight);
  26. //产生缩放后的Bitmap对象
  27. Bitmap resizeBitmap = Bitmap.createBitmap(
  28. bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);
  29. bitmap.recycle();
  30. //Bitmap to byte[]
  31. byte[] photoData = Bitmap2Bytes(resizeBitmap);
  32. //save file
  33. String fileName = "/sdcard/test.jpg";
  34. FileUtil.writeToFile(fileName, photoData);
  35. //save photo check sum to db
  36. DataCenter.GetInstance().ModifyIMMUser();
  37. //refresh ImageView
  38. }
  39. catch (FileNotFoundException exp)
  40. {
  41. exp.printStackTrace();
  42. }

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

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

view plain copy to clipboard print ?
  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。

修改后的代码:

view plain copy to clipboard print ?
  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. int sWidth = 40;
  19. int sHeight = 40;
  20. int s = 1;
  21. while ((mWidth / s > sWidth * 2) || (mHeight / s > sHeight * 2))
  22. {
  23. s *= 2;
  24. }
  25. options = new BitmapFactory.Options();
  26. options.inSampleSize = s;
  27. in = cr.openInputStream(uri);
  28. Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
  29. try
  30. {
  31. in.close();
  32. }
  33. catch (IOException e)
  34. {
  35. e.printStackTrace();
  36. }
  37. if(null == bitmap)
  38. {
  39. Toast.makeText(this, "Head is not set successful,Decode bitmap failure", 2000);
  40. return ;
  41. }
  42. //原始图片的尺寸
  43. int bmpWidth = bitmap.getWidth();
  44. int bmpHeight = bitmap.getHeight();
  45. //缩放图片的尺寸
  46. float scaleWidth = (float) sWidth / bmpWidth;
  47. float scaleHeight = (float) sHeight / bmpHeight;
  48. Matrix matrix = new Matrix();
  49. matrix.postScale(scaleWidth, scaleHeight);
  50. //产生缩放后的Bitmap对象
  51. Bitmap resizeBitmap = Bitmap.createBitmap(
  52. bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);
  53. bitmap.recycle();
  54. Bitmap resizeBitmap = bitmap;
  55. //Bitmap to byte[]
  56. byte[] photoData = bitmap2Bytes(resizeBitmap);
  57. //save file
  58. String fileName = "/sdcard/test.jpg";
  59. FileUtil.writeToFile(fileName, photoData);

view plain copy to clipboard print ?
  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. }

更多相关文章

  1. Android(安卓)Jamendo开源在线音乐播放器源码分析七 数据缓存和
  2. Android(安卓)之 Bitmap
  3. android百度地图:MapController
  4. Android实现图片 高斯模糊,以及图片镜像 翻转。
  5. Android(安卓)播放 Gif 图片控件
  6. Android实现从网络获取图片显示并保存到SD卡的方法
  7. Android(安卓)在 TextView 中设置超链接、颜色、字体、图片
  8. Android(安卓)Volley之加载网络图片
  9. android中listView实现异步加载网络图片

随机推荐

  1. Android(安卓)TabActivity实现多页显示效
  2. 常用对话框部分属性
  3. android SDCARD 读写操作
  4. Android从下往上(动画)滑出窗口
  5. Android(安卓)linux kernel privilege es
  6. TabLayout修改字体大小
  7. Android之Init进程
  8. 发送短信之分割短信 SMSManager
  9. android recycler添加分割线 点击事件等
  10. android 完全关闭进程