Loading a 100MB PNG and draw it on the canvas but it eats 1GB of RAM :(

Hello all

This is a big problem for my university assignment and im the only girl in my class so I cant really ask for help from others there :frowning:

When I load a PNG (100MB in size) and draw it on the canvas. The ram usage is crazy, its 1 GB.

I implemented an image cache store thing to eliminate chances it has been loaded multiple times into the memory. I have to use processing 2.X as per the guidelines by my professor

Is this expected behaviour that a 100mb image uses up 1gb of ram? Is the png compressed and processing is uncompressing it or is it loading each pixel in as an object or something? Why does it take 10X the space in memory than on disk??

Are there any tricks in photoshop i can use to lower the memory footprint, maybe lower the bit depth or something?

I have this giant png being loaded in , its the “land” in my rts game for the assignment. The png is roughly 15000x7000 pixels

Thanks anyone for your help…

This is how i draw the image on the canvas

		canvas.tint(100 + clock.day_minute,100 + clock.day_minute,255,day_night_cycle_tint_num);

		canvas.image(map.main_png, -7550 - cartesian_corner.x - 10, 0 - cartesian_corner.y);

My image cache thing is below. As you can see from the code it would be impossible to load the same image twice from disk…

Love !!
Enda

package image_store;
import java.io.File;
import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PImage;

public class Image_Store {

	
	public ArrayList <Image_Record> image_records;
	public ArrayList <String> ids; 
	public PApplet canvas;
	
	public Image_Store(PApplet canvas){
		this.canvas = canvas;
		this.image_records = new ArrayList <Image_Record>(20);
	}
	
	public PImage create_image(String id){
		
		//System.out.println("Attempting to find an image with id: " + id);
		for(Image_Record record : image_records){
			if(record.id.equals(id)){
				//System.out.println("The id " + id + " already exists and a reference is being returned now ");
				return record.image;
			}
		}
		//System.out.println("The id " + id + " does not exist, now creating it...." + canvas.sketchPath() + File.separator + "data" + File.separator + id + ".png");
		PImage image = canvas.loadImage(canvas.sketchPath() + File.separator + "data" + File.separator + id + ".png");
		
		image_records.add(new Image_Record(image, id));
		//System.out.println("A PImage with ID " + id + " has been added to the image store");
		return image;
	}
}
1 Like

Did you try to save it aa jpg and load this version?
Here you can set properties of the image to reduce its size (or use irfan view, another program)

Please make a copy of the initial image

In processing you can increase memory in the preferences

1 Like

Hello,

There are tools that you can use to monitor memory usage such as VisualVM:
https://visualvm.github.io/

I found this Java.lang.Runtime class useful to monitor memory usage:

I created a couple of images in different formats (JPG and PNG) that were 15000x7000 in image size in pixels which is not the same as image size of the file.

The image size of the file is in the comments in the code below and here:

Results:

The size in memory is the same and it makes no difference if it is a JPG or PNG file.

I did NOT check this and set a size in Preferences for testing:
image

If you do set the maximum available memory give consideration to memory usage for your program and how much memory you have on your system.

I have 16GB and had memory available.

References:

:)

2 Likes

Your image is stored on disc using the PNG is a lossless compression algorithm. When the image is loaded it is uncompressed and will require 4xWxH bytes of memory. So a 10000 x 20000 pixel image would require 800,000,000 bytes and there is not a lot you can do about it.

1 Like

Is it definitely the case that you need the entire map loaded into memory all the time? A common strategy in games is to divide the map into tiles, e.g., 64x64, and then only load the few tiles, say 4x4, that immediately surround the player. If you need to show an over-all map, you can store a separate lower-resolution version.

On the other hand, 1GB for world data isn’t necessarily that bad on modern devices. Even most (many?) cell phones can handle that these days.

2 Likes

Thank you Giv, Quark, Chrisir and Scudly! For being generous with your time and knowledge to help this lost girl.

Giv. Your method of using Java.lang.Runtime in conjunction with VisualVM to analyse memory usage is really cool. I’m going to do some experiments with it :slight_smile:

Quark. Your analysis puts my mind at ease with regard to using processing. I had suspected there was something inheritantly wrong with processing. Thank you for proving that is not the case.

Scubly. I am going to implement your solution and I will keep track of what quarter of the current tile the player is in I think. And if they’re currently in the top left for example of the tile, I will only load the tile above, the tile to the left and the current tile into memory.

Chrisir. Givs analysis seems to be correct. I loaded in a jpg instead of a png. While the jpg was only 13mb on disk and the png was 100mb. They both took the same amount of ram when loaded into a PImage which was a real surprise for me.

Thanks everyone. Im very happy with the help I received and I wish that you all have a nice weekend :slight_smile: In return if you have anything going on in your personal life and need advice from a girl and think I could help pm me.

Love!
Enda

1 Like