Sep 8, 2013 (last update: Sep 8, 2013)

BMP Loader

Score: 3.6/5 (312 votes)
*****
INTRO
If you clicked on this article, you must want to load a .bmp file into your applications.

Although .bmp files may be large in size, they're still widely used in many applications, and well documented on the internet.

Now there are many tutorials on the internet for doing this, however they mostly use the C way of doing it. This will be a C++ tutorial, NOT a C one.

====================

THINGS TO KNOW
This tutorial assumes you're using windows, but it doesn't use windows specific functions. You can easily write your structures. Wikipedia has a pretty good representation of the bitmap headers.

This also uses OpenGL, but it shouldn't be too hard to port to DirectX.

Also, we have a new type. Uint8's are essentially unsigned chars. We also have to include fstream for this.

====================

TUTORIAL
Alright now let's start. We'll have a function that returns a GLuint for our texture.

The function takes 2 parameters.
int LoadBMP(const char* location, GLuint &texture);
The first is the location of the file. The second is a reference to a texture unsigned int, which is the ID of the texture generated.

Alright now get to actual code. We first start off with four pointers, and we'll set 'em to nullptr (or NULL if you'd like).
1
2
3
4
5
6
	Uint8* datBuff[2] = {nullptr, nullptr}; // Header buffers

	Uint8* pixels = nullptr; // Pixels

	BITMAPFILEHEADER* bmpHeader = nullptr; // Header
	BITMAPINFOHEADER* bmpInfo   = nullptr; // Info 


They're really self explanitory.

We use fstream, and open up a file, then check if it's open.
1
2
3
4
5
6
7
8
	// The file... We open it with it's constructor
	std::ifstream file(location, std::ios::binary);
	if(!file)
	{
		std::cout << "Failure to open bitmap file.\n";

		return 1;
	}


Now, we allocate memory for the headers, get the values with the data buffers.
1
2
3
4
5
6
	// Allocate byte memory that will hold the two headers
	datBuff[0] = new Uint8[sizeof(BITMAPFILEHEADER)];
	datBuff[1] = new Uint8[sizeof(BITMAPINFOHEADER)];

	file.read((char*)datBuff[0], sizeof(BITMAPFILEHEADER));
	file.read((char*)datBuff[1], sizeof(BITMAPINFOHEADER));


Once we have the data loaded, we construct the loaded data into the headers.
1
2
3
	// Construct the values from the buffers
	bmpHeader = (BITMAPFILEHEADER*) datBuff[0];
	bmpInfo   = (BITMAPINFOHEADER*) datBuff[1];


Since we have that loaded, we check if the file is a BMP file.
1
2
3
4
5
6
	// Check if the file is an actual BMP file
	if(bmpHeader->bfType != 0x4D42)
	{
		std::cout << "File \"" << location << "\" isn't a bitmap file\n";
		return 2;
	}


Allocate pixel memory, then jump to where the pixel data starts and read.
1
2
3
4
5
6
	// First allocate pixel memory
	pixels = new Uint8[bmpInfo->biSizeImage];

	// Go to where image data starts, then read in image data
	file.seekg(bmpHeader->bfOffBits);
	file.read((char*)pixels, bmpInfo->biSizeImage);


Since bitmaps store pixels as BGR, we convert it to RGB.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
	// We're almost done. We have our image loaded, however it's not in the right format.
	// .bmp files store image data in the BGR format, and we have to convert it to RGB.
	// Since we have the value in bytes, this shouldn't be to hard to accomplish
	Uint8 tmpRGB = 0; // Swap buffer
	for (unsigned long i = 0; i < bmpInfo->biSizeImage; i += 3)
	{
		tmpRGB        = pixels[i];
		pixels[i]     = pixels[i + 2];
		pixels[i + 2] = tmpRGB;
	}

	// Set width and height to the values loaded from the file
	GLuint w = bmpInfo->biWidth;
	GLuint h = bmpInfo->biHeight;


Now we simply generate the texture with OpenGL. If you're using DirectX, ignore this, and use whatever you do to create textures.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
	/*******************GENERATING TEXTURES*******************/

	glGenTextures(1, texture);             // Generate a texture
	glBindTexture(GL_TEXTURE_2D, texture); // Bind that texture temporarily

	GLint mode = GL_RGB;                   // Set the mode

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	 
	// Create the texture. We get the offsets from the image, then we use it with the image's
	// pixel data to create it.
	glTexImage2D(GL_TEXTURE_2D, 0, mode, w, h, 0, mode, GL_UNSIGNED_BYTE, pixels);

	// Unbind the texture
	glBindTexture(GL_TEXTURE_2D, NULL);

	// Output a successful message
	std::cout << "Texture \"" << location << "\" successfully loaded.\n";

	// Delete the two buffers.
	delete[] datBuff[0];
	delete[] datBuff[1];
	delete[] pixels;

	return 0; // Return success code 


And that's about it. Please rate this article.

Have fun with your new BMP Texture loader!

====================