Question

I'm making a game that has lots of pixel art in it. A standard button in my game is about 12x12 pixels and scaled up five times for displaying. All of the characters are also scaled two times bigger, depending on the screen. The problem is that if I store all these images to upscaled bitmaps, I get the out of memory error in Android. If I try to scale them up every time for drawing, the game runs really slowly.

That's why I wrote my own PixelArtBitmap class. It results in great images and requires so little memory, but is highly inefficient, dropping my fps a lot. It's still faster than scaling bitmaps up every time for drawing. Here's the class:

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

class PixelArtBitmap{
    private int[][] pixels = null;
    private boolean[][] visible = null;

    private float width = 0;
    private float height = 0;

    private float drawWidth = 0;
    private float drawHeight = 0;

    private int pixelsX = 0;
    private int pixelsY = 0;

    private static Paint boxPaint = new Paint();

    public PixelArtBitmap(Bitmap bitmap, float scale){
        boxPaint.setStrokeWidth(0);

        pixels = new int[bitmap.getWidth()][bitmap.getHeight()];
        visible = new boolean[bitmap.getWidth()][bitmap.getHeight()];

        pixelsX = bitmap.getWidth();
        pixelsY = bitmap.getHeight();

        //Utility is an another class of mine, providing information about the device
        drawWidth = scale * Utility.getScaleWidth();
        drawHeight = scale * Utility.getScaleHeight();

        width = pixelsX * drawWidth;
        height = pixelsY * drawHeight;

        for(int x = 0 ; x < bitmap.getWidth() ; x++){
            for(int y = 0 ; y < bitmap.getHeight() ; y++){
                pixels[x][y] = bitmap.getPixel(x,y);

                if(Color.alpha(pixels[x][y]) == 0) visible[x][y] = false;
                else visible[x][y] = true;
            }
        }

        bitmap.recycle();
        bitmap = null;
    }

    public void draw(float x, float y, Canvas canvas){
        for(int drawY = 0 ; drawY < pixelsY ; drawY++){
            for(int drawX = 0 ; drawX < pixelsX ; drawX++){
                if(visible[drawX][drawY]){
                    boxPaint.setColor(pixels[drawX][drawY]);
                    canvas.drawRect(x + drawWidth * drawX, y + drawHeight * drawY,
                            x + drawWidth * (drawX + 1), y + drawHeight * (drawY + 1), boxPaint);
                }
            }
        }
    }
}

So, how could I make this class faster or is there a totally different way for doing this correctly?

Was it helpful?

Solution

Instead of creating a new bigger sized Bitmap you can also draw smaller sized Bitmap directly into new size using;

Canvas.drawBitmap(Bitmap, null, dstRect, Paint);

This method should re-size the original Bitmap into dstRect size and I'm quite sure there's a setting to select nearest neighbor filtering. This should enable you to draw smaller image directly into desired size whilst retaining the pixel art looks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top