1

我正在开发一个相机应用程序,我在一个覆盖实时预览的小矩形(128x128 pix)中显示预览图像亮度直方图。

有时会发生 ANR,所以我开始使用 traceview 来优化我的代码(我正在即时进行一些图像处理,但它是非常快的 NEON asm 和本机代码,没问题)。

使用 traceview 我发现 Canvas.drawLine() 方法非常慢。我必须在 customView.onDraw() 中每秒更新直方图 30 次,每帧只绘制 128 条线。令人难以置信的是,绘制 128 条线需要 >8% 的 cpu 时间(!!),当整个原生代码操作转换整个帧(720x480 yuv 到 ARGB_8888)需要 <18%

我试图在新的位图画布上绘制直方图,然后将它 drawBitmap() 绘制到视图的画布上,但 drawLine()s 仍然占用大量 CPU。

我正在寻找一个避免drawLine()的想法......

我必须从标准化为 128 的 int[128] 绘制一个小直方图

这是我的 customView.onDraw (或多或少......)

@Override 
protected void onDraw(Canvas canvas) {
    int size = 128;
    int y = pos_y + size;
    int x;
    for(int i=0;i<size;i++) {
        if(histogram_data[i]>1) {
            x = pos_x+i;

            // this is the slow call!!
            canvas.drawLine(x, y, x, y-histogram_data[i], paint_histogram);
        }
    }
}
4

3 回答 3

0

您可以尝试使用路径而不是线条。

http://developer.android.com/reference/android/graphics/Path.html

于 2013-08-17T14:59:15.460 回答
0

如果您在这里阅读,他们会说以下内容:

动画大路径

当在传递给 Views 的硬件加速 Canvas 上调用 Canvas.drawPath() 时,Android 首先在 CPU 上绘制这些路径,然后将它们上传到 GPU。如果您有大路径,请避免逐帧编辑它们,以便可以有效地缓存和绘制它们。drawPoints()、drawLines() 和 drawRect/Circle/Oval/RoundRect() 更有效——即使您最终使用更多绘图调用,也最好使用它们。

因此,您可以尝试调用一次 drawLines() 来同时绘制多条线,而不是分别为每条线调用 drawLine()。

就我个人而言,我必须画 500 多条线,我尝试了所有可用的在画布中画线的方法:drawPath()、drawLine() 和 drawLines(),但我觉得所有这些方法在我的手机上都非常滞后,所以唯一可用的替代方法是使用 OpenGL ES。这是我使用 OpenGL 编写的用于绘制大量线条的示例,我在手机上对其进行了测试,它像黄油一样光滑。您可以查看它用 Kotlin 编写的源代码,它还支持手指手势,这样您就可以用手指缩放、平移和旋转整个场景。我已经包含了所有基本形状矩形、三角形、圆形、线、多边形,您可以将形状坐标设置为 [-1,1] 之间的值,或者使用像素值的熟悉方式。如果您想了解有关 OpenGL 的更多信息,可以查看android 团队的这篇文章

这是我编写的 OpenGL 示例的结果:

在此处输入图像描述

于 2020-05-08T11:21:58.493 回答
-1

也许您可以在顶部添加新图层并仅绘制这 128 条线一次,同时让其他像素保持透明。

于 2013-08-18T21:09:30.560 回答