Java:使用FileOutputStream保存大的.bmp文件 [英] Java: Saving big .bmp files with FileOutputStream

查看:128
本文介绍了Java:使用FileOutputStream保存大的.bmp文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

我基本上是用一个size * size的正方形,然后对于这个正方形的每个像素,我要从复数平面(从-1.5-1.5i到1.5 + 1.5i的片段)中计算相应的数字,然后我正在启动一种算法来确定它是否属于某些Julia集(我完全确定它可以正常工作,因此您不必担心它).

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).

我想生成非常高分辨率(至少20k * 20k像素)的图像,所以我想用某种输出流来实现.我已经使用BufferedImage,ImageIO.write()和类似的东西生成了此类图像,但是它们不适用于接近9k * 9k像素的图像(JVM堆大小问题).我要补充一点,这是我第一次尝试按字节创建这样的文件.

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.

这是我的代码:

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

提前谢谢!

推荐答案

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

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.

请注意,每行像素必须填充为4字节的精确倍数.只要size是1000的倍数,这都不会造成问题,但是如果您打算接受任意大小,则需要在大小计算中以及完成写入的每一行时考虑填充像素.

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.

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

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.)

这篇关于Java:使用FileOutputStream保存大的.bmp文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆