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

problems building texture from pixel data

Started by luca-deltodesco May 26, 2006 at 4:20 PM 8 replies 1.3k views
Original Post
luca-deltodesco
luca-deltodesco
im building a custom GUI in openGL for a program im making (for the reason that i havnt got to grips with win32 yet, and deffinately not for the usability i need in the program) and i built an object that i can use in my windows, Bitmap, which is just an image with a border around it that can be positioned, and the image is scaled with the same ratios to fit to the size of the Bitmap object the problem is that i couldnt get opengl textures to work for me, so im having to draw them per pixel to the screen, which as you can imagine is causing slow down with CPU usage jumping to 99% even with a small bitmap object now. im using a custom class i made to load bitmaps from file into an array of unsigned integers in the form [r,g,b, r,g,b r,g,b r,g,b] row by row from left to right in continuous data so that to access a pixel, you would find m = 3*(y*height+x), and then the pixel colours would be data[m], data[m+1], data[m+2] now, im not sure first of all if this is format functions like gluScaleImage, and glTexImage2D will take, certainly ive tried and all i get is blackness, so supposing that like there, i have the pixel data in the array 'data' if i attempt to do gluBuild2DMipmaps(GL_TEXTURE_2D,3,width,height,GL_RGB,GL_UNSIGNED_INT,data); i dont get any errors from openGL, but if i try to draw the texture, i get blackness, ive also tried using just glTexImage2D with an image fitting the required dimensions, and i still get blackness, ive tried scaling the pixel data with gluScaleImage and then using glTexImage2D, i still get blackness well anyways, heres a compilable example that im attempting to get to work, except for the gdi32, opengl32, and glu32 libraries that have to be linked still

//Bitmap24.h
class Bitmap24
{
 public:
   unsigned int width;
   unsigned int height;
   
   unsigned int bfSize;
   unsigned int bfOffBits;
   
   unsigned int biSize;
   unsigned int biXPelsPerMeter;
   unsigned int biYPelsPerMeter;
   
   unsigned int * data;
   
   char drive[_MAX_DRIVE];
   char dir[_MAX_DIR];
   char filename[_MAX_FNAME];
   char ext[_MAX_EXT]; 
   
   Bitmap24()
   {
      data = NULL;
   }
   ~Bitmap24()
   {
      if(data!=NULL) delete [] data;
   }
   
   bool loadBitmap(char * path,bool local=false)
   {
     FILE * file;
     if(local)
     {
  	   char path2 [256];
       GetCurrentDirectory(sizeof(path2), path2);
       strcat(path2,path);
       file = fopen(path2,"rb");
     }else 
  	   file = fopen(path,"rb");
     if(file==NULL) return false;
     
     fseek(file,0,SEEK_SET);
     
     char check[3];
     memset(check,0,3);
     fread(check,1,2,file); 
     if(strcmp(check,"BM")!=0) { fclose(file); return false; }
   
     fread(&bfSize,4,1,file);
     
     fseek(file,28,SEEK_SET);
     
     unsigned short bit;
     fread(&bit,2,1,file);
     if(bit!=24) { fclose(file); return false; }
     
     _splitpath(path, drive, dir, filename, ext );
     
     fseek(file,10,SEEK_SET);
     
     fread(&bfOffBits,4,1,file);
     fread(&biSize,4,1,file);
  	 fread(&width,4,1,file);
  	 fread(&height,4,1,file);
  	 
  	 fseek(file,38,SEEK_SET);
  	 fread(&biXPelsPerMeter,4,1,file);
  	 fread(&biYPelsPerMeter,4,1,file);
  	 
  	 data = new unsigned int[width*height*3];
  	 
 	   unsigned short dx = (width*3)%4;
  	 
	   fseek(file,54,SEEK_SET);
	 
     for(unsigned int y=0; y < height; y++)
     {
       for(unsigned int x=0; x < width; x++)
       {
         int index = (y*width + x)*3;
         fread(&data[index+2], 1,1, file);
         fread(&data[index+1], 1,1, file);
         fread(&data[index+0], 1,1, file);
       }
       if(dx!=0)
			 {
         fseek(file,dx,SEEK_CUR);
			 }
	  }
   
     fclose(file);
     return true;
   }
   bool loadBitmap2(char * path,bool local=false)
   {
		   if(!loadBitmap(path,local)) return false;
			 
			 int nwidth = 1<<((int)round(log( float(width) )/log(2) ));
			 int nheight = 1<<((int)round(log( float(height) )/log(2) ));
			 
			 unsigned int * data2 = new unsigned int[3*nwidth*nheight];
			 
			 gluScaleImage(GL_RGB,width,height,GL_UNSIGNED_INT,data,nwidth,nheight,GL_UNSIGNED_INT,data2);
			 
			 delete [] data;
			 data = data2;
			 
			 width = nwidth;
			 height = nheight;
			 
			 return true;
   }
   bool writeBitmap(char * path)
   {
     FILE * file = fopen(path,"wb");
     if(file==NULL) return false;
     
     bfSize = 54 + 3*height*(width+(3*width)%4);
     
     fseek(file,0,SEEK_SET);
     fwrite("BM",1,2,file);
     fwrite(&bfSize,4,1,file);
   	 unsigned short a = 0;
   	 unsigned short a2 = 1;
   	 unsigned int b = 54;
     fwrite(&a,2,2,file);
     fwrite(&b,4,1,file); b = 40;
     fwrite(&b,4,1,file);
  	 fwrite(&width,4,1,file);
  	 fwrite(&height,4,1,file);
  	 fwrite(&a2,2,1,file);
  	 a = 24;
  	 fwrite(&a,2,1,file);
  	 b = 0;
  	 fwrite(&b,4,6,file);
  	 
  	 unsigned short dx = (width*3)%4;
  	 
  	 char c = '0';
  	 
     for(unsigned int y=0; y < height; y++)
     {
       for(unsigned int x=0; x < width; x++)
       {
         int index = (y*width + x)*3;
         fwrite(&data[index+2], 1,1, file);
         fwrite(&data[index+1], 1,1, file);
         fwrite(&data[index+0], 1,1, file);
       }
       if(dx!=0)
			 {
         fwrite(&c,1,dx,file);
		   }
  	 }
     
     fclose(file);
     return true;
   }

};

//testtex.cpp
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <Bitmap24.h>

typedef unsigned int uint;
typedef unsigned long int ulint;
typedef unsigned short int usint;
typedef long int lint;
typedef short int sint;

uint WINDOW_WIDTH = 1024;
uint WINDOW_HEIGHT = 768;
const char * WINDOW_NAME = "window";
uint WINDOW_COLOR = 32;
uint WINDOW_FULLSCREEN;

const float xsca = 2.0f/(1024.0f-6.0f);    
const float ysca = 2.0f/(768.0f-25.0f);

uint width = 1024-6;
uint height = 768-25;

double x2 = double(width)/2;
double y2 = double(height)/2;

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow);
void GLinit();
void GLloop();

HWND hWnd;
HDC hDC;
HGLRC hRC;
HINSTANCE hInstance;
LPSTR autoopen;
bool done = false;

/******************************************************************************/
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{  
  MSG msg;
  hInstance = hInst;
  
  autoopen = lpCmdLine;
  
  WNDCLASS WndCls;
    ZeroMemory(&WndCls, sizeof(WndCls));
	  WndCls.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC;
    WndCls.lpfnWndProc = WndProc;
    WndCls.hInstance = GetModuleHandle(NULL);
    WndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndCls.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndCls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
    WndCls.lpszClassName = "OpenGL";

	RegisterClass(&WndCls);

  DEVMODE dm;
  DWORD	dwstyle = 0;
  
  dwstyle = WS_CAPTION|WS_MINIMIZEBOX|WS_THICKFRAME^WS_SIZEBOX;
	     
	hWnd = CreateWindow("OpenGL", WINDOW_NAME, 
		     dwstyle|WS_POPUP|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, 
		     CW_USEDEFAULT, CW_USEDEFAULT, 
		     WINDOW_WIDTH,
		     WINDOW_HEIGHT, 
		     NULL, NULL, hInstance, NULL);
	
	if( !hWnd )
		return 0;
  
  unsigned int PixelFormat;
	PIXELFORMATDESCRIPTOR	pfd;
    ZeroMemory(&pfd, sizeof(pfd));
  	pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
 	  pfd.nVersion = 1;
  	pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
	  pfd.iPixelType = PFD_TYPE_RGBA;
	  pfd.cColorBits = WINDOW_COLOR;
    pfd.cDepthBits = 24;
  
  hDC = GetDC(hWnd);
  if(!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
  {
    MessageBox(hWnd, "Failed to choose pixel format.", "ERROR", MB_OK);
    return FALSE;
  }
  if(!SetPixelFormat(hDC, PixelFormat, &pfd))
  {
    MessageBox(hWnd, "Failed to set pixel format.", "ERROR", MB_OK);
    return FALSE;
  }
  if(!(hRC = wglCreateContext(hDC)))
  {
    MessageBox(hWnd, "Failed to create the OpenGL rendering context.", "ERROR", MB_OK);
    return FALSE;
  }
  if(!wglMakeCurrent(hDC, hRC))
  {
    MessageBox(hWnd, "Failed to make current the OpenGL rendering context.", "ERROR", MB_OK);
    return FALSE;
  }
  
	ShowWindow(hWnd, SW_SHOWNORMAL);
	SetForegroundWindow(hWnd); 
	
	glViewport(0, 0, WINDOW_WIDTH-6, WINDOW_HEIGHT-25);
  
  GLinit();
    
	while(!done){
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
			if(msg.message==WM_QUIT)
				done = true;
			else{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		
    GLloop();
		SwapBuffers(hDC); 
	}
	
	wglMakeCurrent(NULL, NULL);
  wglDeleteContext(hRC);
	ReleaseDC(hWnd, hDC);
	if(WINDOW_FULLSCREEN)
  	 ChangeDisplaySettings(NULL, 0);
  	 
	DestroyWindow(hWnd);
	return msg.wParam;
} 			 

/******************************************************************************/
Bitmap24 texmap;
GLuint texture;

void GLinit() 
{
  texmap.loadBitmap2("D:\\MAP.bmp");
     
  glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	
	glEnable (GL_LINE_SMOOTH);
	glEnable (GL_TEXTURE_2D); 
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
  
  glGenTextures(1,&texture);
  glBindTexture( GL_TEXTURE_2D, texture );
 
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  
	glTexImage2D(GL_TEXTURE_2D,0,3,texmap.width,texmap.height,0,GL_RGB,GL_UNSIGNED_INT,texmap.data);
}

void GLloop()
{
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  
  glBindTexture( GL_TEXTURE_2D, texture );
  glBegin( GL_QUADS );
   glTexCoord2d(0.0,0.0); glVertex2f(-1.0,-1.0);
   glTexCoord2d(1.0,0.0); glVertex2f(+1.0,-1.0);
   glTexCoord2d(1.0,1.0); glVertex2f(+1.0,+1.0);
   glTexCoord2d(0.0,1.0); glVertex2f(-1.0,+1.0);
  glEnd();
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg)
	{
	  case WM_LBUTTONDBLCLK:
	      break;
	  case WM_MOUSEMOVE:
		  break;
	  case WM_LBUTTONDOWN:
		  break;
	  case WM_LBUTTONUP:
		  break;
	  case WM_CHAR:
		   break;
		case WM_KEYDOWN:
			switch(wParam)
			{
				case VK_ESCAPE:
                    done = true;
					break;
				default:
					break;
			}
			break;
		case WM_DESTROY:
			break;
		case WM_SIZE:
			break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
obiviously you arent going to have the image im loading in, so youll have to change that to something that you have
Anudh
Anudh
Are you sure the bitmap loader is okay ? Why dont you try loading your bitmap with auxDIBImageLoad ? You could see if this works and then port the loading to your bitmap24 class. Here's your complete GLinit function for your convenience.

void GLinit() {  //texmap.loadBitmap2("D:\\MAP.bmp");  glShadeModel(GL_SMOOTH);  glClearColor(0.0f, 0.0f, 0.0f, 0.5f);  glClearDepth(1.0f);  glEnable(GL_DEPTH_TEST);  glDepthFunc(GL_LEQUAL);  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  glEnable (GL_LINE_SMOOTH);  glEnable (GL_TEXTURE_2D);   //glEnable (GL_BLEND);  //Disable blend for now... just in case  //glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);  AUX_RGBImageRec *pTextureImage = auxDIBImageLoad( "MAP.bmp" );	if( pTextureImage != NULL )	{		glGenTextures( 1, &g_textureID );		glBindTexture( GL_TEXTURE_2D, g_textureID );		glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );		glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST );		glTexImage2D( GL_TEXTURE_2D, 0, 3, pTextureImage->sizeX, pTextureImage->sizeY, 0,			GL_RGB, GL_UNSIGNED_BYTE, pTextureImage->data );	}	if( pTextureImage )	{		if( pTextureImage->data )			free( pTextureImage->data );		free( pTextureImage );	}}
-[Anudhyan][Website]
MARS_999
MARS_999
wow you should really use source tags to put that code into or phantom may have a cow!
luca-deltodesco
luca-deltodesco
where can i find this function? i tried just using it, but it hasnt been defined, i have windows, glu, and gl (headers) all included. where can i find it?

And yes, although i have came across some strange problems in loading bitmaps, my class does work for most bitmaps that ive came across, it must be, because i am actually displaying them on the screen per pixel and saving bitmaps


----

i found out its part of glaux.h, but dev-cpp does not come with this, and i cant seem to find anywhere to download it..

----

would you believe that i changed my Bitmap24 class to store pixel data in unsigned char's instead of unsigned int's, changed the bitmap functions to GL_UNSIGNED_BYTE, and guess what... its working! :X
luca-deltodesco
luca-deltodesco
ok, now im stuck again

when using just glTexImage2D, i imagined it would actually only work with bitmaps of dimensions 2^n, but it seems to be working with some bitmaps that aernt, but with otheres it doesnt, for example, i tried with a bitmap of 400*400, and it worked fine, but another bitmap that was 470*391 didnt and this is one of the ones causing problems elsewhere

ive tried using gluScaleImage to scale the bitmaps to dimensions 2^n, but its still these certain bitmaps that dont work

ive tried using gluBuild2DMipmaps but that doesnt seem to let these bitmaps work either

im not sure whether its the bitmaps themselves, which are having their dimensions and pixel data loaded correctly, or whether its opengl having something to do with their dimensions

some of the bitmaps, the colours are ok, but the rendering of them is very dodgy, like different rows being incremented horizontally increasingly, and some of them have their orientation correct, but the colours dodgy
DMINATOR
DMINATOR
There is a general rule, when loading textures. The textures must be power of 2.

32,64,128,256,512 ....

And btw. Have you checked the nehe code for bitmap loading. I think it is a good choice to get and idea how bitmap loading works. Tutorial here

Or you can use this code
//Loads a bitmap texturevoid BMP_Texture(UINT textureArray[], LPSTR strFileName, int ID){	if(!strFileName)   return;		AUX_RGBImageRec *pBitMap = auxDIBImageLoad(strFileName);		if(pBitMap == NULL)	exit(0);	glGenTextures(1, &textureArray[ID]);	glBindTexture(GL_TEXTURE_2D, textureArray[ID]);	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBitMap->sizeX, pBitMap->sizeY, GL_RGB, GL_UNSIGNED_BYTE, pBitMap->data);	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);		if (pBitMap)											{		if (pBitMap->data)										{			free(pBitMap->data);								}		free(pBitMap);										}}// Somewhere in the codeUINT TextureArray[1];BMP_Texture(TextureArray, "test3.bmp", 0);
luca-deltodesco
luca-deltodesco
well as i said, i dont have glaux and cant find anywhere to download it, but either way, i still need to know how the pixel data is set up, because i need to manipulate the bitmaps

my bitmap loading, saving is based on a .bmp file format i found on internet, which has been working fine for months now
luca-deltodesco
luca-deltodesco
well, i gave up on the glu functions, and i made my own simplified version to resize the images, and its working fine now...

but i do have something very strange happening


i have mulitple textures from different images i need to create, and in the function that i have to do so, i have this to set up the opengl texture

glGenTextures( 1, &bit->texnum);glBindTexture( GL_TEXTURE_2D, bit->texnum );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST );glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glTexImage2D( GL_TEXTURE_2D, 0, 3, bit->renderbit.width, bit->renderbit.height, 0,GL_RGB, GL_UNSIGNED_BYTE, bit->renderbit.data );	delete [] bit->renderbit.data;


however, the bitmaps can also change, either via the user loading in a different image, or by a function being called that manipulates one of the bitmaps, so in another function i have to refresh the holder clip, i have this aswell

glDeleteTextures(1,&bit->texnum);glGenTextures(1,&bit->texnum);glBindTexture( GL_TEXTURE_2D, bit->texnum );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR );glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST );glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );  bit->thebitmap.resizeto2(&bit->renderbit); glTexImage2D( GL_TEXTURE_2D, 0, 3, bit->renderbit.width, bit->renderbit.height, 0,GL_RGB, GL_UNSIGNED_BYTE, bit->renderbit.data );	delete [] bit->renderbit.data;


which im hoping should delete the texture from the video memory, and add the new bitmap into the video memory as a new texture

but the strange problems are this:

before the function containing the second block of code is even called. Rather than just the actual Quads im drawing with the texture being drawn with the texture... ANYthing that is coloured white, is suddenly coloured with the colour of the first texel, EVEN if i comment out the part that draws the quad with the texture, just having created the texture in the first block of code, is making all the white turn to the colour of the texel

when a quad with the texture is drawn, it seems ok (apart from the above) but also if i then load in a new bitmap in the program, and the function containing the second block of code is run, all the white changes to the new colour of the first texel of the texture, but not only this, everyother texture that im drawing, is being changed aswell

glColor3f(1,1,1);glBegin(GL_QUADS); glBindTexture( GL_TEXTURE_2D, bit->texnum ); glTexCoord2d(0.0,1.0); glVertex2f(ww*xsca,-hh*ysca); glTexCoord2d(1.0,1.0); glVertex2f((ww+float(bit->x2))*xsca,-hh*ysca); glTexCoord2d(1.0,0.0);  glVertex2f((ww+float(bit->x2))*xsca,-(hh+float(bit->y2))*ysca); glTexCoord2d(0.0,0.0); glVertex2f(ww*xsca,-(hh+float(bit->y2))*ysca);glEnd();


this is the snipped of code in the GLloop function, that is being run to draw the quad with the texture

note that each bitmap object i have in the program, has its own bitmap image, and has the first bit of code run for it, with texnum being stored inside and accessed again here
luca-deltodesco
luca-deltodesco
well ive fixed one of the problems to do with the non drawing of textures (i forgot to enable and disable GL_TEXTURE_2D, so that when i wasnt drawing with the textures, the colour was still there or sometihng along those lines, i know have it so before drawing the bitmap, its enabled, and then afterwards disabled)

however im still having problems that when i create one texture, all the other textures change aswell.

even if i replace glGenTextures, with an an incremental integer, when i change one, they all change

Topic Locked

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

Sign in to reply to this topic.