2

I was writing a program for capturing the screen at a set interval and when I started testing, I found that I get an OutOfMemoryException almost immediately after it starts capturing pictures. I tried allocating more memory - I gave it 256m, but that hardly helped. All that it did was make it last 2 or 3 more seconds before throwing the exception and crashing again.

I understand that the createScreenCapture(...) method uses a lot of memory, but I have seen example programs that can record for long amount of times using the same method - how do they do it?

Edit: I've used some of your guys' advice and now I don't get OutOfMemoryExceptions! Hooray! I took the route that involves saving the photos to the hard drive. However, actually writing them to an archive file does take quite a long time. Writing 63 frames into an archive file takes almost 2 minutes!

I can't provide any code because I'm rewriting the I/O part. Working on improving the ^ situation.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Martin Tuskevicius
  • 2,590
  • 4
  • 29
  • 46

5 Answers5

1

I have seen example programs that can record for long amount of times using the same method - how do they do it?

Serialize the images to disk (as separate files or into a single Zip).


Is there a certain procedure I should use for saving it on a hard drive? I was thinking of converting images into an int[] array and then just storing that, since arrays are serializable.

There are a number of strategies that can be pursued.

  • Convert the image to a non-lossy (& easy to encode) image format and store the image either:
    1. In separate files on disk, or..
    2. As separate entries in an (uncompressed) Zip archive. By using a Zip we can get around early problems reported with storing 'thousands' of files. Make it uncompressed for considerations of speed (and the fact that Zip does very little for most media formats).
  • I once saw code on usenet that was called (AFAIR) 'Screenies' or something like that (can't find it now) that did much like you suggested. It stored the raw information (without any encoding) onto disk. I tried the code and could not get better performance for it than encoding the image to PNG & serializing the image to disk. You might want to run some tests to see which approach comes out faster now.
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • So rather than committing the image to memory for the program's lifetime, it saves it onto the hard drive? – Martin Tuskevicius Jan 08 '12 at 23:41
  • *"saves it onto the hard drive?"* Yes. – Andrew Thompson Jan 08 '12 at 23:50
  • Okay I'll look into that. Is there a certain procedure I should use for saving it on a hard drive? I was thinking of converting images into an int[] array and then just storing that, since arrays are serializable. – Martin Tuskevicius Jan 09 '12 at 01:18
  • ^ would not let me edit the comment. Also, I should have asked this earlier - wouldn't writing the files to the hard drive use a lot of CPU and memory as well? Should I separate the writing operations into a different thread? – Martin Tuskevicius Jan 09 '12 at 01:58
  • *"wouldn't writing the files to the hard drive use a lot of CPU and memory as well?"* Yes. *"Should I separate the writing operations into a different thread?"* Quite possibly. You'll need to experiment. – Andrew Thompson Jan 09 '12 at 02:17
1

How is it storing the image? How big is your screen? I'm not familiar with all the ColorModels supported by BufferedImage, but worst case a full RGB image @ 1900 x 1200 would be 1900 * 1200 * 24 bits, or about 7 MB. Even at 5 FPS, that's 35 MB per second, which will overflow 256 MB in less than 10 seconds, ignoring all other memory usage.

You most certainly will need to write to disk instead, or compress that data on the fly, but you'll still hit memory limits, easily.

James
  • 8,512
  • 1
  • 26
  • 28
  • Would I reach limits quickly even if I would turn the images into integer arrays and write those to the hard drive? – Martin Tuskevicius Jan 09 '12 at 01:19
  • What are you doing with them later? I'm assuming you want to play something back? If you write the image files to disk instead of keeping them in the collection, you'll be bound by disk size (35 MB per second would be roughly 1GB per 30 seconds), so you'd have maybe 4 hours of record time on a 500 GB drive. You can probably compress them If you're turning them into a video, just do that. If the robot you're referring to happens to be Xuggle, look at http://wiki.xuggle.com/MediaTool_Introduction#How_To_Take_Snapshots_Of_Your_Desktop – James Jan 09 '12 at 03:34
0

90 milliseconds is a pretty short sleep interval before snapping the next picture. You're probably taking too many. Why not set a limit on how big collection can get.

Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
0

Thread.sleep(90) will make your program pause for 90 milliseconds. So in 2-3 seconds, it takes about 200-300 pics, which would be quite a lot.

Liang
  • 383
  • 4
  • 13
  • Usually, I have a setting that lets the user choose how many pictures per second. Originally I tested with 30 frames per second (FPS) and it ran out of memory in a few seconds, then I put it to 5 frames per second, and it crashed maybe a second or two later. – Martin Tuskevicius Jan 08 '12 at 23:42
0

You are adding the memory of the image (area) to the Collection.

        BufferedImage image = robot.createScreenCapture(area); //OutOfMemory on this line.
        collection.addFirst(image);

What could you expect, the more you add, the larger it gets.

Try to write it to a file / database or remove the older image buffer to maintain a buffer of perhaps 20 last images.

90 ms is a little short, If you are trying to compare images, try to compare the previous image to the current one before adding to the collection.

If you are doing Tracking type solutions from web cams, let us know, its a whole new set of tools and concepts.

Araejay
  • 222
  • 1
  • 2
  • 9
  • Well at the moment, it's pretty much unanimous that I need to store it on the hard drive. – Martin Tuskevicius Jan 09 '12 at 01:16
  • Could you tell me what are you trying to achieve? there are many ways to skin the cat – Araejay Jan 09 '12 at 01:24
  • Essentially make a tool that captures your screen in a video format. Takes lots of pictures then convert to video using JMF. – Martin Tuskevicius Jan 09 '12 at 01:34
  • Ah. its straight forward, try this: http://stackoverflow.com/questions/6236119/how-to-develop-screen-capture-to-video-application – Araejay Jan 09 '12 at 01:45
  • Well, that post says to put the images in a collection, which is what I do. However, as others have said, I run out of memory because each image takes up a lot of memory. So that's why I am looking for an alternative. – Martin Tuskevicius Jan 09 '12 at 01:48
  • Not really mate, notice the way handles it? streams. Please try it out. – Araejay Jan 09 '12 at 01:58