简体   繁体   中英

BufferedImage slows down performance

I'm working on a game, nothing serious, just for fun.
I wrote a class 'ImageBuilder' to help creating some images.
Everything works fine, except one thing.
I initialize a variabile like this:

// other stuff
m_tile = new ImageBuilder(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_RGB).paint(0xff069dee).paintBorder(0xff4c4a4a, 1).build();
// other stuff

Then, in the rendering method, i have:

for (int x = 0; x < 16; x++) {
    for (int y = 0; y < 16; y++) {
         g.drawImage(m_tile, x * (TILE_SIZE + m_padding.x) + m_margin.x, y * (TILE_SIZE + m_padding.y) + m_margin.y, null);
    }
}

Note: m_padding and m_margin are just two Vector2i

This draws on the screen a simple 16x16 table using that image, but the game is almost frozen, i can't get more than like 10 FPS.

I tried to creating the image without that class, by doing this (TILE_SIZE = 32):

m_tile = new BufferedImage(TILE_SIZE, TILE_SIZE, BufferedImage.TYPE_INT_RGB);

for (int x = 0; x < TILE_SIZE; x++) {
    for (int y = 0; y < TILE_SIZE; y++) {
        if (x == 0 || y == 0 || x + 1 == TILE_SIZE || y + 1 == TILE_SIZE)
             m_tile.setRGB(x, y, 0x4c4a4a);
        else
             m_tile.setRGB(x, y, 0x069dee);
    }
}

This time, i get 60 FPS. I can't figure out with is the difference, i used to creating image using 'ImageBuilder' and all is fine, but not this time.

ImageBuilder class:

    // Constructor
    public ImageBuilder(int width, int height, int imageType) {
        this.m_width = width;
        this.m_height = height;
        this.m_image = new BufferedImage(m_width, m_height, imageType);
        this.m_pixels = ((DataBufferInt) m_image.getRaster().getDataBuffer()).getData();
        this.m_image_type = imageType;
    }

    public ImageBuilder paint(int color) {
        for (int i = 0; i < m_pixels.length; i++) m_pixels[i] = color;
        return this;
    }

    public ImageBuilder paintBorder(int color, int stroke) {
        for (int x = 0; x < m_width; x++) {
            for (int y = 0; y < m_height; y++) {
                if (x < stroke || y < stroke || x + stroke >= m_width || y + stroke >= m_height) {
                    m_pixels[x + y * m_width] = color;
                }
            }
        }
        return this;
    }

    public BufferedImage build() {
        return m_image;
    }

There are other methods, but i don't call them, so i don't think is necessary to write them

What am i doing wrong?

My guess is that the problem is your ImageBuilder accessing the backing data array of the data buffer:

this.m_pixels = ((DataBufferInt) m_image.getRaster().getDataBuffer()).getData();

Doing so, may (will) ruin the chances for this image being hardware accelerated. This is documented behaviour, from the getData() API doc :

Note that calling this method may cause this DataBuffer object to be incompatible with performance optimizations used by some implementations (such as caching an associated image in video memory).

You could probably get around this easily, by using a temporary image in your bilder, and returning a copy of the temp image from the build() method, that has not been "tampered" with.

For best performance, always using a compatible image (as in createCompatibleImage() , mentioned by @VGR in the comments) is a good idea too. This should ensure you have the fastest possible hardware blits.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM