更多内存优化版本的Bitmap.createScaledBitmap?

时间:2019-07-10 02:21:13

标签: java android bitmap surfaceview

我完全理解“过早的优化是万恶之源。”但是,我已经达到了一个点,我认为我希望做的优化不再被视为“过早的优化”。 “。

我正在编写一个Android应用程序,其中包括从USB设备流式传输实时图像提要,使用OpenCV执行一些图像处理,将帧转换为位图,然后将该位图实时渲染为SurfaceView。时间。

我一切正常,(实时提要已正确呈现到SurfaceView),Android Studio的“ Profiler”工具表明我已经做好了内存管理(请注意,垃圾收集器不会在下面显示的10秒):

enter image description here

但是,由于我正在流式传输的图像是低分辨率(320x180),因此当我直接将其渲染到SurfaceView时,实际上实际上在设备的屏幕上最终变得很小。

因此,我决定将位图缩放到适合SurfaceView的最大大小,然后再将其渲染到屏幕上。但是,这样做之后,我惊恐地发现现在的内存使用情况图表看起来太可怕了! (垃圾收集器每秒运行一次以上!

enter image description here

以下是相关的代码段:

  • 在缩放位图(干净的内存图)之前:

    canvas = getHolder().lockCanvas();
    openCvMat = frameQueue.take();
    Utils.matToBitmap(openCvMat, bitmapFromMat);
    mat.release();
    canvas.drawColor(Color.BLACK);
    canvas.drawBitmap(bitmapFromMat, 0, 0, null);
    getHolder().unlockCanvasAndPost(canvas);
    
  • 缩放位图(可怕的内存图)后:

    canvas = getHolder().lockCanvas();
    openCvMat = frameQueue.take();
    Utils.matToBitmap(openCvMat, bitmapFromMat);
    mat.release();
    canvas.drawColor(Color.BLACK);
    Bitmap scaled = scaleBitmapToViewport(bitmapFromMat);
    canvas.drawBitmap(scaled, 0, 0, null);
    scaled.recycle();
    getHolder().unlockCanvasAndPost(canvas);
    
  • scaleBitmapToViewport()方法:

    private Bitmap scaleBitmapToViewport(Bitmap bitmap)
    {
        //Landscape
        if((canvas.getHeight() * aspectRatio) < canvas.getWidth())
        {
            return Bitmap.createScaledBitmap(bitmap, (int) Math.round(canvas.getHeight() * aspectRatio), canvas.getHeight(), true);
        }
        else //Portrait
        {
            return Bitmap.createScaledBitmap(bitmap, canvas.getWidth(), (int) Math.round(canvas.getWidth() / aspectRatio), true);
        }
    }
    

所以看来Bitmap.createScaledBitmap()是元凶。有谁知道另一种方法来完成相同的工作,而这并不能使垃圾收集器赚钱呢?

1 个答案:

答案 0 :(得分:0)

与其像您一样缩放位图本身,还不能在绘制时缩放吗?

我正在查看canvas.drawBitmap(位图位图,Rect src,Rect dst和Paint paint)-请注意,它同时包含源矩形和目标矩形。

您需要将源设置为(小)图像尺寸,将目标设置为表面尺寸。