Canvas绘图缓存位图略有模糊或具有抗锯齿功能

时间:2011-06-08 12:13:23

标签: android

在我的应用程序中,我已经推出了自己的SVG转换器,它将原始SVG XML文件转换为一系列图形矢量对象(Paint,Path等),然后应用于Canvas。首先将SVG数据与路径列表等一起转换为一种字节码格式,这意味着初始XML解析仅进行一次,然后每次重绘SVG图形可以相当快地进行。 SVG转换在运行时完成的事实使我能够对各种图形元素执行一些程序操作。例如,我可以在Inkscape中绘制图形温度计,并且在运行时代码操纵仪表的刻度并移动指针。这就是为什么我需要绘制静态背景图形以及使用矢量运算来移动图形,而不是编译静态位图。无论如何,这是我正在做的一些背景信息;我将转到实际的问题。

假设一个典型的仪表小部件由两个重叠的视图组成。背景视图包含使用路径绘制的静态图形(仪表的圆形面,数字图例,刻度线)。前景视图包含需要经常重绘的指针的图形。每个小部件都可能使用RelativeLayout来包含这些子视图。

我意识到每当为前景指针View调用onDraw()时,就会为位于它后面的背景视图调用onDraw。因此,为了优化窗口小部件重绘时间,我尝试将Canvas的绘图缓存用于后台视图。我所做的工作确实有效,并且可以提高重绘速度,但问题是我保存的缓存位图以及之后重新绘制到Canvas的缓存位图从来没有像最初使用Paths绘制的那样锐利。

我在onDraw()方法中用于后台View的基本代码是:

Bitmap bm = null;

onDraw(Canvas canvas){

    if(bm!=null){
        Paint bitmapPaint = new Paint();
        bitmapPaint.setAntiAlias(false);
        bitmapPaint.setFilterBitmap(false);
        bitmapPaint.setDither(false);
        canvas.drawBitmap(bm, 0, 0, bitmapPaint);

        return;             
    }


    ... Vector drawing to the Canvas using Path objects happens here,
        performed by the SVG converter object ... 


    setDrawingCacheEnabled(true);   
    setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
    bm = Bitmap.createBitmap(getDrawingCache());
}

为了尽量提高位图的质量,我做了以下事情:

  1. 确保缓存绘图质量很高。

  2. 在绘制位图时禁用了具有反别名,抖动等的Paint对象(bitmapPaint)。

  3. 知道位图的任何缩放会立即影响其质量,我(希望)确保不需要执行位图缩放。我已将View的大小设置为原始SVG图像的大小,这意味着我的SVG转换器代码不会对Canvas应用任何缩放。 scale()调用总是由SVG转换器执行,但在目前的情况下,它使用参数canvas.scale(1,1)。如果我故意将视图的宽度/高度更改为与原始SVG图像的宽度/高度不匹配,则Canvas缩放不再是1,1然后对位图的进一步质量损失非常明显。

  4. 所以我的主要问题是,我上面使用的代码是否有任何错误来使用绘图缓存位图?我觉得有些密度/比例发生在我不知道的位图上,即使它出现在屏幕上的尺寸与我绘制的原始图形完全相同。

    此外(可能超出主要问题的范围)是否还有其他技术可以避免在有前景移动图形时重绘背景矢量图形?据我所知,到目前为止,使用位图缓存是我所知道的唯一方法。

    提前致谢;任何建议将不胜感激。

    崔佛

1 个答案:

答案 0 :(得分:3)

我很高兴地说问题现在已经解决了。我意识到首先传递给onDraw()的Canvas已经应用了一些缩放。这种缩放存在的事实是降低了位图的质量。但我无法理解为什么Canvas应该已经有了一些扩展。

我在这里发布了另一个问题:In the onDraw() method, why does the supplied Canvas already have scale?。接受的答案表明我可能没有指定android:minSdkVersion。的确,我没有这么愚蠢。一旦我指定了minSdkVersion,缓存位图现在就能很好地绘制。令人惊讶的是,直到现在我还没有意识到我正在绘制的图像到手机的正确屏幕分辨率;由于缺乏minSdkVersion,它们都被缩放。

由于adamp的信用!