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 に答える