2015-09-23 105 views
-1

我目前正在嘗試創建一個小幫手類,可以使多個圖像中的一個圖像。它應該採取屏幕的大小,並採取所有圖像的相等部分,然後將它們組合成一個單一的圖像並排顯示所有圖像的一小片。如何在Android中有效地結合位圖

到目前爲止,我的課程成功創建了這樣的圖像。我創建這個圖像後唯一的麻煩是使用RAM的數量。你有什麼建議,我可以提高RAM使用後,我創建該圖像? (我不想耗盡內存)也許我在創造圖像的方式浪費記憶(我打開更好的建議)。 重要的是要知道,我不能將這些圖像緩存在磁盤上,因爲它們永遠不會相同。

我注意到一旦我運行手動GC,RAM使用率從70MiB左右回到15MiB。

private LruCache<Integer, Bitmap> mMemoryCache; 
private List<Integer> IDs = new ArrayList<>(); 
private CombinerTask task; 

private void combineImages(boolean useScreenSize){ 
     if(task != null) 
      task.cancel(true); 
     task = new CombinerTask(useScreenSize); 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
     } else { 
      task.execute(); 
     } 
    } 

class CombinerTask extends AsyncTask<Void,Void,Bitmap>{ 
    private boolean useScreenSize; 

    public CombinerTask(boolean useScreenSize){ 
     this.useScreenSize = useScreenSize; 
    } 

    @Override 
    protected Bitmap doInBackground(Void...voids) { 
     Bitmap bmOverlay; 
     if(useScreenSize){ 
      WindowManager wm = (WindowManager) ImageCombiner.getInstance().getSystemService(Context.WINDOW_SERVICE); 
      Display display = wm.getDefaultDisplay(); 
      Point size = new Point(); 
      display.getSize(size); 

      for(int x = 0; x < IDs.size(); x++){ 
       float scaleFactor = (float)size.y/(float)mMemoryCache.get(IDs.get(x)).getHeight(); 
       Bitmap temp = Bitmap.createScaledBitmap(mMemoryCache.get(IDs.get(x)),(int)(mMemoryCache.get(IDs.get(x)).getWidth() * scaleFactor), (int)(mMemoryCache.get(IDs.get(x)).getHeight() * scaleFactor),false); 
       mMemoryCache.put(IDs.get(x),temp); 
      } 

      bmOverlay = Bitmap.createBitmap(size.x,size.y,mMemoryCache.get(IDs.get(0)).getConfig()); 
     }else { 
      bmOverlay = Bitmap.createBitmap(mMemoryCache.get(IDs.get(0)).getWidth(),mMemoryCache.get(IDs.get(0)).getHeight(),mMemoryCache.get(IDs.get(0)).getConfig()); 
     } 

     Canvas canvas = new Canvas(bmOverlay); 

     for(int i = 0; i < IDs.size(); i++){ 
      Bitmap bm = Bitmap.createBitmap(mMemoryCache.get(IDs.get(i)),mMemoryCache.get(IDs.get(i)).getWidth()/3,0,bmOverlay.getWidth()/mMemoryCache.size(),mMemoryCache.get(IDs.get(i)).getHeight()); 
      canvas.drawBitmap(bm,bm.getWidth()*i,0,null); 
      bm.recycle(); 
     } 
     canvas = null; 
     return bmOverlay; 
    } 

    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if(listener != null) 
      listener.combineFinished(bitmap); 
     for (int i = 0; i < IDs.size(); i++){ 
      mMemoryCache.get(IDs.get(i)).recycle(); 
     } 
     mMemoryCache = null; 
     IDs = null; 
    } 
} 

歡迎任何建議。祝你有美好的一天。

回答

0

我會自己回答這個問題,因爲我能夠將所需的內存從70Mib減少到2Mib。我做的很簡單。我的代碼只是將其用於屏幕寬高比,而不是在我的代碼中放大圖像。縮放將由ImageView本身完成。這節省了近60%的內存。

此外,我現在使用後直接回收大部分位圖,一旦完成所有作業,LruCache將被逐出。

這是我更新的代碼(這不是決賽,但一個更好的起點比前):

private void combineImages(boolean useScreenSize){ 
    if(task != null) 
     task.cancel(true); 
    task = new CombinerTask(useScreenSize); 
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
     task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
    } else { 
     task.execute(); 
    } 
} 

class CombinerTask extends AsyncTask<Void,Void,Bitmap>{ 
    private boolean useScreenSize; 

    public CombinerTask(boolean useScreenSize){ 
     this.useScreenSize = useScreenSize; 
    } 
    @Override 
    protected Bitmap doInBackground(Void...voids) { 
     if(!mMemoryCache.get(IDs.get(0)).isRecycled()) { 
      Bitmap bmOverlay; 
      if (useScreenSize) { 
       WindowManager wm = (WindowManager) ImageCombiner.getInstance().getSystemService(Context.WINDOW_SERVICE); 
       Display display = wm.getDefaultDisplay(); 
       Point size = new Point(); 
       display.getSize(size); 


       for (int x = 0; x < IDs.size(); x++) { 
        int width = mMemoryCache.get(IDs.get(x)).getWidth(); 
        int height = mMemoryCache.get(IDs.get(x)).getHeight(); 

        float scaleFactorWidth = 1f; 
        float scaleFactorHeight = 1f; 
        scaleFactorWidth = (float) size.x/(float) width; 
        scaleFactorHeight = (float) size.y/(float) height; 

        Bitmap temp = null; 
        if (scaleFactorHeight > scaleFactorWidth) { 
         temp = Bitmap.createScaledBitmap(mMemoryCache.get(IDs.get(x)), (int) (width * scaleFactorHeight), (int) (height * scaleFactorHeight), false); 
         Bitmap cropped = Bitmap.createBitmap(temp, 0, 0, size.x, size.y); 
         temp.recycle(); 
         temp = Bitmap.createScaledBitmap(cropped, (int) ((float) cropped.getWidth()/scaleFactorHeight), (int) ((float) cropped.getHeight()/scaleFactorHeight), false); 
         cropped.recycle(); 

        } else if (scaleFactorHeight < scaleFactorWidth) { 
         temp = Bitmap.createScaledBitmap(mMemoryCache.get(IDs.get(x)), (int) (width * scaleFactorWidth), (int) (height * scaleFactorWidth), false); 
         Bitmap cropped = Bitmap.createBitmap(temp, 0, 0, size.x, size.y); 
         temp.recycle(); 
         temp = Bitmap.createScaledBitmap(cropped, (int) ((float) cropped.getWidth()/scaleFactorWidth), (int) ((float) cropped.getHeight()/scaleFactorWidth), false); 
         cropped.recycle(); 
        } 
        if(mMemoryCache.get(IDs.get(x)) != null) 
         mMemoryCache.get(IDs.get(x)).recycle(); 
        mMemoryCache.put(IDs.get(x), temp); 
       } 

       bmOverlay = Bitmap.createBitmap(mMemoryCache.get(IDs.get(0)).getWidth(), mMemoryCache.get(IDs.get(0)).getHeight(), mMemoryCache.get(IDs.get(0)).getConfig()); 
      } else { 
       bmOverlay = Bitmap.createBitmap(mMemoryCache.get(IDs.get(0)).getWidth(), mMemoryCache.get(IDs.get(0)).getHeight(), mMemoryCache.get(IDs.get(0)).getConfig()); 
      } 

      Canvas canvas = new Canvas(bmOverlay); 

      for (int i = 0; i < IDs.size(); i++) { 
       Bitmap bm = Bitmap.createBitmap(mMemoryCache.get(IDs.get(i)), 0, 0, bmOverlay.getWidth()/mMemoryCache.size(), mMemoryCache.get(IDs.get(i)).getHeight()); 
       canvas.drawBitmap(bm, bm.getWidth() * i, 0, null); 
       bm.recycle(); 
      } 
      canvas = null; 
      return bmOverlay; 
     } 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if(listener != null && bitmap != null) 
      listener.combineFinished(bitmap); 
     for (int i = 0; i < IDs.size(); i++){ 
      if(mMemoryCache.get(IDs.get(i))!= null) 
       mMemoryCache.get(IDs.get(i)).recycle(); 
     } 
     mMemoryCache.evictAll(); 
     IDs.clear(); 
    } 
}