Java:使用FileOutputStream保存大的.bmp文件

时间:2013-10-19 23:16:03

标签: java file save bmp

我正在尝试编写一个生成并保存Julia sets高分辨率图像的应用程序,但我遇到了问题。我的代码创建的文件大小几乎与我应该的(在我看来)相对应,但是当我尝试打开它时,会出现关于文件过早结束的错误消息。

我基本上采用尺寸*大小的正方形,然后对于这个正方形的每个像素,我正在计算复平面上的相应数字(片段从-1.5 - 1.5i到1,5 + 1.5i),之后我正在开始一个算法,确定它是否属于某个Julia设置(我完全确定它是否正常工作,所以你不必担心它。)

我想生成非常高的分辨率(至少像20k * 20k像素)图像,所以我想用某种输出流来做。我用BufferedImage,ImageIO.write()和类似的东西生成了这样的图像,但是这些图像不适用于接近9k * 9k像素的图像(JVM堆大小问题)。我只是添加,这是我第一次尝试按字节创建这样的文件时。

这是我的代码:

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();
    }
}

提前致谢!

1 个答案:

答案 0 :(得分:0)

标题中的所有数字必须为little-endian。例如,当将54表示为四个字节时,这四个字节必须为54,0,0,0。要将24表示为两个字节,则两个字节必须为24,0。

请注意,每行像素必须填充到4个字节的精确倍数。只要size是1000的倍数,这不会导致问题,但如果您打算接受仲裁大小,则需要在大小计算中考虑填充,并在完成每个一排像素。

与您的问题无关的其他内容,但值得注意的是,Windows位图以相反的顺序包含其行。如果在位图标题中将图像高度指定为正数,则需要先写入最后一行,然后写入倒数第二行,依此类推。但是,如果在标题中将图像高度指定为负数(即-size),则可以按从上到下的顺序写出行。 (对于Julia集合,这可能不是那么重要。)