美文网首页
Android Bitmap擦除后留下黑色背景(硬件加速相关)

Android Bitmap擦除后留下黑色背景(硬件加速相关)

作者: Rimson | 来源:发表于2018-12-25 15:06 被阅读0次

需求和问题

需求是在一个自定义view中放置两张重叠的bitmap,然后局部擦除顶部的那一张图,以此可以看到底部的图片。

大致思路:

    //底部的图片已经通过其他方式绘制完成
    canvas.drawBitmap(topBitmap, 0f, 0f, null)
    // 画笔的建立需要在onDraw外面执行,这里为了叙述方便才放在这里
    val clearPaint = Paint() 
    clearPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.XOR)
    canvas.drawCircle(x, y, r, clearPaint)

但是并没有出现预期的效果,在drawCircle的地方,显示的背景为黑色,并不能看到底部的背景图。

网上的说法

1. 图片的格式问题,JPEG不支持透明。

但是这里并没有用到图片本身的透明属性,而是将整个canvas或是bitmap“设置为透明”。另外,按照这种说法,所有设置透明度时只能使用png格式的图片,不符合现实状况,也不利于用户使用。

2. Bitmap.Config

顺便复习一下

Possible bitmap configurations. A bitmap configuration describes how pixels are stored. This affects the quality (color depth) as well as the ability to display transparent/translucent colors.
这个属性代表了Bitmap可以的配置情况。一个配置描述的是这些像素信息是如何存储的。这个影响到了图片质量和透明度。

ALPHA_8:Each pixel is stored as a single translucency (alpha) channel.

每个像素信息只存储了alpha这一项信息。

ARGB_4444:This field was deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead.

这个值在level 13的时候就已经不被建议使用了,因为这是一个低质量的配置,建议使用ARGB_8888

ARGB_8888:Each pixel is stored on 4 bytes. This configuration is very flexible and offers the best quality. It should be used whenever possible.

每个像素信息占用4个字节(即32个二进制位)的存储空间,alpha、red、green、blue各占8个二进制位。这个配置项是非常灵活,并提供了最好的质量。他应该在可能的情况下尽量被使用。

RGB_565:Each pixel is stored on 2 bytes and only the RGB channels are encoded: red is stored with 5 bits of precision (32 possible values), green is stored with 6 bits of precision (64 possible values) and blue is stored with 5 bits of precision.This configuration may be useful when using opaque bitmaps that do not require high color fidelity

每个像素信息占用2个字节(即16位二进制位)并且至存储了RGB的信息没有alpha信息,其中Red5位,Green6位,Blue5位。这个配置项在不需要提供透明度的情况下更有用。

这个说法不恰当的理由,跟png格式如出一辙。

3. 硬件加速的问题

在构造函数中(Kotlin选手在init方法中)关闭硬件加速:

setLayerType(View.LAYER_TYPE_SOFTWARE, null)

问题解决!

探究原因

有关硬件加速

从Android 3.0(API Level 11)开始,Android支持硬件加速,从Android 4.0开始,手机支持。硬件加速可充分利用GPU的特性,使得界面渲染更加平滑,但是会消耗更多内存RAM。硬件加速自身并非完美,在某些Android 5的rom上,由于内存RAM分配的问题,如果代码不当,会引发闪屏、花屏等渲染问题。

1.Android3.0(API level 11)开始,2D渲染管道支持硬件加速,也就是说绘制操作可以使用GPU绘制在View的canvas上。使用硬件加速需要更多的资源,所以app会消耗更多内存。

2.硬件加速在Target API >= 14时是默认开启的。

3.硬件加速还不支持所有的2D绘图命令,开启后可能会影响自定义View和绘图操作。异常通常是不可见元素、运行异常、或者错误的像素点。

4.如果只使用系统的View和Drawable,则没有任何副作用。

5.如果app里有自定义的绘图操作,需要在开启硬件加速的设备上测试来发现问题。

控制硬件加速

可以在4个级别上控制硬件加速

Application:(AndroidManifest.xml)

 <application
        ...
        android:hardwareAccelerated="true"
       ...
        >

Activity:(AndroidManifest.xml)

<activity
            android:name=".MainActivity"
            android:hardwareAccelerated="true">

Window

window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
            WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)

View

setLayerType(View.LAYER_TYPE_SOFTWARE, null)

在这四个级别上,Application和Activity是可以自由控制开关的,Window只能控制打开,View只能控制关闭。(在自己的例子中就是关闭了view的硬件加速)

我的问题通过这个小技巧解决了,还没有深入学习原理,但希望可以帮到他人。

参考文章:
Stack Overflow
Android 硬件加速使用总结

相关文章

网友评论

      本文标题:Android Bitmap擦除后留下黑色背景(硬件加速相关)

      本文链接:https://www.haomeiwen.com/subject/vgbxlqtx.html