Writing an array to a BMP file

First of all, being new to this forum I would like to say hello to everyone :)

now my problem; I'm trying to write the contents of an array to a BMP file.
I've google'd, wiki'ed, and searched for two days now and I can't get this figured out.

I know about the BITMAPFILEHEADER, BITMAPINFOHEADER, RGBQUAD, and BYTE structures and the data members contained inside of them and what they represent, I just don't know how in the hell to use them!

I got the fstream working and I can write to txt files. That's about as far as I've managed to get myself..

Can someone teach me how to get these freakin' structs set up and written so I can output the array data?? I just want the most basic way possible to write a BMP (apparently 24-bit bmp files are easiest because you're writing straight colour data to each pixel)

Any help would be appreciated, and links to sites with tutorials might cause me to /wrists

Thanks a lot for your time!
Pfft. bmps are so easy you don't even need structues. You can just write the headers yourself:
All integers are unsigned and little endian (http://en.wikipedia.org/wiki/Endianness )

Bytes 0-1: Magic word. It contains the letters 'B' and 'M'.
Bytes 2-5: Double word. File size.
Bytes 6-10: No idea. Leave this zeroed.
Bytes 11-14: Double word. Start of the bitmap.
Bytes 15-18: Double word. Size of the header. Normally set to 40. The header is considered to start at offset 15.
Bytes 19-22: Double word. Width.
Bytes 23-26: Double word. Height.
Bytes 27-28: Word. Planes. Must be 1.
Bytes 29-30: Word. Bits per pixel. You'll need this as 24.
Bytes 31-34: Double word. Compression. Leave it as zero.
Bytes 35-38: Double word. Compressed size. Since there's no compression, this value will be the same as file size.
Bytes 39-42: Double word. Horizontal resolution. See below.
Bytes 43-46: Double word. Vertical resolution. Pixels per meter, according to Wikipedia. The values seem to vary, but 2835 should do for both.
Bytes 47-50: Double word. Number of colors in the palette. Leave as zero.
Bytes 51-54: Double word. "Important colors". Leave as zero.
Bytes 55-EOF: Bitmap.

In a 24-bit bitmap, every pixel channel uses exactly 8 bits and, being a little endian file, they appear in BGR order.
Rows appear from top to bottom (in a 640x480 image, the first pixel in the file is 0;479, then the next row is 478, etc.).
If the last byte in a row isn't at file offset divisible by 4, padding pixels must be added until this condition is met. For example:
1
2
3
//file is an std::vector<unsigned char>
while (file.size()%4)
	file.push_back(0);


This pretty much covers bmps.
so lets say I have;
 
float grid[Xmax][Ymax];

How would I write that into the file? That's the problem I'm having, I'm not sure how to input the byte data you listed up there.

1
2
3
4
5
6
ofstream myfile;
myfile.open("test_BMP.bmp");

myfile << // what goes here and how

myfile.close();


would it be something like;
1
2
3
4
5
myfile << "BM";
DWORD fileSize = sizeof(grid) // +sizeof(header)?
myfile << filesize;
myfile << 0000;
DWORD startOfBitmap = //no idea 

I think with that example it shows where I'm stuck with this lol

Thanks for the quick reply!
Well, the thing is that you can't use << for output of binary data. You need to write all the data you have to an array and then write() it to the file in one sweep.

float isn't a suitable data type for pixel data. Maybe unsigned long, but the ideal is a struct pixel24{unsigned char r;unsigned char g;unsigned char b;}, which is portable to all platforms and doesn't waste space.

Example of how to write the data to an array:
1
2
3
4
5
6
7
8
9
10
data[0]='B';
data[1]='B';
writeLittleDWORD(data+2,305419896);
writeLittleDWORD(data+6,0);
writeLittleDWORD(data+11,55);
writeLittleDWORD(data+15,40);
writeLittleDWORD(data+19,640);
writeLittleWORD(data+27,1);
writeLittleWORD(data+29,24);
//... 

writeLittleDWORD() is a function you'll have to define that will automatize writing binary data to an array. Its prototype can be something like void writeLittleDWORD(unsigned char a,unsigned long b). When b==305419896 (0x12345678), for example, it will perform the following operations (not the actual code, of course):
a[0]=120; //0x78
a[1]=86; //0x56
a[2]=52; //0x34
a[3]=18; //0x12

0x, by the way, is the notation used for hexadecimal numbers.
Last edited on
I ended up just writing a .raw file, open in photoshop, and re-save as a proper file :p
...

I thought you wanted to write a program to see how it was done. You should have told me you just wanted to convert data. That would have saved me a lot of time and typing.
no no, I totally appreciate what you took the time to write, and I did try my best to understand it. I just couldn't get it to work properly so I just reverted to a method that I knew. After all it did net me roughly what I was looking for.
I don't want you to think that I just ignored your advice, because I did take the time to go through it it detail, line by line, especially since you're the only person that replied to this thread with real tangible advice and suggestions!
Even if you couldn't make it work, make sure you understand the concept of endianness. It's basic for some advanced topics in programming.
Topic archived. No new replies allowed.