deal with large buffered image

What is the effect way to create an image undo? I have a large buffered image, which I need to manipulate but also want to be able to undo the changes. I create another buffered image to save the original image prior to the changes. But I constantly get out off memory error. Maybe I can save some memory by creating the undo image as a non-buffered image.

What is the difference between an image and buffered images in terms of sizes? How can I create a new non-buffered image from a buffered image?

I use to follow method to try to create a new image from a buffered image. But what I get is the same image object being converted from buffered to non-buffered :

image=bufferedImage.getSource();

I need to create a new non-buffered image from a buffered image.

Jay

non-buffered image?

A BufferedImage is simply an image stored in memory.
Back in the old Java image model, it meant the ImageProducer that constructed the image was a piece of memory, rather than a file (on disc, or across the net)

Thats where the name came from, the image was buffered completely in memory, so there was no cost when the image needed to be reconstructed.
(As apposed to an ‘unbuffered image’ where it would have to be re-read from a File or URL to reconstruct it)

As for your undo question,
How big is your original BufferedImage?

What are the changes being made to the image?

Could you store the image as a sequence of modifications, rather than a sequence of full rasters?

i.e.

your undo stack would look something like :-

  1. Original image
  2. fillRect(blah blah)
  3. drawLine(blah blah)
    4)…

failing that, you could write a ColorModel that implemented a simply compression algorithm - perhaps RLE?

Another option, is to stream the undo steps to a file on the HD, though this would be incredibly slow.

Yet another option, is to simply increase the maximum heap space Java allocates for itself - “java -Xmx128m” for instance.

The original image size varies with the largest one about 1.2M. This is what I tried to implement in my code :

Image origImage=new ImageIcon(imageName).getImage();

BufferedImaeg drawCanvas = gc.createCompatibleImage(imgW, imgH,Transparency.TRANSLUCENT);

draw_g2=drawCanvas.createGraphics();

BufferedImage backupCanvas = gc.createCompatibleImage(imgW, imgH,Transparency.TRANSLUCENT);

backup_g2=backupCanvas.createGraphics();

backup_g2.drawImage(drawCanvas, 0,0, this); // create undo

//perform drawing tasks …
draw_g2.fillRect(…);
draw_g2.drawLine(…);
……

//undo the changes

draw_g2.drawImage(backupCanvas, 0,0,this);

This works fine except it uses too much memory when the original image is large. I’m trying to figure out a way to reduce the memory usage by not to create a buffered image for storing the image backup. Creating an undo stack may be an option but I do not know if the undo stack would work if the changes are the actual pixels changes of the original image.

Yes you are correct. I do not have issue if I increase the heap space but I want to see if there better solution in the code itself.

You could just backup the portion of the image that will be changed, instead of copying the entire image as the backup.

For example, you could:

  1. Get a bounding rectangle of the most current modification

  2. Copy the area of the bounding rectangle (before modification) onto a new image, and push that onto the stack.

  3. When undoing, just sift through the stack, and copy each image from the stack onto the drawing canvas.

How about catching the OutOfMemoryError in a try/catch block and repsonding in an appropriate way. For example, if the image is large enough that you can’t have at least two copies of it in memory (i.e. the “before” and “after” images) then just serialize it to disk. There’s really no way around this. If you don’t have enough memory to hold what you need (no matter what method you use), then you have to go to the hard disk for more space.

Put the undo images in temporary files if you like, and then delete them when the program exits. In other words, you could implement unlimited undo/redo within a single run of the application. Once the application closes, any changes made would be final.