Large B Image size in ram

In my pursuit of a worms 2d-style view in my 2d game, I am using one large PNG or GIF image as the background

I made the following method to break this image into tiles so it can be accelerated

public void makeBack(String back)
{
BufferedImage background = getImage(back);
mapWidth = background.getWidth();
mapHeight = background.getHeight();
int numberXTiles = background.getWidth() / TILE_SIZE;
int numberYTiles = background.getHeight() / TILE_SIZE;
backMap = new BufferedImage[numberXTiles][numberYTiles];

for (int x = 0; x < numberXTiles; x++)
{
  for (int y = 0; y < numberYTiles; y++)
  {
    backMap[x][y] = gc.createCompatibleImage(TILE_SIZE, TILE_SIZE,
                                             Transparency.OPAQUE);

    Graphics g = backMap[x][y].getGraphics();

    g.drawImage(background.getSubimage(x * TILE_SIZE, y * TILE_SIZE,
                                       TILE_SIZE, TILE_SIZE), 0, 0, null);
    g.dispose();

    if (backMap[x][y].getCapabilities(gc).isAccelerated())
    {
      System.out.println("True");
    }
    else
    {
      System.out.println("False");
    }

  }
}

background = null;

}

The problem is that it takes an insane amount of RAM on my system. The original image is of size 2048*2048 and is around 800KB as a GIF

when i run this method, the RAM usage in task manager rises to around 70,000KB which is huge.

when i try and make both the foreground and background, i get a java heap size out of memory error

i could increase the heap size but this is only a small game and that is more of a workaround than a real solution

i would appreciate some help/advice on why the size in RAM is so large and ways to alleviate this problem

So, let’s count

  1. 2048x2048 gif image (1 byte per pixel) = 4M (remember that it’s uncompressed in memory)-btw, it’d be wise to get rid of it once you created your tiles.
  2. a number of tiles which amounts to the same
    image: 2048x2048x4bytes=16M (assuming 32bpp desktop depth)

This alone amounts to 20M of heap. But the real problem, I think, is that you’re using getSubImage, which does some horrible things under the cover.

Don’t use getSubImage(), instead use one of Graphics.drawImage() calls which can copy a rectangle of the source image to the destination graphics.

Dmitri

ok, thanks for your reply

i assume you are talking about the drawImage() calls under graphics with both the destination and source coordinates?

when i am trying to use that now, it draws the first tile but then the drawImage call returns false for every other tile

the API says that if it returns false the image pixels are still changing, which they shouldnt be

im not using an image observer, should i be?

im going to keep trying to work this out

do you have any suggestions for what format image i should use? the background does not need any transparency so almost anything would work

PNGCrush is a util you can google for. It can make png’s very small. So that means .png is a good format to use for your purpose :slight_smile:

As for the drawImage() returning false thing. How bout you post your image loading code so we can make sure that’s not an issue?

public BufferedImage getImage(String name)
{
BufferedImage a = null;

try
{
  a = ImageIO.read(this.getClass().getResource(name));
}

catch (IOException e)
{
  return null;
}

BufferedImage b = gc.createCompatibleImage(a.getWidth(), a.getHeight(),
                                           Transparency.BITMASK);
b.createGraphics().drawImage(a, 0, 0, null);
return b;

}

that is the code im using to get an image

it does take it in as a bitmask but with the tile-making code it should be converted to opaque

this is only because the foreground should be bitmask and i want the method to be compatible with both

also another strange thing i noticed it that when i first load the program, i get bad fps, around 60-70

but when i alt-tab to check my ram usage and then go back in, the fps jumps to around 500

this sounds weird but it does happen everytime

The BufferedImage “b” will use 4 bytes per pixel, wich for your 2048*2048 image totals to 16MB of ram. The makeBack function will create a copy of it. So your using 32MB of the heap. The memory used shown in the task manager is usually twice that of the heap usage. Making the total 64MB + overhead, wich is what you are seeing.

ok thank you, i got rid of the bufferedimage b

since im going through the process of acceleration later anyways, i dont need it there

but i still have to work on that tiling code because it isnt making them still’

oh, and with the changes so far im down to 46 megs of ram

Why don’t you manually break your image up into smaller pieces and see if there is a difference. Make your program do 8x8 tiles, check the memory, then manually break them up and load each one separately and check your mem usage.