Reputation: 3809
I'm trying to load a BMP image using this method :
int TextureManager::LoadBMP(std::string path, unsigned int &texture)
{
unsigned char* datBuff[2] = { nullptr, nullptr }; // Header buffers
unsigned char* pixels = nullptr; // Pixels
BITMAPFILEHEADER* bmpHeader = nullptr; // Header
BITMAPINFOHEADER* bmpInfo = nullptr; // Info
std::ifstream file(path, std::ios::binary);
if (!file)
{
std::cout << "Failure to open bitmap file.\n";
return 1;
}
// Allocate byte memory that will hold the two headers
datBuff[0] = new unsigned char[sizeof(BITMAPFILEHEADER)];
datBuff[1] = new unsigned char[sizeof(BITMAPINFOHEADER)];
file.read((char*)datBuff[0], sizeof(BITMAPFILEHEADER));
file.read((char*)datBuff[1], sizeof(BITMAPINFOHEADER));
// Construct the values from the buffers
bmpHeader = (BITMAPFILEHEADER*)datBuff[0];
bmpInfo = (BITMAPINFOHEADER*)datBuff[1];
// Check if the file is an actual BMP file
if (bmpHeader->bfType != 0x4D42)
{
std::cout << "File \"" << path << "\" isn't a bitmap file\n";
return 2;
}
// First allocate pixel memory
pixels = new unsigned char[bmpInfo->biSizeImage];
// Go to where image data starts, then read in image data
file.seekg(bmpHeader->bfOffBits);
file.read((char*)pixels, bmpInfo->biSizeImage);
unsigned char 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
unsigned int w = bmpInfo->biWidth;
unsigned int h = bmpInfo->biHeight;
/TODO:***************GENERATING TEXTURES*******************/
// Output a successful message
std::cout << "Texture \"" << path << "\" successfully loaded.\n";
// Delete the two buffers.
delete[] datBuff[0];
delete[] datBuff[1];
delete[] pixels;
return 0; // Return success code
}
but the bmpInfo->biSizeImage
always = 0 , so I have searched and found that I can find out the size in bytes of the bitmap data by multiplying the width by height by (bpp / 8), so I edit the function to be like this :
int TextureManager::LoadBMP(std::string path, unsigned int &texture)
{
unsigned char* datBuff[2] = { nullptr, nullptr }; // Header buffers
unsigned char* pixels = nullptr; // Pixels
BITMAPFILEHEADER* bmpHeader = nullptr; // Header
BITMAPINFOHEADER* bmpInfo = nullptr; // Info
std::ifstream file(path, std::ios::binary);
if (!file)
{
std::cout << "Failure to open bitmap file.\n";
return 1;
}
// Allocate byte memory that will hold the two headers
datBuff[0] = new unsigned char[sizeof(BITMAPFILEHEADER)];
datBuff[1] = new unsigned char[sizeof(BITMAPINFOHEADER)];
file.read((char*)datBuff[0], sizeof(BITMAPFILEHEADER));
file.read((char*)datBuff[1], sizeof(BITMAPINFOHEADER));
// Construct the values from the buffers
bmpHeader = (BITMAPFILEHEADER*)datBuff[0];
bmpInfo = (BITMAPINFOHEADER*)datBuff[1];
// Check if the file is an actual BMP file
if (bmpHeader->bfType != 0x4D42)
{
std::cout << "File \"" << path << "\" isn't a bitmap file\n";
return 2;
}
DWORD FileDataSize;
DWORD ActualDataSize;
LONG AjustedWidth;
LONG WidthOver = 0;
if (((bmpInfo->biWidth * (bmpInfo->biBitCount / 8)) % 4) != 0)
{
WidthOver = 4 - ((bmpInfo->biWidth * (bmpInfo->biBitCount / 8)) % 4);
}
AjustedWidth = bmpInfo->biWidth + WidthOver;
ActualDataSize = bmpInfo->biWidth * bmpInfo->biHeight * (bmpInfo->biBitCount / 8);
FileDataSize = AjustedWidth * bmpInfo->biHeight * (bmpInfo->biBitCount / 8);
// First allocate pixel memory
pixels = new unsigned char[FileDataSize];
// Go to where image data starts, then read in image data
file.seekg(bmpHeader->bfOffBits);
file.read((char*)pixels, FileDataSize);
unsigned char tmpRGB = 0; // Swap buffer
for (unsigned long i = 0; i < FileDataSize; 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
unsigned int w = bmpInfo->biWidth;
unsigned int h = bmpInfo->biHeight;
/TODO:***************GENERATING TEXTURES*******************/
// Output a successful message
std::cout << "Texture \"" << path << "\" successfully loaded.\n";
// Delete the two buffers.
delete[] datBuff[0];
delete[] datBuff[1];
delete[] pixels;
return 0; // Return success code
}
now it's not reading the pixels , the variable pixels is always 0, what am doing wrong here?
EDIT: values of bmpInfo
biSize 40
biWidth 1024
biHeight 1024
biPlanes 1
biBitCount 32
biCompression 0
biSizeImage 0
biXPelsPerMeter 0
biYPelsPerMeter 0
biClrUsed 0
biClrImportant 0
Upvotes: 1
Views: 1310
Reputation: 4468
The biSizeImage entry correctly may be left at zero for RGB bitmaps. Microsoft documents that behavior here. In that case, you would have to use a different calculation, using biWidth and biHeight.
So the bitmap you are testing with is not necessarily flawed, and a general purpose BMP reader should be prepared for this case.
Upvotes: 1
Reputation: 8161
Based on our conversion MixedCoder, I think that bitmap you're trying to load was not correctly saved. We can see that
bmpHeader.bfOffBits = 54;
that means if we subtract our fix size of 14 for the header. That leaves us 40 bytes for the bmpInfo which by definition is the size of the BITMAPINFOHEADER. So we can rule out some misalignment problem.
I would just saved that image again using Paint and load it that way.
Upvotes: 1