Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android中高效地组合位图_Android_Image_Performance_Memory_Bitmap - Fatal编程技术网

如何在Android中高效地组合位图

如何在Android中高效地组合位图,android,image,performance,memory,bitmap,Android,Image,Performance,Memory,Bitmap,我目前正在尝试创建一个小助手类,它可以从多个图像中生成一个图像。它应该取屏幕的大小,取所有图像的相等部分,然后将它们组合成一个单独的图像,其中有一小块并排的所有图像 到目前为止,我的班级成功地创造了这样一个形象。我唯一的问题是在我创建了这个图像之后,使用了大量的内存。在我创建了那个映像之后,你有什么建议可以提高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;
    }
}
私有LruCache-mMemoryCache;
私有列表ID=new ArrayList();
私密任务;
专用void组合图像(布尔值useScreenSize){
如果(任务!=null)
任务。取消(true);
任务=新组合任务(使用屏幕大小);
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.hyboone){
task.executeOnExecutor(异步task.THREAD\u POOL\u EXECUTOR);
}否则{
task.execute();
}
}
类CombinerTask扩展了AsyncTask{
屏幕大小的私有布尔值;
公共组合任务(布尔值useScreenSize){
this.useScreenSize=useScreenSize;
}
@凌驾
受保护位图doInBackground(无效…无效){
位图覆盖;
如果(使用屏幕大小){
WindowManager wm=(WindowManager)ImageCombiner.getInstance().getSystemService(Context.WINDOW\u服务);
Display Display=wm.getDefaultDisplay();
点大小=新点();
display.getSize(size);
对于(int x=0;x

欢迎提出任何建议。祝你度过愉快的一天。

我将自己回答这个问题,因为我能够将所需的内存量从70Mib减少到2Mib。我做的很简单。我没有在我的代码中放大我的图像,我只采用它与屏幕的纵横比。缩放将由ImageView本身完成。这节省了近60%的内存

此外,我现在在使用后直接回收大部分位图,一旦所有作业完成,LruCache将被逐出

下面是我更新的代码(这不是最终的,但比以前好得多):

private void组合图像(布尔值useScreenSize){
如果(任务!=null)
任务。取消(true);
任务=新组合任务(使用屏幕大小);
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.hyboone){
task.executeOnExecutor(异步task.THREAD\u POOL\u EXECUTOR);
}否则{
task.execute();
}
}
类CombinerTask扩展了AsyncTask{
屏幕大小的私有布尔值;
公共组合任务(布尔值useScreenSize){
this.useScreenSize=useScreenSize;
}
@凌驾
受保护位图doInBackground(无效…无效){
如果(!mMemoryCache.get(IDs.get(0)).isRecycled()){
位图覆盖;
如果(使用屏幕大小){
WindowManager wm=(WindowManager)ImageCombiner.getInstance().getSystemService(Context.WINDOW\u服务);
Display Display=wm.getDefaultDisplay();
点大小=新点();
display.getSize(size);
对于(int x=0;x缩放因子宽度){
temp=Bitmap.createScaledBitmap(mMemoryCache.get(id.get(x)),(int)(宽度*scaleFactorHeight),(int)(高度*scaleFactorHeight),false);
位图裁剪=Bitmap.createBitmap(temp,0,0,size.x,size.y);
温度循环();
temp=Bitmap.createScaledBitmap(裁剪,(int)((float)裁剪.getWidth()/scaleFactorHeight),(int)((float)裁剪.getHeight()/scaleFactorHeight),false);
crapped.recycle();
}否则
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();
    }
}