0

我花了很多时间来了解如何在没有内存不足异常的情况下缩放图像,我想分享我的知识,我编写了将图像(从大到小)缩放到精确大小的函数。算法是:

  1. 我们使用尽可能匹配的快速算法缩放图像,但图像的尺寸仍应大于所需的尺寸。
  2. 我们将图像缩放到精确的结果大小。

该功能注释很好,因此很容易理解。如果您发现错误或者您知道如何使其更正确和更快,请发表评论。

4

1 回答 1

2

享受!

//this function change image size(from big to small) using low memory(as possible)
//the bigger side of result image will equals to IMAGE_BIGGER_SIDE_SIZE
//and second side will be scaled proportionally
//for example if you have image 800x400 and call decodeBitmapSize(bm, 200)
//you will receive image 200x100
//algorithm:
//1. we scale image using quick algorihtm as match as possible, 
//   but image will still has sizes more then required
//2. we scale image to exactly result size
public static Bitmap decodeBitmapSize(Bitmap bm, int IMAGE_BIGGER_SIDE_SIZE){

      //we will return this Bitmap  
      Bitmap b = null;          


      //convert Bitmap to byte[]
      ByteArrayOutputStream stream = new ByteArrayOutputStream();
      bm.compress(Bitmap.CompressFormat.JPEG, 100, stream);
      byte[] byteArray = stream.toByteArray();

      //We need to know image width and height, 
      //for it we create BitmapFactory.Options object  and do BitmapFactory.decodeByteArray
      //inJustDecodeBounds = true - means that we do not need load Bitmap to memory
      //but we need just know width and height of it
      BitmapFactory.Options opt = new BitmapFactory.Options();          
      opt.inJustDecodeBounds = true;
      BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, opt);
      int CurrentWidth = opt.outWidth;
      int CurrentHeight = opt.outHeight;


      //there is function that can quick scale images
      //but we need to give in scale parameter, and scale - it is power of 2
      //for example 0,1,2,4,8,16...
      //what scale we need? for example our image 1000x1000 and we want it will be 100x100
      //we need scale image as match as possible but should leave it more then required size
      //in our case scale=8, we receive image 1000/8 = 125 so  125x125, 
      //scale = 16 is incorrect in our case, because we receive 1000/16 = 63 so 63x63 image 
      //and it is less then 100X100
      //this block of code calculate scale(we can do it another way, but this way it more clear to read)
      int scale = 1;
      int PowerOf2 = 0;
      int ResW = CurrentWidth;
      int ResH = CurrentHeight;
      if (ResW > IMAGE_BIGGER_SIDE_SIZE || ResH > IMAGE_BIGGER_SIDE_SIZE) {
          while(1==1)
          {
              PowerOf2++;
              scale = (int) Math.pow(2,PowerOf2);
              ResW = (int)((double)opt.outWidth / (double)scale);
              ResH = (int)((double)opt.outHeight / (double)scale);
              if(Math.max(ResW,ResH ) < IMAGE_BIGGER_SIDE_SIZE)
              {
                  PowerOf2--;
                  scale = (int) Math.pow(2,PowerOf2);
                  ResW = (int)((double)opt.outWidth / (double)scale);
                  ResH = (int)((double)opt.outHeight / (double)scale);
                  break;
              }

          }
      }




      //Decode our image using scale that we calculated
      BitmapFactory.Options opt2 = new BitmapFactory.Options();
      opt2.inSampleSize = scale; 
      b = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, opt2);


      //calculating new width and height
      int w = b.getWidth();
      int h = b.getHeight();
      if(w>=h)
      {
          w = IMAGE_BIGGER_SIDE_SIZE;
          h =(int)( (double)b.getHeight() * ((double)w/b.getWidth()));
      }
      else
      {
          h = IMAGE_BIGGER_SIDE_SIZE;
          w =(int)( (double)b.getWidth() * ((double)h/b.getHeight()));
      }


      //if we lucky and image already has correct sizes after quick scaling - return result
      if(opt2.outHeight==h && opt2.outWidth==w)
      {
          return b;
      }


      //we scaled our image as match as possible using quick method
      //and now we need to scale image to exactly size
      b = Bitmap.createScaledBitmap(b, w,h,true);   


      return b;
  }
于 2013-04-04T15:24:06.813 回答