2015-09-23 22 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(); 
    } 
}