I have command line c++ project for my final project of my course. I've decided to go a little further than the course intends and write a class for creating an uncompressed bitmap picture file.

As an initial exercise I decided to create the 2x2 pixel bitmap example from Wikipedia. http://en.wikipedia.org/wiki/BMP_file_format#Example_of_a_2x2_Pixel.2C_24-Bit_Bitmap

The problem I'm having is that .bmp file can't be opened by Windows image viewer. I'm not sure where I've gone wrong.

One of the problems with the code is that the size of FileHeader is supposed to be 14 bits, all of the sizes of the internal variables of the structure add up to 14 but when reading the size of the entire structure it is 16 bits.

This is the code for my header:

#ifndef bitmap_saver
#define bitmap_saver

namespace kspace
{
	class bmp
	{
	public:
		typedef struct FileHeader
		{
			unsigned _int16 FileType;
			unsigned _int32 FileSize;
			unsigned _int16 Reserved1;
			unsigned _int16 Reserved2;
			unsigned _int32 BitmapOffset;
		};
	
		typedef struct BitmapHeader
		{
			unsigned long bmpHeaderSize;
			long Width;
			long Height;
			unsigned short Planes;
			unsigned short BitsPerPixel;
			unsigned long CompressionType;
			unsigned long BMPByteSize;
			long hres;
			long vres;
			unsigned long NumColours;
			long NumImpColours;
		};
	
		typedef struct ColourPalette
		{
			unsigned _int8 Blue;
			unsigned _int8 Green;
			unsigned _int8 Red;
			unsigned _int8 buffer;
		};

		//Function prototyping
		void bmp_create();
	};
}

#endif

And for the function definition

#include "bitmap_saver.h"
#include <iostream>
#include <fstream>

using namespace std;
using namespace kspace;


void bmp::bmp_create()
{
	int sz =0;

		FileHeader fileHeader;

		fileHeader.FileType=19778;
		fileHeader.FileSize=70;
		fileHeader.BitmapOffset=54;

		sz += sizeof(fileHeader);
		
		cout << sizeof(fileHeader.BitmapOffset)+sizeof(fileHeader.FileSize)+sizeof(fileHeader.FileType)+sizeof(fileHeader.Reserved1)+sizeof(fileHeader.Reserved2) << endl;
		cout << sz << endl;
		
		BitmapHeader bmpHeader;

		bmpHeader.bmpHeaderSize=40;
		bmpHeader.Width=2;
		bmpHeader.Height=2;
		bmpHeader.Planes=1;
		bmpHeader.BitsPerPixel=24;
		bmpHeader.CompressionType=0;
		bmpHeader.BMPByteSize=16;
		bmpHeader.hres=2835;
		bmpHeader.vres=2835;
		bmpHeader.NumColours=0;
		bmpHeader.NumImpColours=0;

		sz += sizeof(bmpHeader);
		
		cout << sizeof(bmpHeader) << endl;

		ColourPalette a[4];

		for(int i=1;i<4;i++)
		{
			a[i].Blue=255;
			a[i].Green=255;
			a[i].Red=255;
			a[i].buffer=0;
		}

		sz += sizeof(a);

		cout << sizeof(a) << endl;

		cout << sz << endl;
	fstream test;

	test.open("test.bmp", ios::out|ios::binary);
	test.write(reinterpret_cast<char*>(&fileHeader), sizeof(fileHeader));
	test.write(reinterpret_cast<char*>(&bmpHeader), sizeof(bmpHeader));
	test.write(reinterpret_cast<char*>(&a), sizeof(a)); 
	test.close();
}
Salem commented: Great first question - code (tagged of course), evidence of research and a question +20

> for(int i=1;i<4;i++)
This doesn't initialise ALL the elements.

> bmpHeader.BitsPerPixel=24;
You've said the format is 3 bytes per pixel - so why are you writing 4?

Padding for 4 byte alignment (Could be a value other than zero)

You forgot to take into account this little detail.

Generally, you need to assemble a byte array yourself, then write that out.
Pointing at some struct is generally a bad approach, even when it seems to work.

Thank you Salem! I've got it working now. I really should have seen the error in the for loop. I fixed the problems with the padding. I didn't create a byte array to store the information (I don't know how- unless it's just an array of characters and I store all the values in there). Instead I used #pragma pack(1) to set the alignment of the structure to the one I want.

Thank you again for your help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.