2013-04-04 14 views
0

我花了很多時間來理解如何在沒有內存異常的情況下對圖像進行縮放,並且我想分享我的知識,我寫了將縮放圖像(從大到小)縮放到完全大小的函數。該算法是:Android。如何縮放圖像而無內存異常?

  1. 我們使用快速算法儘可能匹配縮放圖像,但圖像仍應具有更多所需的大小。
  2. 我們將圖像縮放到精確的結果大小。

該函數很好評論,所以很容易取消。如果你會發現錯誤,或者你知道如何使它更加正確和更快,請留下評論。

+0

你的方法提供的優於給定的Android開發人員處理位圖的文檔化方式? http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Grambot 2013-04-04 15:27:56

+1

這與谷歌推薦的方式完全相同,我只是在一個函數中寫了所有內容,並對它進行了很好的評論。 Google只給我們部分代碼,我給你準備使用的功能。在90%的情況下,當我們縮放圖像時,我們需要將圖像縮放到小方塊,這是在這裏完成的。 – 2013-04-04 15:41:17

回答

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; 
    }