2

I am trying to run a sketch that is supposed to show images (png´s, between 100kb and 1,5mb in size, 55.4mb total) in a coverflow animation. it works with about 10 images, but using more I get a out of memory error. I am loading the images file names into an string array like so:

String[] names = {"00.jpg", "01.jpg", "02.jpg"};

and then they get loaded into the sketch like so:

covers = new Cover[names.length];
  for (int i = 0; i < covers.length; i++ ) {
  covers[i] = new Cover(names[i]);
}
initCovers();

covers class:

class Cover {
  PImage img;

Cover( String name ) {
img = loadImage(name);

public void drawCover() {
  beginShape();    
    textureMode(NORMALIZED);
    texture(img);
    vertex(-300, -300, 0, 0, 0);
    vertex( 300, -300, 0, 1, 0);
    vertex( 300,  300, 0, 1, 1);
    vertex(-300,  300, 0, 0, 1);
  endShape();

when I run the sketch, my ram (8gb) gets filled within seconds, and the sketch doesn´t even load, it just crashes. when I start the sketch with about 10 images, everything works fine ( bout 1,5gb of ram usage).

my question is: why is it using so much memory? is it normal? is there a way to make it run more memory efficient (e.g. freeup memory of images that are not currently displayed because we can only see about 3 images at once on screen).

EDIT: I think the problem is that in the cover class, each time it gets called a new PImage is created. could that be possible?

image size in memory: width * height * (color depth/8), so for my images (1575y1969, 24bit) that woul be 8,9mb. times 91 images: about 807mb of memory usage just for the images.

Kris
  • 768
  • 1
  • 8
  • 19
  • 2
    Don't forget that PNGs are compressed. When you load them into an image that can be rendered directly, they'll get uncompressed into raw bitmaps. Maybe it'll be enough to only keep the ones that are currently displayed uncompressed, and keep the other ones in memory in compressed form to avoid I/O. – millimoose Jul 31 '12 at 22:44
  • 1
    Sounds like a bug somewhere. Are you sure that you aren't loading the same images over and over again (in a loop or something)? I'd then suggest profiling. @millimoose - I doubt that png decompression can go from 55MB to 1.5GB. That would be a compression ratio of 96%. – Ted Hopp Jul 31 '12 at 22:47
  • (I misread JPG for PNG but the point applies, if not more so.) – millimoose Jul 31 '12 at 22:50
  • @TedHopp JPG on disk 167kb, in memory 1.39mb, PNG on disk 157kb, in memory 6.37mb - and that's without an alpha channel – MadProgrammer Jul 31 '12 at 22:56
  • Why does the text say PNG, while the code use JPG? Which is it? – Andrew Thompson Jul 31 '12 at 23:44
  • BTW - DYM like this [Cover Flow](http://en.wikipedia.org/wiki/Cover_Flow)? If it were a simple fixed delay animation, you could turn the images into a MOV using JMF. – Andrew Thompson Jul 31 '12 at 23:47
  • @andrew: I tried with both. with jpgs and a smaller resolution I can acutally run the sketch on my pc with 8gb ram. with the smaller jpgs the sketch still uses about 6-7 gb of ram, which the machine where it is supposed to run eventualla doesn´t have AND which seems an awful lot still, even if the images need more "space" when in memory. // i mean this [cover-flow](http://adrianavarro.net/blog/quick-cover-flow-in-processing/) – Kris Jul 31 '12 at 23:48
  • @TedHopp Looking through a bunch of wallpapers, JPG can get compression ratios over 90 fairly easily. Also, the relation between "how much memory you think you've allocated" and "how much memory is the JVM going to eat" isn't necessarily clear. – millimoose Jul 31 '12 at 23:53
  • @Kris OutOfMemoryError doesn't mean you ran out of available RAM, it means you've run out of the Java heap size. This defaults to 1GB RAM in your case. You need to give your app a bigger heap to reliably test what using more images does: http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html – millimoose Jul 31 '12 at 23:54
  • @TedHopp I just did an experiment that amply supports that 'it depends what is in the image'. A blank RGB image of 4000x4000 will compress by a ratio of over a 1000 to 1 when saved as PNG. Admittedly, this is not very relevant to 'real world images', but still mildly interesting (IMO). – Andrew Thompson Aug 01 '12 at 00:03
  • @AndrewThompson - OP's edit suggests that in terms of pixel data, the images should occupy about 0.8MB. Although Java does have some overhead for object allocation, etc., it's hard to believe that there would be 100% memory overhead for large, contiguous blocks of memory. – Ted Hopp Aug 01 '12 at 00:19
  • @Ted Oh right, see your point. Hmm.. still think my answer is valid & relevant to the general task, but it is obviously not the answer to the actual question here. Might delete it.. The comment I'll leave though, simply because it is factual, and after 5 comments, unless up-voted, it will disappear anyway. – Andrew Thompson Aug 01 '12 at 01:39

4 Answers4

3

Now that I understand the use-case better, I recommend to change the entire approach.

Cover Flow GUI

The types of applications (e.g. seen above) that you are trying to emulate do not load the entire slew of images as soon as the app. is presented. Instead, they read the small group of images that they are going to present to the user first. As the user approaches the end of that group, the software flushes some of the images at the start of the sequence (if memory is tight) and loads some more at the end.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    Add in scaling and we've started moving in the right direction – MadProgrammer Aug 01 '12 at 00:12
  • well, since this it not really an option because of time constraints and since it seems that ther is no obvious memory leak I guess we have to scale down on the number of images/quality that we can display. – Kris Aug 01 '12 at 00:18
1

Try increasing the JVM heap space

java -Xmx1024m

(Yes, I know, 1gig is a 'little' excessive, but after some experimentation, this value can be trimmed down)

As @millimoose states, the images loaded by Java are uncompressed into memory when they are loaded, so even a small image of 100kb on disk can suddenly occupy mb's of RAM when uncompressed. It becomes even more complicated when you start dealing with the alpha channel as well.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • image size in memory: width * height * (color depth/8), so for my images (1575y1969, 24bit) that woul be 8,9mb. times 91 images: about 807mb of memory usage just for the images. and I am increased the ram for processing to 2gb already. not sure how to juse the java cmd line option with processing.. – Kris Jul 31 '12 at 23:16
  • @Kris: Do you *really* need all of those images in memory at once and do they *really* need to be that large? Are they being displayed at full resolution? If not then scale them down. – Ed S. Jul 31 '12 at 23:19
  • @Kris Also, you might want to make sure that the color model is compatible with your screen device – MadProgrammer Jul 31 '12 at 23:24
  • 1GB might actually be the default as per http://docs.oracle.com/javase/7/docs/technotes/guides/vm/gc-ergonomics.html. (Not sure, the document doesn't explicitly mention the case of a server-class machine running the client VM.) – millimoose Jul 31 '12 at 23:58
1

The size of compressed images isn't a good guide to the memory requirements.

The size in pixels is better. For example a modern camera photo with 8 megapixel resolution requires at least 32mb of memory to represent. If you are manipulating images this size with swing, double or triple that, at least. It's easy to gobble up a lot of memory.

Also, Java's internal memory management isn't very good at dealing with chunks this size.

ddyer
  • 1,792
  • 19
  • 26
0

I would say try painting them to a component using a single temp Cover as a handle as opposed to having N-many objects hanging around? And if you need interactions with images after draw time just hold back some simple meta data about their draw positions and dimensions, then use click event x,y etc to look up a a given image to allow you to work with it.

James C
  • 464
  • 1
  • 4
  • 12