Skip to main content
GameDev.net gamedev.net
🔒 Locked

Help with bitmap loading...

Started by Tjaalie Jul 15, 2005 at 8:45 AM 8 replies 1.1k views
Original Post
Tjaalie
Tjaalie
Hello ThreadReader, I load an bitmap with the following function and when it enters the loop it crashes (when i leave the loop out i got the bitmap wiht the r and b values wrong (bgr not rgb)). So does anyone know why its not working????

//Load the bmp file
bool Bmp(char* file, int* height, int* width, unsigned char** rgbData, int* error)
{
    //Vars
    FILE*          File = NULL;
    BMP_Header     Header;
    BMP_Info       Info;
    unsigned char  Swap;
    
    //Open the file
    File = fopen(file, "rb");
    if (File == NULL)
    {
        *error = 1;
        return false;
    }
    
    //Read the file header
    fread(&Header, 1, sizeof(BMP_Header), File);
    
    //Check if its a bitmap
    if (Header.Type[0] != 'B' && Header.Type[1] != 'M')
    {
        *error = 2;
        return false;
    }
    
    //Read the info header
    fread(&Info, 1, sizeof(BMP_Info), File);
    
    //Bmp type
    if (Info.Bits != 24)
    {
        *error = 2;
        return false;
    }    
    
    //Make room for the image data
    *rgbData = new unsigned char[((Info.Width*Info.Height)*3)+1];
    
    //Read the image data
    fread(*rgbData, 1, (Info.Width*Info.Height)*3, File);
    
    //Close the file
    fclose(File);
    
    // swap the R and B values to get RGB since the bitmap color format is in BGR
	for (int i=0;i<(Info.Width*Info.Height)*3;i+=3)
	{
		Swap = *rgbData;
		*rgbData = *rgbData[i+2];
		*rgbData[i+2] = Swap;
	}
    
    //Set the vars
    *height   = Info.Height;
    *width    = Info.Width;
    
    //Succes
    return true;
}



Thanks for your reaction.
if (*pYou == ASSHOLE) { pYou->Die(); delete pYou; };
marvel
marvel
Try using a struct:


struct rgbData
{
unsigned char b;
unsigned char g;
unsigned char r;
};


with the elements in their proper order like that, you could just read in the info from the file and never have to worry about switching it around. No more loop to swap red and blue values.
Tjaalie
Tjaalie
I'm going to try that out, thanx.
if (*pYou == ASSHOLE) { pYou->Die(); delete pYou; };
Tjaalie
Tjaalie
OpenGL still reads them in the wrong order becouse.
Becouse it doesn't matter for the names.
if (*pYou == ASSHOLE) { pYou->Die(); delete pYou; };
Dorvo
Dorvo
I found a tutorial which explains how to load Bitmap files.
Now, I haven't tried it out, but it looks like it would be helpful.

Loading a 24-Bit Bitmap
Tjaalie
Tjaalie
I followed several of them but i think this error is becouse
something is not good alocated. Does anyone see the problem.
if (*pYou == ASSHOLE) { pYou->Die(); delete pYou; };
Dorvo
Dorvo
Do you have the OpenGL Game Programming book?
It has a decent section on loading bitmaps.
Interesting Dave
Interesting Dave
Microsoft (who designed BMPs) decieded to store the pixel data in BGR order (dunno why). Now you could try swapping it around in memory like you're doing, or just call glTexImage2D(GL_TEXTURE, 0, 3, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, data) - notice the GL_BGR_EXT ? should be a standard extension methinks.
Roger that, lets run like hell!
Allmight
Allmight
Well, reason you get them backward is because they are stored backward. What you have to do is loade the data, and then manually reverse them so you get them in the order you want.

Dont ask me why they are stored backward. All i know is that it dates back to the time Microsoft and IBM were struggling against eachother. Microsoft with Windows and IBM with OS2. They both wanted to use Bitmaps, but they could not agree in a standard format on how to store and use them. Well, the end result was that it was stored backwards.

Hope that clears the subject some.

// Allmight
-------------------------------------------------Founder and DirectorAllSoft Studios
Enigma
Enigma
Your immediate problem is that operator[] has higher precedence than operator*, making your call *rgbData mean *(rgbData), instead of (*rgbData).

Your bigger problem is the horrible mix of C and C++ you're using. It's not really your fault, a lot of tutorials teach really bad practices and treat C++ as an extension to C rather than considering C as a subset of C++.

Here's how I might write a simple bitmap loader:
#include <algorithm>#include <fstream>#include <functional>#include <iostream>#include <iterator>#include <vector>class Bitmap{	public:		explicit Bitmap(std::string const & filename);		unsigned int height() const;		unsigned int width() const;		/* example function */		void printBitmapValues() const;	private:		class Rgb		{			public:				unsigned char red;				unsigned char green;				unsigned char blue;				void bgrToRgb();		};		friend std::ostream & operator<<(std::ostream & stream, Bitmap::Rgb const & rgb);		std::vector< Rgb > data_;		unsigned int width_;		unsigned int height_;};Bitmap::Bitmap(std::string const & filename){	std::ifstream reader(filename.c_str(), std::ios::binary);	if (!reader)	{		throw "Failed opening file: " + filename;	}	BMP_Header header;	reader.read(reinterpret_cast< char * >(&header), sizeof(header));	if (std::strncmp(header.Type, "BM", 2))	{		throw "File : " + filename + " is not a valid BMP file";	}	BMP_Info info;	reader.read(reinterpret_cast< char * >(&info), sizeof(info));	if (info.Bits != 24)	{		throw "Failed loading bitmap file: " + filename + "\nLoading of non 24-bit bitmaps is not supported.";	}	width_ = info.Width;	height_ = info.Height;	data_.resize(width_ * height_);	reader.read(reinterpret_cast< char * >(&data_[0]), sizeof(Rgb) * data_.size());	std::for_each(data_.begin(), data_.end(), std::mem_fun_ref(&Rgb::bgrToRgb));}unsigned int Bitmap::height() const{	return height_;}unsigned int Bitmap::width() const{	return width_;}void Bitmap::printBitmapValues() const{	std::copy(data_.begin(), data_.end(), std::ostream_iterator< Bitmap::Rgb >(std::cout, ", "));}void Bitmap::Rgb::bgrToRgb(){	std::swap(red, blue);}std::ostream & operator<<(std::ostream & stream, Bitmap::Rgb const & rgb){	stream << '(' << int(rgb.red) << ", " << int(rgb.green) << ", " << int(rgb.blue) << ')';	return stream;}int main(){	try	{		Bitmap bitmap("bitmap.bmp");		bitmap.printBitmapValues();	}	catch (std::string & str)	{		std::cout << str << '\n';	}}

The implementation is pretty much 1-1 to your existing function but is much safer with no loss of efficiency. It requires your BMP_Header and BMP_Info classes. Your preferred C++ reference should have information on anything you are unfamiliar with. If you still don't understand anything, just ask.

Enigma

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.