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 char
s. 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!
====================