How to solve texture being cut off when drawing Bitmap with antialiasing in Android?

67 Views Asked by At

I've been making game information application. It's basically showing stats, information of game that I play (with many others). This game has animation, and I managed to make my own View that draws animation of unit, enemy, or just any components. Since drawing code requires a lot of transformation (scaling, rotation, translation, etc.), I needed this custom View to be hardware-accelerated

If I explain how the animation works simply, it has sprite sheet that contains several part images. I crop images from sprite sheet, and draw each cropped parts with specified angle, scale, x/y position, and so on. I didn't want result to be pixelated, I enabled dithering and antialiasing aliasing, and performed drawing image like below

//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)
}

So far, it draws well, but when I magnify the animation viewer, texture doesn't get antialiased properly. Texture itself gets smooth, yes, but when it comes to boundary of texture, it gets cut off

View with non-proper antialiasing

Check image's feather, and upper part. As yo can see, texture doesn't show smooth pixels, but rather sudden cut-off effects.

I think I saw there's solution that disabling hardware-acceleration can solve the problem, but if I do so, performance gets really worse than before, so I have to stick with hardware acceleration. From my very bear knowledge, what I assume is that when Android draws bitmap to Canvas, Android doesn't antialias after drawing texture, but antialias texture itself, then draw already-antialiased one, so those pixels which are out of boundary of texture due to effect of antialiasing, get cut off

To solve this problem, I approached with bit dirty way. Since I don't have deep knowledge about low-level rendering (such as OpenGL, etc.), what I tried is just appending one more pixel on each side of cropped image like below

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)
    }
}

With this way, I can solve the problem. Picture is below. Consider that I handled 1px offset caused by appended texture.

"Temporarily" fixed result

However, I feel, bit unsatisfied. I questioned myself if this is really a solution. I googled about this situation for few days, but with the fact that I don't know what this problem is called, I failed to get clear, ultimate solution for it. I wonder if there's a way to solve this problem without manually re-creating wider texture

UPDATE

The way I tried has severe problem when I try to scale it too much. For example, if texture needs to be scaled along x-axis 50 times larger than original, that means the offset pixel (which is transparent) will get scaled 50 times as well. This leads texture to antialiased too much, leading to weird result. So I can't use the way I tried above

0

There are 0 best solutions below