Skip to main content
gamedev.net
🔒 Locked 🎲 GameMaker

Loading bitmap

Started by tnutty Mar 8, 2009 at 7:09 PM 20 replies 3.2k views
Original Post
tnutty
tnutty
I have a bitmap function that load bit map as shown below. The problem is that this function does not stretch the whole star into a quads for which I use transparency in order to make it look like only the star is there and not the quad. Instead, each quad has 3 small star and a wried line underneath the star. So, the quads thats supposed to look like a single star because of glblend, does not. Can you see why this is doing so. The end result of my program should look like a spiral of stars constantly swirling around the center, but instead, it looks like 3 start for each star I load onto a quad. here is what my star looks like : http://img186.imageshack.us/my.php?image=mystar.jpg whereas you could imagine what it should look like here is my Bmploader()

#include<GL/glut.h>
#include<cstdio>
#include<windows.h>
#include"Global.h"

int texID = -1;

int loadBitmap(char * Filename)
{
	unsigned char *ucTexSize;
	RGBTRIPLE rgb;
	BITMAPFILEHEADER fHeader;
	BITMAPINFOHEADER iInfo;
	FILE* pFile = NULL;

	texID++;

	pFile = fopen(Filename,"rb");
	
	if(pFile == NULL)
	{
		MessageBox(NULL,L"ERROR: READING BITMAP FAILED!",L"LOADING BITMAP IMAGE",MB_OK);
		fclose(pFile);
		return -1;
	}

	fread(&fHeader,sizeof(fHeader),1,pFile);
	fseek(pFile,sizeof(fHeader),SEEK_SET);
	fread(&iInfo,sizeof(iInfo),1,pFile);


	ucTexSize = (byte *) malloc(iInfo.biWidth * iInfo.biHeight * 4);
	memset(ucTexSize,0,iInfo.biWidth*iInfo.biHeight*4);

	for(int i=0,j=0;i<iInfo.biHeight*iInfo.biWidth;i++)
	{
		fread(&rgb,sizeof(rgb),1,pFile);
		
		ucTexSize[j+0] = rgb.rgbtRed;
		ucTexSize[j+1] = rgb.rgbtGreen;
		ucTexSize[j+2] = rgb.rgbtBlue;
		ucTexSize[j+3] = 255;
		j+=4;
	}

	
	fclose(pFile);

	glBindTexture(GL_TEXTURE_2D,texID);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_GEN_S,GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_GEN_T,GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);
	
	glTexImage2D(GL_TEXTURE_2D,0,4,iInfo.biWidth,iInfo.biHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,ucTexSize);
	gluBuild2DMipmaps(GL_TEXTURE_2D,4,iInfo.biWidth,iInfo.biHeight,GL_RGBA,GL_UNSIGNED_BYTE,ucTexSize);


	free(ucTexSize);

	return(texID);
}

Our whole life is a opengl application.
mobeen
mobeen
Hi,
This is related to how bitmaps are stored in memory. If you have a power of two bitmap, it fits nicely into the memory but if there is a non power of two bitmap, every single scan line (stride) will be padded with zeros so that it can fit nicely into the memory. You need to calculate the pitch and then use that information while you load the bitmap.

For power of two bitmaps,
stride =bitmap width
but for non power of two bitmaps, it's
stride =bitmap width + (zero padding width);

I think you might be assuming that the total number of bytes in bitmap are
totalBytes =bmWidth*bmHeight*bmBytesPerPixel;
this is ok only for power of two images and will fail for non power of two images.
The solution is to use the bmWidthBytes field of the BITMAP struct that contains the whole stride width. So the total bytes are
totalBytes = bmHeight*bmWidthBytes;

Here is a simple win32 based bmp loader code see if this helps.
void LoadBMP(const char* filename, GLubyte** imgPtr, int& w, int& h ){   HBITMAP hbmp;    BITMAP	bmp;    hbmp=(HBITMAP)LoadImage(GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );   GetObject(hbmp, sizeof(bmp), &bmp);  				   		   w = bmp.bmWidth;   h = bmp.bmHeight;    int size = bmp.bmHeight*bmp.bmWidthBytes;   *imgPtr=new GLubyte[size];   memcpy(*imgPtr,bmp.bmBits,size);	   DeleteObject(hbmp);	}


Hope this helps,
Mobeen
Proud to be a PAKISTANI.
tnutty
tnutty
hey thanks for the reply.

I couldn't get you bmploader to work, but
when I checked the dimension of the star.bmp it
was 128 x 128.

This is a power of 2.

But i notice that the only time I could load a whole image without it repeating is a image whose dimension is 256 x 256.

I am not sure why this is.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
hey thanks for the reply.

I couldn't get you bmploader to work ...

What error does it give you? I can load all 24 bit rgb bitmaps (power of 2 and non power of 2) correctly using it. I tested it on my system to see if it works and it is working for me.
Here are the snapshots from my test.



One more thing, it might be that you previous code is working also but you are not setting the texture params / tex coordinates correctly?
Just noticed in your previous code, the third parameter in call to
glTexImage2D and 2nd param to gluBuild2DMipmaps is the internal format which should be GL_RGBA for your case and not 4. See if this sorts out the problem?

Thanks,
Mobeen
Proud to be a PAKISTANI.
tnutty
tnutty
I was thinking that. I changed it from rgba to 4 to see if that helps.

when i tried it it was late. I'll try it in a bit. Thanks for your help so far.
Our whole life is a opengl application.
tnutty
tnutty
I changed the internalFormat for both of the parameters of texImage2D and build2d, and got the same result.

Maybe my LoadBitmap is not loading correctly?

If you want I could zip the solution to you so you can check it?
Although you dont have too.

[Edited by - tnutty on March 9, 2009 7:06:37 PM]
Our whole life is a opengl application.
tnutty
tnutty
Its definitely my bmpLoader because when I converted the 128x128 bmp image to

256x256 tga image and used my tga loader, the star came out as 1 full star without any defects expect the colors did not change for some reason, so the star was just white in a black background, but still!
Any advice how why my bmp is like so? OR can you help me add a portion to my LoadBitmap function so it does not have to take only 2^n by 2^m bmp image.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
Its definitely my bmpLoader because when I converted the 128x128 bmp image to

256x256 tga image and used my tga loader, the star came out as 1 full star without any defects expect the colors did not change for some reason, so the star was just white in a black background, but still!
Any advice how why my bmp is like so? OR can you help me add a portion to my LoadBitmap function so it does not have to take only 2^n by 2^m bmp image.

Sure send the code to my email mmmova@yahoo.com I'll see if i can make it work.

Thanks,
Mobeen
Proud to be a PAKISTANI.
tnutty
tnutty
Cool man I'll send it now.

These are the keys :
{
default = transparent quads swirling.

x = Star swirling using LoadBitmap() function.

c = Star swirling using TGALoader function.

space bar : twinkle = true; makes the star "shine".
}

Thanks man.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
Cool man I'll send it now.

These are the keys :
{
default = transparent quads swirling.

x = Star swirling using LoadBitmap() function.

c = Star swirling using TGALoader function.

space bar : twinkle = true; makes the star "shine".
}

Thanks man.


Hi there,
Actually, the bitmap is a color index bitmap (8bpp see the iInfo.biBitCount field) this means that the bitmap has an associated color table present in bmciColors field of BITMAPINFO structure. You need to load the table and then use the indices stored to get the colors. Moreover, the internal format must match the data contained in the bitmap pixels loaded from the file. Here again the biBitCount field or bmp.bmBitsPixel field can be used to find the number of bytes per pixel.
For the version i gave earlier, you dont have to do this yourself as the gdi function LoadBitmap does it for u. I have modified you loadBitmap function. I have checked it with your image in the code and its working fine. Please note that the bitmap is shown ok but this is not a good approach to load a bitmap. I would recommend the image loading libraries like devIL and freeImage as they handle the intricate details of the format and abstract it from u.
I have not tested this on 1,4,24 and 32 bitper pixel bmp images but i think it should work fine. Here is the loadBitmap function for you.

int loadBitmap( char* filename){   GLubyte* pixels;   HBITMAP hbmp;    BITMAP  bmp;    GLuint size;   GLenum format;   GLuint totalBytes;   texID++;   hbmp=(HBITMAP)LoadImage(GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );   if(hbmp==NULL)      return -1;   GetObject(hbmp, sizeof(bmp), &bmp);  				       size = bmp.bmHeight*bmp.bmWidthBytes;      totalBytes = bmp.bmBitsPixel/8;   switch(bmp.bmBitsPixel){		case 1:		case 4: 		case 8:		   format = GL_LUMINANCE;					break;		case 24:   		   format = GL_RGB;		break;		case 32:  		   format = GL_RGBA;		break;   }   pixels=new GLubyte[size];   memcpy(pixels,bmp.bmBits,size);	   DeleteObject(hbmp);   glBindTexture(GL_TEXTURE_2D,texID);   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_GEN_S,GL_REPEAT);   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_GEN_T,GL_REPEAT);   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);   glTexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_REPLACE);	    glTexImage2D(GL_TEXTURE_2D,0,format,bmp.bmWidth,bmp.bmHeight,0,format,GL_UNSIGNED_BYTE,pixels);   gluBuild2DMipmaps(GL_TEXTURE_2D,totalBytes,bmp.bmWidth,bmp.bmHeight,format,GL_UNSIGNED_BYTE,pixels);   delete [] pixels;   return 1;}



Hope this helps,
Thanks,
Mobeen

[Edited by - mobeen on March 10, 2009 2:02:17 AM]
Proud to be a PAKISTANI.
tnutty
tnutty
thanks man.

I look up on bitmap tomorrow and try to figure it out as well. Thanks for
the hint. Take your time.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
thanks man.

I look up on bitmap tomorrow and try to figure it out as well. Thanks for
the hint. Take your time.


Check your email.
Proud to be a PAKISTANI.
tnutty
tnutty
This is wried. When I load your project it compiles. But when I copy the
files into my original file I get two errors:

error C2664: 'LoadImageW' : cannot convert parameter 2 from 'char *' to 'LPCWSTR'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

The above error was for this line :
hbmp=(HBITMAP)LoadImage(GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );


AND THE SECOND ERROR WAS :

error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [30]' to 'LPCWSTR'

and that error was for this line :
	if(pFile == NULL)	{		MessageBox(NULL,"ERROR: READING BITMAP FAILED!","LOADING BITMAP IMAGE",MB_OK);		fclose(pFile);		return -1;	}



I directly copied it to my file by right click copy and paste. Why would the
compiler give me an error. It doesn't make sense.

By the way thanks for your help. The stars look good in my program.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
This is wried. When I load your project it compiles. But when I copy the
files into my original file I get two errors:

error C2664: 'LoadImageW' : cannot convert parameter 2 from 'char *' to 'LPCWSTR'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

The above error was for this line :
hbmp=(HBITMAP)LoadImage(GetModuleHandle(NULL), filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );


AND THE SECOND ERROR WAS :

error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [30]' to 'LPCWSTR'

and that error was for this line :
	if(pFile == NULL)	{		MessageBox(NULL,"ERROR: READING BITMAP FAILED!","LOADING BITMAP IMAGE",MB_OK);		fclose(pFile);		return -1;	}



I directly copied it to my file by right click copy and paste. Why would the
compiler give me an error. It doesn't make sense.

By the way thanks for your help. The stars look good in my program.


Hi,
I think you are using Visual Studio 8 or above. These compilers have default support for unicode character sets. For all the functions that are provided with windows for e.g. MessageBox, there are two versions, one accepting a wide char pointer and another accepting a generic type point (TCHAR). Now based on you compiler's settings of support for unicode(multi-byte character set)/single byte character set, the appropriate functions are loaded. In your case the multibyte version MessageBoxW and LoadImageW are loaded and they expect the parameters to be wide character set but since we are providing a single byte character set, the error is raised.

The solution is to add an L macro to all strings like this,
MessageBox(NULL,L"ERROR: READING BITMAP FAILED!",L"LOADING BITMAP IMAGE",MB_OK);


also change the char* filename parameter to either TCHAR* filename or wchar_t* filename, and then when you call this function use TEXT() macro for TCHAR and L macro for wchar_t. Take one of the two approaches
//wide char versionint loadBitmap(wchar_t* filename){...}  //when calling it use loadBitmap(L"c:\Test.bmp");//generic versionint loadBitmap(TCHAR* filename){...}  //when calling it use loadBitmap(TEXT("c:\Test.bmp"));

I hope you get this otherwise bug me again :)
Thanks,
Mobeen
Proud to be a PAKISTANI.
tnutty
tnutty
I figured out the L"..." but for loadImage(...) I wasn't sure.
And about that solution you gave me for loadImage()...sorry.


with loadbitmap(TCHAR* Filename); //in main using loadbitmap(TEXT("c:\Stars.bmp"))

error :
 error C2664: 'loadBitmap' : cannot convert parameter 1 from 'const wchar_t [9]' to 'char *'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


and with loadbitmap(wchar_t Filename)//in main loadbitmap(L"c:\Star.bmp");

error :
error C2664: 'loadBitmap' : cannot convert parameter 1 from 'const wchar_t [11]' to 'char *'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


These compilers are starting to bug me so much.
Sorry if I am bugging you man. Thanks for taking your time to help me.
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
I figured out the L"..." but for loadImage(...) I wasn't sure.
And about that solution you gave me for loadImage()...sorry.


with loadbitmap(TCHAR* Filename); //in main using loadbitmap(TEXT("c:\Stars.bmp"))

error :
 error C2664: 'loadBitmap' : cannot convert parameter 1 from 'const wchar_t [9]' to 'char *'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


and with loadbitmap(wchar_t Filename)//in main loadbitmap(L"c:\Star.bmp");

error :
error C2664: 'loadBitmap' : cannot convert parameter 1 from 'const wchar_t [11]' to 'char *'1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


These compilers are starting to bug me so much.
Sorry if I am bugging you man. Thanks for taking your time to help me.


Hi,
1) I have the following settings in vstudio .net 2003,
General -> CharacterSet = Use Unicode Character Set
2) Then in my code i have the loadbitmap function defined as
int loadBitmap( TCHAR* filename){...}

3) I have removed the declaration of loadBitmap from your header globals.h into the main file main.cpp.
4) In the main.cpp keyboard handler, i have this case'x':loadBitmap(TEXT("Star.bmp"));break;
5) In ms visual studio .net 2003, I get 0 compile errors and 0 link errors. here is a snapshot
I converted the solution to visual studio 2005 and yet i get 0 errors. here is the snapshot from the solution.


I am sending the two versions to you. Let me know if u still can't get it running.
Thanks,
Mobeen
Proud to be a PAKISTANI.
tnutty
tnutty
I got the email. Its getting late so I check it tommorow, plus my brain hurts from my physics assignments.

regards,

TNUTTY
Our whole life is a opengl application.
tnutty
tnutty
This express edition seems to still complain with your version of code, both
03 and 05. You know what Forget about it. I don't want to waste your time.
Thanks for all your help man. I try to figure this out. You gave me a start at least.
OH and I have it on the same setings as well for my project, in set unicode.

[Edited by - tnutty on March 11, 2009 1:43:48 PM]
Our whole life is a opengl application.
tnutty
tnutty
Hey can you explain the loadbitmap function that you made a little bit?
The one you emailed to me? I dont know much win API. I searched in msdn,
but did not get what certaing function did.


[Edited by - tnutty on March 11, 2009 6:06:12 PM]
Our whole life is a opengl application.
mobeen
mobeen
Quote:
Original post by tnutty
Hey can you explain the loadbitmap function that you made a little bit?
The one you emailed to me? I dont know much win API. I searched in msdn,
but did not get what certaing function did.


Hi,
The function is using the WinGDI LoadBitmap function. I refered to Windows Programming by Charles Petzold it contains the details you might want to see if u are interested in the details.
NOTE: As I already mentioned, this is a really quick way of getting the bmp loaded however there might be cases where this may fail. Therefore, i advice you to look at some of the image loading libraries like devIL and free image. They take care of the details for you and save u a lot of hastle so that u may work on your purpose.
I think I have wasted quite a bit of my time already to resolve some stupid compiler issues. I think it would be a good learning thing for u to figure these out urself. Consider this my last reply on this thread.

Thanks,
Mobeen
Proud to be a PAKISTANI.

Topic Locked

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

Sign in to reply to this topic.