4

I have a very large (around a gigapixel) image I am trying to generate, and so far I can only create images up to around 40 megapixels in a BufferedImage before I get an out of memory error. I want to construct the image piece by piece, then combine the pieces without loading the images into memory. I could also do this by writing each piece to a file, but ImageIO does not support this.

Fractaly
  • 834
  • 2
  • 10
  • 25
  • 1
    Why not increase the memory available to the application, instead? – Andrew Thompson Oct 05 '11 at 22:58
  • I did, and that increased my threshold to 100 megapixels, but I am running out of ram. Plus, I would like to my program to be expandable to even higher resolutions. It is a fractal generating program for the mandelbrot set. – Fractaly Oct 05 '11 at 23:12
  • 1
    Can you cut the image(s) by an external tool, combine the pieces with your program and then recombine the image? – 9000 Oct 05 '11 at 23:12
  • That is an option, but I would be unable to distribute the program without forcing the user to download an external tool. – Fractaly Oct 05 '11 at 23:16
  • 1
    If each pixel contains a byte each for R, G, B & A, a 40 MPix image will consume 160 Meg of memory. Even with no alpha component, it will come to 120 Meg. Are you getting some inclination as to why 100 Meg failed? O_o As to 9000's suggestion, you might deploy the app. using Java Web Start and have it install the external app. as appropriate for Mac, *nix or Windows. As far as the user is concerned it is simply a matter of clicking OK when prompted - the installation of the tool is automatic. – Andrew Thompson Oct 05 '11 at 23:23
  • Very cool, and I will look into it, but does anyone have a pure java solution? – Fractaly Oct 05 '11 at 23:25

4 Answers4

2

I think JAI can help you build what you want. I would suggest looking at the data structures and streams offered by JAI.

Also, have a look at these questions, might help you with ideas.

  1. How to save a large fractal image with the least possible memory footprint
  2. How to create a big image file from many tiles
  3. Appending to an Image File

You basically want to reverse 2 there.
Good luck with your project ;)

Community
  • 1
  • 1
c00kiemon5ter
  • 16,994
  • 7
  • 46
  • 48
  • Those all pretty much describe my problem. They all recommend JAI too. I found a decent JAI API [here](http://download.oracle.com/docs/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/index.html) – Fractaly Oct 06 '11 at 02:14
  • yeah, JAI is kinda neglected, there hasn't been an update for years. Part of it is now [`javax.ImageIO`](http://download.oracle.com/javase/7/docs/api/javax/imageio/package-summary.html). – c00kiemon5ter Oct 06 '11 at 03:01
  • Hmm. It's not looking very good for the possibility of combining image out of RAM. Does anyone know how to append to a file? – Fractaly Oct 14 '11 at 03:12
0

I see two easy solutions. Create a custom binary format for your image. For saving, just generate one part at a time, seek() to the appropriate spot in the file, then offload your data. For loading, seek() to the appropriate spot in the file, then load your data.

The other solution is to learn an image format yourself. bmp is uncompressed, but the only easy one to learn. Once learned, the above steps work quite well.

Remember to convert your image to a byte array for easy storage.

warren
  • 563
  • 2
  • 13
0

If there is no way to do it built into Java (for your sake I hope this is not the case and that someone answers saying so), then you will need to implement an algorithm yourself, just as others have commented here saying so.

You do not necessarily need to understand the entire algorithm yourself. If you take a pre-existing algorithm, you could just modify it to load the file as a byte stream, create a byte buffer to keep reading chunks of the file, and modify the algorithm to accept this data a chunk at a time.

Some algorithms, such as jpg, might not be possible to implement with a linear stream of file chunks in this manner. As @warren suggested, bmp is probably the easiest to implement in this way since that file format just has a header of so many bytes then it just dumps the RGBA data straight out in binary format (along with some padding). So if you were to load up your sub-images that need to be combined, loading them logically 1 at a time (though you could actually multithread this thing and load the next data concurrently to speed it up, as this process is going to take a long time), reading the next line of data, saving that out to your binary output stream, and so on.

You might even need to load the sub-images multiple times. For example, imagine an image being saved which is made up of 4 sub-images in a 2x2 grid. You might need to load image 1, read its first line of data, save that to your new file, release image 1, load image 2, read its first line of data, save, release 2, load 1 to read its 2nd line of data, and so on. You would be more likely to need to do this if you use a compressed image format for saving in.

To suggest a bmp again, since bmp is not compressed and you can just save the data in whatever format you want (assuming the file was opened in a manner which provides random access), you could skip around in the file you're saving so that you can completely read 1 sub-image and save all of its data before moving on to the next one. That might provide run time savings, but it might also provide terrible saved file sizes.

And I could go on. There are likely to be multiple pitfalls, optimizations, and so on.

Instead of saving 1 huge file which is the result of combining other files, what if you created a new image file format which was merely made up of meta-data allowing it to reference other files in a way which combined them logically without actually creating 1 massive file? Whether or not creating a new image file format is an option depends on your software; if you are expecting people to take these images to use in other software, then this would not work - at least, not unless you could get your new image file format to catch on and become standard.

Loduwijk
  • 1,950
  • 1
  • 16
  • 28
0

Not a proper solution, just a sketch.

Unpacking a piece of image is not easy when an image is compressed. You can decompress, by an external tool, the image into some trivial format (xpm, uncompressed tiff). Then you could load pieces of this image as byte arrays, because the format is so straightforward, and create Image instances out of these raw data.

9000
  • 39,899
  • 9
  • 66
  • 104
  • that would still require loading all of the images into memory. – Fractaly Oct 14 '11 at 03:14
  • That will require loading the image into memory, but not the entire image at once! You'll be able to load chunks of right size, because pixel data would be just a linear array. Some `seek()`s will be required, but not much else. – 9000 Oct 14 '11 at 13:39
  • How could I create one image file containing all of the image data? – Fractaly Oct 15 '11 at 20:53