Question

I'm trying to write an application generating and saving high resolution images of Julia sets, but I've got a problem. My code is creating a file with size almost corresponding to what (in my opinion) it should be, but when I try to open it, there's an error message about premature end of file.

I'm basically taking a size*size square, then for each pixel of this square I'm calculating corresponding number from the complex plane (fragment from -1.5 - 1.5i to 1,5 + 1.5i), and after that I'm starting an algorithm determining whether it belongs to certain Julia set or not (I'm totally sure that it works correctly, so you don't have to worry about it).

I'd like to generate very high resolution (like 20k*20k pixels, at least) images, so I'd like to do it with some kind of output stream. I've generated such images with BufferedImage, ImageIO.write() and stuff like that, but these are not working with images approaching to 9k*9k pixels (JVM heap size issues). I'll just add, that it/s my first time when I try to create a file like this, byte-by-byte.

Here's my code:

import java.io.FileOutputStream;
import java.io.IOException;

public class Save_big_bmp{
    public static void main(String[] args) throws IOException{
        int size, filesize;
        byte[] pixelColorBGR = new byte[3];
        boolean prisoner;

        size=1000;
        filesize=(3*size*size)+54;
        Complex c = new Complex(-0.1, 0.65);

        byte[] header=
        {66, 77, (byte)((filesize >> 24) & 0xFF), (byte)((filesize >> 16) & 0xFF), 
        (byte)((filesize >> 8) & 0xFF), (byte)(filesize & 0xFF), 0, 0, 0, 0, 0, 0, 0, 54,    
        0, 0, 0, 40, (byte)((size >> 24) & 0xFF), (byte)((size >> 16) & 0xFF), 
        (byte)((size >> 8) & 0xFF), (byte)(size & 0xFF), (byte)((size >> 24) & 0xFF),     
        (byte)((size >> 16) & 0xFF), (byte)((size >> 8) & 0xFF), (byte)(size & 0xFF), 0, 1, 0, 24,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

        FileOutputStream output = new FileOutputStream("output.bmp");
        output.write(header);

        for(int i=0;i<size;i++){
            for(int j=size;j>=0;j--){
                Complex z0 = new Complex(((double)i*3/size)-1.5,1.5-((double)j*3/size));
                prisoner = true;

                for(int k=0;k<1000;k++){
                    z0 = z0.squared();
                    z0 = z0.add(c);

                    if(z0.dist()>2){
                        prisoner = false;
                        break;
                    }
                }
                if(!prisoner){
                    pixelColorBGR[0]=0; pixelColorBGR[1]=0; pixelColorBGR[2]=0;
                    output.write(pixelColorBGR);
                }if(prisoner){
                    pixelColorBGR[0]= (byte) 0xFF; pixelColorBGR[1]=(byte) 0xFF; pixelColorBGR[2]=(byte) 0xFF;
                    output.write(pixelColorBGR);
                }
            }
        }
        output.close();
    }
}

Thanks in advance!

Was it helpful?

Solution

All numbers in the headers must be little-endian. For instance, when representing 54 as four bytes, those four bytes must be 54, 0, 0, 0. To represent 24 as two bytes, the two bytes must be 24, 0.

Be aware that every row of pixels must be padded to an exact multiple of 4 bytes. This isn't causing a problem as long as size is a multiple of 1000, but if you plan to accept an arbitary size, you'll need to account for the padding in your size calculation and when you finish writing each row of pixels.

Something else that isn't related to your issue, but is worth noting, is that a Windows bitmap contains its rows in reverse order. If you specify the image height as a positive number in the bitmap header, you will need to write the last row first, then the second-to-last row, and so on. However, you can write out the rows in top-to-bottom order if you specify the image height as a negative number (that is, -size) in the header. (This may not be all that important for a Julia set.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top