Building large images
I am writing a class that builds large PNG files directly from a database of small ones. The approach I'm using is this. (psuedocode)
publicvoid buildImage(){
BufferedImage canvas =new BufferedImage(width,height, BufferedImage.TYPE_INT_ARGB);
for(each small database image){
//draw the small image on to the canvas
}
ImageIO.write(canvas,"png",new File("file.png"));
}
This works fine as long as the file I'm trying to build is relatively small. (Less than, say, 4000x4000.) But for large images, I get the following error java.lang.OutOfMemoryError: Java heap space. The error occurs BEFORE entering the FOR loop. So it seems that the problem is my original BufferedImage (the canvas) is too large for storage in memory.
Do you think my diagnosis is correct? If so, does anyone know a solution that allows me to build/export the PNG file in small pieces? Or any suggestions that get around allocating space to a massive BufferedImage?
Thanks,
Bill
[1378 byte] By [
BillCa] at [2007-10-3 10:41:14]

Thank you for the suggestion. Unfortunately, this app is intended for distribution, so I can not assume my users will make this change. Also, its important that the upper limit on file size is limited by their HD size - not the JVM. Is there any way I can build the image in small parts? Or write data directly to the hard drive without first building it in memory? I can accept that this would run much slower.
Again, I really appreciate the help!
- Bill
You might consider dealing with the image as a set of Tiles. I guess if you know how the file is structured by could read it in byte by byte, and create a Tile from a byte array. I'm not experienced in this area, sorry.
BTW, you can set any java runtime flags you want if you use a script to launch your APP.
regards
messengers, I appreciate your efforts. My problem is not reading images, but writing them. I already have a set of tiles (in fact, my database is a set of small tiles). I need to combine them and write them out into a large rendered image.Thanks,Bill
Morjaria,I'd be glad to help, but lets keep it in the forum. That way, our conversation is available online for future developers who have the same problem. If you'd like to discuss it in a different forum, let me know.Good luck,Bill
Is there any way I can build the image in small parts? Or write data directly to the hard drive without first building it in memory?
If you know the structure of the file format you can assemble the file header and the data for each pixel in a java.io.ByteArrayOutputStream
You could calculate the array offset for each tile as a function of its position on a grid. You would need to format the pixel data for each tile as the byte data specified in the file format. You can use the ByteArrayOutputStream.write(byte[], arrayOffset, lengthOfData)
to compile the file and write it to an outputStream when ready using the writeTo method.
If the only limit to the size of the picture is the size of a users hard drive perhaps the images cannot realistically be expected to display on video monitors?
my 2c
regards
Messengers,
You are correct about the size of the files. As far as my class is concerned, their maximum size is infinity. In practice, it is unlikely that any images will ever be as large as you suggested, but my class can not assume a max size. The point is that there will not always be enough heap space for my image to be created first im RAM.
It looks like I may have to learn the structure of PNG files and use a ByteArrayOutputStream as you suggested. I was hoping something in the Java API would do that for me. I'm going to look through the JAI API as per Dmitri's suggestion first. I hadn't tried that yet. Otherwise, its one byte at a time. . .
Thanks for all your help.
Bill