Android decodeByteArray在自己的线程上非常慢但在线程

时间:2015-07-21 17:10:30

标签: java android multithreading bitmap bitmapfactory

我实际上是在开发基于相机的项目。我正在添加一个队列,从相机中预览来自 onPreviewFrame 的帧,我在一个正在运行的线程中回来处理并在SurfaceView中绘制它。 (我的目标是通过网络发送)。

我的问题是我的自定义线程上的BitmapFactory.decodeByteArray()函数非常慢,但在 UI线程上工作得很好:

这很好用:

    private void drawFromThread(final byte[] data) {

    size = mCamera.getPreviewSize();
    YuvImage yuvimage;
    yuvimage = new YuvImage(data, ImageFormat.NV21, size.width,size.height, null);
    ByteArrayOutputStream baos;
    baos = new ByteArrayOutputStream();
    yuvimage.compressToJpeg(new Rect(0, 0, size.width, size.height), 10,baos);  
    final byte[] jdata = baos.toByteArray();
    ((Activity)context).runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Bitmap bmp;
            bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
            Canvas canvas = contactView.getHolder().lockCanvas();
            canvas.drawBitmap(bmp, 0, 0, null);
            contactView.getHolder().unlockCanvasAndPost(canvas);
        }
    });
}

但是,这真的很慢:

    private void drawFromThread(final byte[] data) {

    size = mCamera.getPreviewSize();
    YuvImage yuvimage;
    yuvimage = new YuvImage(data, ImageFormat.NV21, size.width,
            size.height, null);
    ByteArrayOutputStream baos;
    baos = new ByteArrayOutputStream();
    yuvimage.compressToJpeg(new Rect(0, 0, size.width, size.height), 10,
            baos);
    final byte[] jdata = baos.toByteArray();
    Bitmap bmp;
    bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
    Canvas canvas = contactView.getHolder().lockCanvas();
    canvas.drawBitmap(bmp, 0, 0, null);
    contactView.getHolder().unlockCanvasAndPost(canvas);
}

我搜索了很多,但没有找到任何有同样问题的人。

我知道有最有效的方法来使用相机和SurfaceView,我有另一个surfaceView用于以“标准方式”显示我的相机帧。但我试图模拟我将从网络获取的帧并在SurfaceView上绘制它。

感谢您的时间。

2 个答案:

答案 0 :(得分:0)

我认为它看起来很慢,因为在慢速示例中你并没有在UI线程上做任何事情。由于运行更新的其他内容,以后可能会更新画布。相反,如果您在一个线程中进行计算,然后在UI中进行渲染,则应该具有更快的响应时间。

private void drawFromThread(final byte[] data) {

    size = mCamera.getPreviewSize();
    YuvImage yuvimage;
    yuvimage = new YuvImage(data, ImageFormat.NV21, size.width,size.height, null);
    ByteArrayOutputStream baos;
    baos = new ByteArrayOutputStream();
    yuvimage.compressToJpeg(new Rect(0, 0, size.width, size.height), 10,baos);  
    final byte[] jdata = baos.toByteArray();

    final Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
    ((Activity)context).runOnUiThread(new Runnable(){
        @Override
        public void run() {
            Canvas canvas = contactView.getHolder().lockCanvas();
            canvas.drawBitmap(bmp, 0, 0, null);
            contactView.getHolder().unlockCanvasAndPost(canvas);
        }
    });
}

注意"昂贵" decodeByteArray是在UI线程下完成的,但渲染是在UI线程上完成的。这不起作用吗?

答案 1 :(得分:0)

我发现了问题的来源。我正在推动Ui Thread的相机预览帧排队。我从另一个线程的队列中检索的帧。问题是Ui Thread在队列中每秒推送的帧数比其他线程每秒可以处理的帧数多。在Ui Thread上执行decodeByteArray会减慢它的速度,这可以让时间到另一个线程来绘制我的位图。 我改变了我正在使用的队列类型以使其更快并且仍然试图找到一种在我的线程中更快地渲染的方法。 如果有人有建议,我会接受。