Jos*_*arl 35 graphics android drawing hardware-acceleration porter-duff
我有一个视图,它做了一些基本的绘图.在此之后,我想绘制一个打孔的矩形,这样只能看到上一个图形的一个区域.我想为我的视图启用硬件加速以获得最佳性能.
目前我有两种方法可以工作,但只有在禁用硬件加速时才有效,而另一种方法太慢.
方法1:SW加速(慢)
final int saveCount = canvas.save();
// Clip out a circle.
circle.reset();
circle.addCircle(cx, cy, radius, Path.Direction.CW);
circle.close();
canvas.clipPath(circle, Region.Op.DIFFERENCE);
// Draw the rectangle color.
canvas.drawColor(backColor);
canvas.restoreToCount(saveCount);
Run Code Online (Sandbox Code Playgroud)
这不适用于为视图启用的硬件加速,因为在此模式下不支持'canvas.clipPath'(我知道我可以强制SW渲染,但我想避免这种情况).
方法2:硬件加速(V.慢速)
// Create a new canvas.
final Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
final Canvas c = new Canvas(b);
// Draw the rectangle colour.
c.drawColor(backColor);
// Erase a circle.
c.drawCircle(cx, cy, radius, eraser);
// Draw the bitmap on our views canvas.
canvas.drawBitmap(b, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)
橡皮擦创建的地方
eraser = new Paint()
eraser.setColor(0xFFFFFFFF);
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
Run Code Online (Sandbox Code Playgroud)
这显然很慢 - Bitmap每次绘图调用都会创建一个新的视图大小.
方法3:硬件加速(快速,在某些设备上不起作用)
canvas.drawColor(backColor);
canvas.drawCircle(cx, cy, radius, eraser);
Run Code Online (Sandbox Code Playgroud)
与HW加速兼容方法相同,但不需要额外的画布.但是这有一个主要的问题 - 它适用于SW渲染强制,但在HTC One X(Android 4.0.4 - 可能还有其他一些设备)上至少启用了HW渲染它会使圆圈完全变黑.这可能与22361有关.
方法4:硬件加速(可接受,适用于所有设备)
根据Jan关于改进方法2的建议,我避免在每次调用时创建位图onDraw,而是在onSizeChanged:
if (w != oldw || h != oldh) {
b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
c = new Canvas(b);
}
Run Code Online (Sandbox Code Playgroud)
然后只使用这些onDraw:
if (overlayBitmap == null) {
b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
c = new Canvas(b);
}
b.eraseColor(Color.TRANSPARENT);
c.drawColor(backColor);
c.drawCircle(cx, cy, radius, eraser);
canvas.drawBitmap(b, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)
性能不如方法3好,但比2好得多,略好于1.
这个问题
如何以与HW加速兼容的方式实现相同的效果(AND在设备上一致地工作)?提高SW渲染性能的方法也是可以接受的.
注意:当移动圆圈时,我只是使一个区域无效 - 而不是整个画布 - 所以那里没有改进性能的空间.
Joh*_*rak 18
您应该能够分配一次,然后在每次重绘时重复使用画布,而不是在每次重绘时分配新画布.
在init和on resize上:
Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Run Code Online (Sandbox Code Playgroud)
重画:
b.eraseColor(Color.TRANSPARENT);
// needed if backColor is not opaque; thanks @JosephEarl
c.drawColor(backColor);
c.drawCircle(cx, cy, radius, eraser);
canvas.drawBitmap(b, 0, 0, null);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9906 次 |
| 最近记录: |