Alexander Schaefer
Alexander Schaefer

Reputation: 99

java.awt.Graphics -> graphics.drawImage is too slow, what is wrong?

I'd like to program a 2D game engine. The problem i have (i don#t use opengl and stuff like that, so i render with cpu) is, that i only get 7fps through the graphics.drawImage(); Do you have any suggestions to speed this up or any alternatives?

image = new BufferedImage(gc.getWidth(), gc.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
canvas.createBufferStrategy(1);
bs = canvas.getBufferStrategy();
g = bs.getDrawGraphics();
g.drawImage(image, 0, 0, canvas.getWidth(), canvas.getHeight(), null);

My renderer should simply color the frame (width 320 height 240 pixels) cyan, and he does, but only at a maximum of 8fps. Renderer:

private int width, height;
private byte[] pixels;

public Renderer(GameContainer gc){
    width = gc.getWidth();
    height = gc.getHeight();
    pixels = ((DataBufferByte)gc.getWindow().getImage().getRaster().getDataBuffer()).getData();
}

public void clear(){
    for(int x = 0; x < width; x++){
        for(int y = 0; y < height; y++){
            int index = (x + y * width) * 4;
            pixels[index] = (byte)255;
            pixels[index+1] = (byte)255;
            pixels[index+2] = (byte)255;
            pixels[index+3] = 0;
        }
    }
}

Upvotes: 0

Views: 1855

Answers (2)

C1bergh0st
C1bergh0st

Reputation: 23

I know i'm a little late to this party but for anyone looking at this in the future:

Dont try to handle your images as arrays!

If you want to color your whole screen or an Image using a canvas, get the Graphics object as described above and use a rectangle to fill your screen like this:

g.setColor(new Color(REDVALUE,GREENVALUE,BLUEVALUE);
g.fillRect(0,0,canvas.getWidth(),canvas.getHeight());

If your current class extends Canvas then you can obviously use:

getWidth() and getHeight()

Instead of:

canvas.getWidth() and canvas.getHeight()

If you have problems understanding how the Graphics object works you might want to take a look at this first.

If you want to do more complex Image manipulation this might help you.

EDIT: Drawing big images is somehow (???) slower then drawing small images to fill the same area.

Upvotes: 1

Kyranstar
Kyranstar

Reputation: 1720

I'm not really sure how to optimize your current example (but does using the data buffer in clear really create a speedup from just using Graphics.fillRect?), but I can give you some general Java2D tips.

First of all, using the most compatible image type for your computer is important. Here is a method to find a compatible image:

private static final GraphicsConfiguration GFX_CONFIG = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

public static BufferedImage toCompatibleImage(final BufferedImage image) {
    /*
     * if image is already compatible and optimized for current system settings, simply return it
     */
    if (image.getColorModel().equals(GFX_CONFIG.getColorModel())) {
        return image;
    }

    // image is not optimized, so create a new image that is
    final BufferedImage new_image = GFX_CONFIG.createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());

    // get the graphics context of the new image to draw the old image on
    final Graphics2D g2d = (Graphics2D) new_image.getGraphics();

    // actually draw the image and dispose of context no longer needed
    g2d.drawImage(image, 0, 0, null);
    g2d.dispose();

    // return the new optimized image
    return new_image;
}

It is also generally good practice to dispose of Graphics objects when you're done with them (it might help if you create them in a tight loop).

Here are some other questions that give some tips:

Java2D Performance Issues

Java 2D Drawing Optimal Performance

Upvotes: 1

Related Questions