Archived

This topic is now archived and is closed to further replies.

jaba

BMP

Recommended Posts

Guest Anonymous Poster

class CBitmap
{
private:
unsigned short width;
unsigned short height;
unsigned char* data;



public:
// Constructor

inline CBitmap()
{
data = NULL;
}


// Overloaded constructor

inline CBitmap( char *fileName )
{
data = NULL; // Set data to NULL so createBitmap won''t think we alredy have a bitmap

createBitmap( fileName );
}


// Destructor

inline ~CBitmap()
{
destroyBitmap();
}



// Create a new 24-bits RGB-bitmap from a bmp file

bool createBitmap( char *fileName )
{
if ( data != NULL )
return false;

FILE *file;
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
RGBQUAD *palette = NULL; // = NULL for ( ''palette'' may be used without having been initialized ).


file = fopen( fileName, "rb" );

if ( file == NULL )
return false;

// Read the header

fread( &fileHeader, sizeof( BITMAPFILEHEADER ), 1, file );

// Check if it is a real bitmap

if ( fileHeader.bfType != bitmapId() )
{
fclose( file );
return false;
}

// read the info header

fread( &infoHeader, sizeof( BITMAPINFOHEADER ), 1, file );

// We can only read RGB bitmaps

if ( infoHeader.biCompression != BI_RGB )
{
fclose( file );
return false;
}

// We can read 8-bit ( 256 colors ) bitmaps,

if ( infoHeader.biBitCount == 8 )
{
if ( infoHeader.biClrUsed == 0 ) // This means a palette of 256 colors.

infoHeader.biClrUsed = 256;

// Create and read the palette.

palette = new RGBQUAD[ infoHeader.biClrUsed ];

fread( palette, infoHeader.biClrUsed * sizeof( RGBQUAD ), 1, file );
}
else if (( infoHeader.biBitCount != 24 ) && ( infoHeader.biBitCount != 1 )) // And we can read 24-bits ( 2^24 colors ) and 1-bits ( 2 color ) bitmaps.

{
fclose( file );
return false;
}

// Go to the picture bits.

fseek( file, fileHeader.bfOffBits, SEEK_SET );

width = (unsigned short)abs( infoHeader.biWidth );
height = (unsigned short)abs( infoHeader.biHeight );

// Store the size of the bitmap.

int size = ( width * height * 3 );

data = new unsigned char[ size ];

if ( infoHeader.biBitCount == 24 )
{
fread( data, size, 1, file ); // We can just read the bitmap.


// Swap the R and B values to get RGB since the bitmap color format is in BGR.

swapColors( data, size );
}
else if ( infoHeader.biBitCount == 8 ) // With 8 bit we need to create the colors with the palette.

{
// We only read 1 byte per RGB so it 3 times smaller.

int tempSize = size / 3;

unsigned char *tempData = new unsigned char[ tempSize ];

fread( tempData, tempSize, 1, file );

// Create the bitmap with the palette and the data we read.

int j = 0;
for ( int i = 0; i < tempSize; i++ )
{
data[j+0] = palette[ tempData[i] ].rgbRed;
data[j+1] = palette[ tempData[i] ].rgbGreen;
data[j+2] = palette[ tempData[i] ].rgbBlue;
j += 3;
}

// Delete the palette and the tempdata.

delete [] palette;
delete [] tempData;
}
else if ( infoHeader.biBitCount == 1 ) // With 1 bit we need to create the colors from 1 bit.

{
// We only read 1 bit per RGB so it ((size/3)/8) times smaller.

int tempSize = (size / 3) / 8;

unsigned char *tempData = new unsigned char[ tempSize ];

fread( tempData, tempSize, 1, file );

// Create the bitmap with the data we read.

int j = 0;
for ( int i = 0; i < tempSize; i++ )
{
// We need to go through all the 8 bits

for ( int n = 7; n >= 0; n-- )
{
if ( tempData[i] & (1<<n) ) // Black

{
data[j+0] = 0;
data[j+1] = 0;
data[j+2] = 0;
j += 3;
}
else // White

{
data[j+0] = 255;
data[j+1] = 255;
data[j+2] = 255;
j += 3;
}
}
}

// Delete the palette and the tempdata.

delete [] tempData;
}

// We don''t need the file anymore.

fclose( file );

return true;
}



// Save the bitmap to a file

bool saveBitmap( char *fileName ) // TODO: Bitmaps won''t show as thumbnails in winXP?

{
if ( data == NULL )
return false;

FILE *file;
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;

file = fopen( fileName, "wb" );

// Check if we could open the file

if ( file == NULL )
return false;

// Fill the BITMAPFILEHEADER struct

fileHeader.bfSize = sizeof( BITMAPFILEHEADER );
fileHeader.bfType = bitmapId();
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );

// Write the BITMAPFILEHEADER struct

fwrite( &fileHeader, sizeof( BITMAPFILEHEADER ), 1, file );


int size = ( width * height * 3 );


// Fill the BITMAPINFOHEADER struct to the file

infoHeader.biSize = sizeof( BITMAPINFOHEADER );
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biCompression = BI_RGB;
infoHeader.biSizeImage = size;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
infoHeader.biWidth = width;
infoHeader.biHeight = height;

// Write the BITMAPINFOHEADER struct to the file

fwrite( &infoHeader, sizeof( BITMAPINFOHEADER ), 1, file );


// Create a new buffer which will hold the data we are going to save

// We need a new buffer because we have to swap RGB to BGR

unsigned char *tempData = new unsigned char[ size ];

// Copy the data to the buffer

memcpy( tempData, data, size );

// Swap the R and B values to get BGR.

swapColors( tempData, size );

fwrite( tempData, size, 1, file );

fclose( file );

// Delete the temporary buffer

delete [] tempData;

return true;
}


// Destroy a window if we have one

inline void destroyBitmap()
{
if ( data == NULL )
return;

delete [] data;
data = NULL;
}



// Return the bitmaps data

inline unsigned char *getData()
{
return data;
}


// Return the bitmaps width

inline unsigned short getWidth()
{
return width;
}


// Return the bitmaps width

inline unsigned short getHeight()
{
return height;
}



// Return the Universal bitmap identifier 0x4D42

static unsigned short bitmapId()
{
return 0x4D42;
}



// Swap the red and blue bytes.

// Windows stores bitmaps in BGR ( Blue, Green, Red )

static void swapColors( void* buffer, int size )
{
int s = size / 3;

__asm
{
mov ecx, s
mov ebx, buffer

label:
mov al, [ebx+0]
xchg al, [ebx+2]
mov [ebx+0], al

add ebx,3

loop label
}
}
};

Share this post


Link to post
Share on other sites
Guest Anonymous Poster

// to create the texture

GLuint t;
CBitmap b;
b.createBitmap("thatexture.bmp");
glGenTextures(1, &t);
glBindTexture(GL_TEXTURE_2D, t);\
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, b.getWidth(), b.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, b.getData());
b.destroyBitmap(); // you won''t need this anymore



// to use the texture

glBindTexture(GL_TEXTURE_2D, t);
glBegin(GL_TRIANGLES);

... // render stuf


glEnd();


// to destroy the texture

glDeleteTextures(1, &t);
[/code]

Share this post


Link to post
Share on other sites
ah I misunderstood the entire thing... since the tutor already uses LoadBMP, what is the advantage of creating this class? purely getting rid of AUX_RGBImageRec? and does that mean you can get rid of the header glaux?

Share this post


Link to post
Share on other sites
quote:
Original post by Ruudje
ah I misunderstood the entire thing... since the tutor already uses LoadBMP, what is the advantage of creating this class? purely getting rid of AUX_RGBImageRec? and does that mean you can get rid of the header glaux?


Precisely

Share this post


Link to post
Share on other sites
uh... id like one more please :D

anywayz, is it OK for me to use that code from ''anonymous''? havent studied it yet, but I''ll probably create my own format soon enough. (had one for ddraw7, which could work for this as well.)

Share this post


Link to post
Share on other sites
quote:
Original post by Ruudje
anywayz, is it OK for me to use that code from 'anonymous'?


always write your own. even AP will let you get away with using his freely contributed source code, someone else in the future might not. It's best to get used to doing your own coding.

edit: misspelling 'freely' with a k in the place of the l even looks kinda funny...

[edited by - crispy on July 4, 2003 9:34:10 PM]

Share this post


Link to post
Share on other sites
lol tnx, i will study it somewhere soon.

but say I want to alter the format. Above these posts I spoke of ''my'' own format (though more people probably came up with the same theory no doubt) Say I have a fileformat:

4 bytes: width
4 bytes: height
width*height times: 1 byte r + 1 byte g + 1 byte b

Can I just make the data* a list of all b+g+r values? Because it looked like that to me when quickly going over it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Can I just make the data* a list of all b+g+r values?


Yes you can, but you will have to use GL_BGR_EXT as format for <href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glfunc03_16jo.asp">glTexImage2D</a>.

Share this post


Link to post
Share on other sites
quote:
Original post by ToohrVyk
I would advise throwing in an alpha channel too...


I would advise making it optional since it makes your textures take up 25% more video memory.

Share this post


Link to post
Share on other sites