【问题标题】:Canvas drawing cache bitmap is slightly blurred or has anti-alias画布绘图缓存位图略微模糊或有抗锯齿
【发布时间】:2011-06-10 21:58:49
【问题描述】:

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

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

我意识到,每当为前景指针 View 调用 onDraw() 时,就会为位于它后面的背景 View 调用 onDraw。因此,为了优化小部件重绘时间,我尝试将 Canvas 的绘图缓存用于背景视图。我所做的工作确实有效并导致重绘速度大大提高,但问题是我保存然后重绘到画布的缓存位图从来没有像最初使用路径绘制的那样清晰。

我在 onDraw() 方法中用于背景视图的基本代码是:

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. 知道位图的任何缩放都会立即影响其质量,我(希望)确保不需要执行位图的缩放。我已将视图的大小设置为与原始 SVG 图像的大小完全相同,这意味着我的 SVG 转换器代码不会对画布应用缩放。 scale() 调用始终由 SVG 转换器执行,但在当前情况下,它是使用参数 canvas.scale(1, 1) 进行的。如果我有意更改视图的宽度/高度以使其与原始 SVG 图像的宽度/高度不匹配,则画布缩放不再是 1,1,然后位图质量的进一步损失非常明显。

所以我的主要问题是,我上面用来使用绘图缓存位图的代码有什么问题吗?我有一种感觉,位图发生了某种我不知道的密度/比例,即使它出现在屏幕上的大小与我绘制的原始图形完全相同。

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

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

特雷夫

【问题讨论】:

    标签: android


    【解决方案1】:

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

    我在这里发布了另一个问题:In the onDraw() method, why does the supplied Canvas already have scale?。那里接受的答案表明我可能没有指定 android:minSdkVersion。确实,很愚蠢,我没有。一旦我指定了 minSdkVersion,缓存位图现在绘制得很漂亮。令人惊讶的是,直到现在我才意识到我正在绘制的图像不符合手机的正确屏幕分辨率。由于缺少 minSdkVersion,它们都被扩展了。

    adamp 的功劳!

    【讨论】:

    猜你喜欢
    • 2016-04-24
    • 2013-01-02
    • 2011-02-14
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多