我一直在做游戏信息应用。它基本上显示我玩的游戏(和其他许多游戏)的统计数据和信息。这个游戏有动画,我设法制作了自己的
View
来绘制单位、敌人或任何组件的动画。由于绘图代码需要大量转换(缩放、旋转、平移等),因此我需要此自定义 View
进行硬件加速
如果我简单地解释一下动画的工作原理,它有一个包含多个部分图像的精灵表。我从精灵表中裁剪图像,并使用指定的角度、比例、x/y 位置等绘制每个裁剪部分。我不希望结果像素化,我启用了抖动和抗锯齿锯齿,并执行了如下所示的绘制图像
//Somewhere initializing Paint
paint = Paint()
paint.apply {
isFilterBitmap = true
isAntiAlias = true
isDither = true
}
//Somewhere drawing bitmap
fun drawImage(b: Bitmap, x: Float, y: Float, w: Float, h: Float) {
//m2 is Matrix
m2.reset()
c.setMatrix(m2)
val w = b.width.toFloat()
val h = b.height.toFloat()
val wr = d.toFloat() / w
val hr = e.toFloat() / h
m2.set(m)
m2.preTranslate((x-1).toFloat(), (y-1).toFloat())
m2.preScale(wr, hr)
c.drawBitmap(b, m2, paint)
}
到目前为止,它绘制得很好,但是当我放大动画查看器时,纹理没有得到正确的抗锯齿效果。纹理本身变得平滑,是的,但是当涉及到纹理边界时,它会被切断
检查图像的羽毛和上部。正如你所看到的,纹理并不显示平滑的像素,而是突然的截止效果。我想我看到了禁用硬件加速可以解决问题的解决方案,但如果我这样做,性能会比以前更差,所以我必须坚持使用硬件加速。根据我的知识,我假设当Android将位图绘制到
Canvas
时,Android在绘制纹理后不会抗锯齿,而是抗锯齿纹理本身,然后绘制已经抗锯齿的纹理,因此那些超出边界的像素由于抗锯齿效果,纹理被切断为了解决这个问题,我用了一点
dirty的方式。由于我对低级渲染(例如OpenGL等)没有深入的了解,所以我尝试的只是在裁剪图像的每一侧再添加一个像素,如下所示
fun getCroppedBitmap(src: Bitmap, x: Int, y: Int, w: Int, h: Int) : Bitmap {
return try {
//Crop image from source sprite sheet
val cropped = Bitmap.createBitmap(bit, x, y, w, h)
//Since each side has to have 1px appended, total width and height are w+2, and h+2
val appended = Bitmap.createBitmap(cropped.width + 2, cropped.height + 2, Bitmap.Config.ARGB_8888)
//Draw cropped image into appended, empty bitmap
//Be careful that cropped image must be drawn with 1px offset
appended.applyCanvas {
drawBitmap(cropped, 1f, 1f, null)
}
return appended
} catch (e: IOException) {
//handling failure
e.printStackTrace()
Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
}
}
这样我就可以解决问题了。图片如下。考虑一下我处理了由附加纹理引起的 1px 偏移。
但是,我觉得,有点不满意。我问自己这是否真的是一个解决方案。我用谷歌搜索了几天这种情况,但由于我不知道这个问题叫什么,所以我未能找到明确的,最终的解决方案。我想知道是否有办法解决这个问题,而无需手动重新创建更宽的纹理