Canvas antialiasing with hardware acceleration (Android API 11 and Later)

妖精的绣舞 提交于 2019-11-30 15:54:28

问题


I have a simple bitmap that I draw within a canvas & that I rotate using a matrix.

The problem I bump into is that using hardware acceleration the edges are not anti-aliased when rotated (this is working perfectly with Hardware acceleration turning off). And of course things like “setDrawFilter” are useless as they are ignored when hardware acceleration is turned on!

canvas.setDrawFilter(new PaintFlagsDrawFilter(1, Paint.ANTI_ALIAS_FLAG));

Am I missing something or is it just a limitation of the hardware rendering method ? Is there any alternative?


回答1:


Setting the antialias flag on the paint would not help anyway. To get antialiased borders on bitmap when rotating them you should add a 1px transparent border around them.




回答2:


Adding this 1px transparent border is not as easy as I thought. Adding it at runtime is really messy. My app loads a lot of bitmap and to add this border I need to allocate even more bitmap to redraw them. This really bust the heap but as I took good care with avoiding any memory leak, it´s working as intended. What’s really killing me is the “lags” that this has introduced. I tracked down this fluidity lost to the GC. This last one seems to be slowing down the UI Thread when he claim back the recycled bitmaps. Using a cache is not the solution either. This is the best way towards performance but storing 500x500 PNGs (alpha obliged) is way out of proportion. So, here I am, hitting the wall. I haven’t yet tried a “draw time” way but my guess is that drawing to an off-screen bitmap buffer that I don’t think will be HW acc. (correct me if I’m wrong) won’t help my cause.

The Idea of having an “AA shader” is really seducing and I see here several advantage. It’s well supported by the hardware acceleration, will of course be a marvel for the memory (no more savage bitmap allocation) and could be totally independent from the bitmap scaling. I made a quick test and this is by far the best AA (and here I mean in quality) I ever manage to get and … it’s fast… This quick wrap-up do an upper edge AA using shaders.

        BitmapShader bitmapShader = new BitmapShader(mBitmap,
                TileMode.CLAMP, TileMode.CLAMP);
        Matrix m = new Matrix(); 
        m.postTranslate(0, 1); 
        bitmapShader.setLocalMatrix(m); 

        final LinearGradient AAshader = new LinearGradient(0, 0, 0, 1, 0x00000000, 0xffffffff, TileMode.CLAMP);

        ComposeShader compositor = new ComposeShader(bitmapShader,
                AAshader, PorterDuff.Mode.DST_IN);

        mPaint.setShader(compositor);
        canvas.drawRect(this.getBounds(), mPaint);

Now the big drawback ! How to get a 4 edge AA :) ??? We can probably manage an upper/lower edge AA using a multi steps Gradient but this is still dirty. A nice way will be to combine the source bitmap with some kind of 9-patch to get the transparent border, but we cannot compose 2 bitmapShader… So, here I am once again. How to get this mask Shader! Damn wall ;)




回答3:


Fix that worked in my case:

private void fixAntiAlias(View viewFromThe80s) {
    if (Build.VERSION.SDK_INT > 10) {
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
        viewFromThe80s.setLayerType(View.LAYER_TYPE_SOFTWARE, p);
        ((View) viewFromThe80s.getParent()).setLayerType(View.LAYER_TYPE_SOFTWARE, p);
    }
}

Details:

My textview used a 9-patch as a background so I couldn't add a transparent 1px border without impacting the 9-patch pixels. So, instead, I was able to get this working by disabling hardware acceleration for the given view and its parent:

I'm calling this right after view inflation. Specifically in onCreateViewHolder in my case (in the viewholder constructor to be exact). This fixes my rotated TextView which uses a NinePatchDrawable background, similar to the following:

<TextView
    android:id="@+id/text_new_feature"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:rotation="-30"
    android:background="@drawable/background_new_feature"/>


来源:https://stackoverflow.com/questions/9730249/canvas-antialiasing-with-hardware-acceleration-android-api-11-and-later

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!