OutOfMemory Error when animating with PGraphic images

So I’m creating 1000 PGraphic images and want to animate through them. I’m keeping them empty for this example. The problem is I run out of memory before animating through all of them once (as in it stops around the 800 frames mark) and this must mean there’s something wrong with how I’m animating them. Other programs wouldn’t have a problem going through less than a minute’s worth of frames. They must be accumulating in some strange way rather than one at a time.

Here’s the error message:

An OutOfMemoryError means that your code is either using up too much memory
because of a bug (e.g. creating an array that’s too large, or unintentionally
loading thousands of images), or that your sketch may need more memory to run.
If your sketch uses a lot of memory (for instance if it loads a lot of data files)
you can increase the memory available to your sketch using the Preferences window.

I’ve increased memory in preferences to around 2.5GB, but I don’t think this is the problem, is it? It shouldn’t be taking up this much memory in the first place, right? Imagine animating a second’s worth of 4K images. There must be a better way.

Here’s my code:

int frames = 1000;
int counter = 1;
PGraphics animation[] = new PGraphics[frames];
int frameTotal = 0;
int frame;

void setup() {
  frameRate(72);
  size(500,500);
  
  thread("emptyFrames");
}

void draw() {
   
    if (counter % 3 == 0){ // 72 fps / 24fps = 3
      frame = frameTotal % frames;  
      image(animation[frame],0,0);
      println(frameTotal);
      frameTotal++;
      
    }
    counter++;
}

void emptyFrames () {
  for(int i = 0; i < frames; i++) {
    animation[i] = createGraphics(500, 500);
    
  }

}

you might want to check out this thread, hopefully one of the solution will work for you. the same issue is scattered all over. personally i would go with the first option offered in the thread linked.

1 Like

I’m not sure how I would “unload” the current PGraphics images and then reload them. This seems like the right solution, but I’m not sure how to implement it. If anyone can help out in that regard I’d really appreciate it.

can you give a bit more info… what exactly are you doing with the PGraphics images? are you generating images and then just trying to play them back in sequence? or?

Yes, exactly. The code above is doing that with the bare minimum (all transparent pixels).

is the algorithm generating the images too slow to generate them in realtime as the images are needed? or could you generate them in batches? without seeing the code i’m feeling around in the dark but maybe someone else will have a solution for you.

It’s not about slow, the error is with memory. Sorry, why can’t you see the code?

i can see the code you have posted but not the actual image generation method. if the images can be generated quickly enough you can just do something like

PGraphics generatedImage;

void setup() {
  size(512, 512, P2D);  
  frameRate(10);
}

void generateImage() {
  if(generatedImage == null)
    generatedImage = createGraphics(width, height);
  else
    generatedImage.clear();
  
  generatedImage.beginDraw();
  int shapeCount = (int)random(5);
  //draw some random stuff
  for(int i = 0; i < shapeCount; i++) {
    int shapeType = (int)random(2);
    int randomX = (int)random(width);
    int randomY = (int)random(height);
    int randomW = (int)random(width / 4);
    int randomH = (int)random(height / 4);
    
    generatedImage.fill((int)random(255), (int)random(255), (int)random(255), 255);
        
    switch(shapeType) {
      case 0:
        generatedImage.rect(randomX, randomY, randomW, randomH);
        break;
      case 1:
        generatedImage.ellipse(randomX, randomY, randomW, randomH);
        break;
    }
  }
  generatedImage.endDraw();
}

void draw() {
  background(0);
  generateImage();
  image(generatedImage, 0, 0);
}

or if the method is too slow you can generate them in another thread* while the first batch is being shown and once shown swap the current batch with the fresh batch

*i’m not 100 percent sure about PGraphics drawing while in a thread but i think it should be fine i think it’s more a sync issue if you are drawing to screen from a thread whereas this way you would be drawing offscreen.

So the reason why this solution isn’t working for me is that I have PGraphic images with specific drawings on them and I need to animate them. So I would need to copy the current frame’s pixel array to the active/animating frame. In order to do that I need to have the pixel array of each frame loaded and that causes a memory overload as well.

Could there be a solution in writing the pixel arrays into a temporary file on the hard drive and calling them for the animation?

i think you’ll have to wait until kll chrisir or gotoloop respond. sorry i couldn’t help best of luck with it.

You seem to have a misunderstanding of how those other programs work. Most will be using compressed data in some fashion if they’re not real-time generation. PGraphics are uncompressed. Using so many is a recipe for disaster. They’re 500x500x4 bytes (so 1MB) each - almost a GB for the raw data before you get into other things, like caching.

Also, initializing them in a separate thread is wrong. The renderers are not thread safe, and there’s no checking / handoff to the main thread.

So…uh, is there a right way to do this in processing?

Ok, so I solved this by storing the pixel color information in a 2D array and copying back and forth with 2 PGraphics images rather than having each frame be a separate PGraphics image.