How to save an image in a new thread?

edited August 2014 in How To...

Hi! I have an animation that must play smoothly. Sometimes I have to save screenshots. While saving, the animation stops for half second. The rendering is happening inside a P3D PGraphics.

If I try to save this PGraphics in a thread, the animation stays smooth, but the resulting image is gray:

                Thread saveThread = new Thread() {
                    @ Override
                    public void run() {
                        pg.get().save("screenshot/gray.tif");
                    };
                };
                saveThread.start();

If I make a copy of the PGraphics, and try to save that in a thread, the animation stops:

                final PImage screenshot = pg.get();
                Thread saveThread = new Thread() {
                    @ Override
                    public void run() {
                        screenshot.save("screenshot/goodButPaused.tif");
                    };
                };
                saveThread.start();

Is there any trick to save an image without delaying the animation?

Answers

  • edited August 2014

    The way it's laid out, your Thread doesn't make any sense! It just invokes 1 save() and then it ends! :-/
    When run() returns, the Thread running it vanishes! That's why we place an infinite loop in run()! :-B

    Anyways, since save() is a slow task, it's smarter to merely enqueue PImage screenshots in a data structure.
    Either save() them all when it's all done or use a producer/consumption Queue approach split in 2 Threads! *-:)

  • The way it's laid out makes sense to me. That's what I want, to save an image in a different thread and be over with it. If 5 minutes later I want to save another image I do the same. I could keep the thread alive doing nothing, but I don't see the point.

    I can't save things when done because the program is supposed to run all day, and the image saved in the thread must be uploaded online immediately.

    Unfortunately it does not answer the problems, which are:

    • copying the PGraphics using .get() in the main thread for saving it later in a thread pauses the animation (get() seems to be cpu intensive).
    • accessing the PGraphics directly from the second thread results in a gray image (saved smoothly, but boring).

    The issue is, if I'm redrawing the PGraphics 30 times per second, how can I rescue one frame to save it before it's overwritten, without causing the frame rate to go down?

  • Answer ✓

    See if loadPixels() followed by an arrayCopy() of the pixels[] array is faster than get().

  • Thanks for the tip. Trying on two different computers I discovered the bottleneck.

    In my development computer, with an integrated graphics chip, the following code results in 1 frame per second:

    void setup() {
      size(1200, 800, P3D);
    }
    void draw() {
      background(0);
      loadPixels();
      text(frameRate, 100, 100);
    }
    

    Which is very weird. Normally I'm fine rendering hundreds of 3D objects. In JAVA2D the code above plays at 60 fps. With a computer with a modern graphics card it plays at 60fps both in JAVA2D and P3D. Something goes wrong when trying to access the pixels array of a P3D display in my laptop.

    Since the get() operation is not slow in the modern computer, I can then use a thread to save the PImage to disk. Problem solved.

    I've said it before, but now it's really time to get a new laptop. Then I won't waste people's time with weird bugs :)

Sign In or Register to comment.