C Board  

Go Back   C Board > General Programming Boards > Game Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 03-12-2006, 03:19 PM   #1
Absent Minded Programmer
 
Join Date: May 2005
Posts: 933
Loading a bitmap (Without using glaux)

Okay, so I got this bit of code from NeHe, it works alright, havn't had any problems with it so far..

Code:
LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);				// Declaration For WndProc

AUX_RGBImageRec *LoadBMP(const char *Filename)						// Loads A Bitmap Image
{
	FILE *File=NULL;												// File Handle

	if (!Filename)													// Make Sure A Filename Was Given
	{
		return NULL;												// If Not Return NULL
	}

	File=fopen(Filename,"r");										// Check To See If The File Exists

	if (File)														// Does The File Exist?
	{
		fclose(File);												// Close The Handle
		return auxDIBImageLoad(Filename);							// Load The Bitmap And Return A Pointer
	}

	return NULL;													// If Load Failed Return NULL
}

GLuint LoadGLTexture( const char *filename )						// Load Bitmaps And Convert To Textures
{
	AUX_RGBImageRec *pImage;										// Create Storage Space For The Texture
	GLuint texture = 0;												// Texture ID

	pImage = LoadBMP( filename );									// Loads The Bitmap Specified By filename

	// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
	if ( pImage != NULL && pImage->data != NULL )					// If Texture Image Exists
	{
		glGenTextures(1, &texture);									// Create The Texture

		// Typical Texture Generation Using Data From The Bitmap
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, pImage->sizeX, pImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pImage->data);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

		free(pImage->data);											// Free The Texture Image Memory
		free(pImage);												// Free The Image Structure
	}

	return texture;													// Return The Status
}
I notice that it uses auxDIBImageLoad to actually load the bitmap... The way my program is set up, I want to create a texture object with its own loading function..

Something like

Code:
class BMPTexture
{
// storage structs
// Loading Code
};
I kinda want to mirror this setup (snipped from my MS3DModel definition)

Code:
class MS3DModel
{
public:

	MS3DModel();

	virtual ~MS3DModel();

	struct Vertex
	{
		char BoneID;
		float Location[3];
	};

	int NumVertices;
	Vertex *Vertices;

	struct Triangle
	{
		float VertexNormals[3][3];
		float Textures1[3], Textures2[3];
		int VertexIndices[3];
	};

	int NumTriangles;
	Triangle *Triangles;

	struct Mesh
	{
		int MaterialIndex;
		int NumTriangles;
		int *TriangleIndices;
	};

	int NumMeshes;
	Mesh *Meshes;

	struct Material
	{
		float Ambient[4], Diffuse[4], Specular[4], Emissive[4];
		float Shininess;
		GLuint Texture;
		char *TextureFilename;
	};

	int NumMaterials;
	Material *Materials;

	bool Load( const std::string & name );
	void ReloadTextures();
	void Draw();
};
Aside from the drawing function and reloadTextures function, and of course different storage structures, I want to mirror this setup, I find it works quite nicely with the resource manager I've created, shown here:

Code:
template< typename T_ >
class Resource_Manager
{  

public:

	typedef T_ value_type; // std library convention 

	typedef boost::shared_ptr<T_> Resource_Ptr;
	typedef boost::weak_ptr<T_> Resource_Observer;
	typedef std::map< std::string, Resource_Ptr > Resource_Map;

	Resource_Manager<T_>() {};
	~Resource_Manager<T_>() {};

	Resource_Observer Request_Resource(const std::string & name)
	{
		Resource_Map::iterator  it = mResources.find(name);

		if (it == mResources.end())
		{
			Resource_Ptr Raw_Resource(new T_);
			Raw_Resource->Load(name);
			mResources.insert(std::make_pair(name, Raw_Resource));
			Resource_Observer Resource(Raw_Resource);
			return Resource;
		}
		else
		{
			return Resource_Observer(it->second);
		}
	}

	void Request_Resource_Removal(const std::string & name)
	{
		Resource_Map::iterator it = mResources.find(name);

		if (it != mResources.end())
		{
			mResources.erase(it);
		}
	}

private:
	Resource_Map  mResources;
};
As you can see, it returns a resource observer weak pointer, but the actual loading of the bitmap returns a texture ID. While applying textures via ID is what I want to be able to do, you kinda have to in opengl. HMmmm...

Looking at the loading code more closely, LoadBMP actually returns a pointer to the actual bitmap, while the GLLoadTexture func creates the texID.. The reason I want to use my manager to do all this stuff is, not to sound boastful, basically that my resource manager can do a cleaner job than the auxDIBImageLoad function. I don't really have to worry about deleting stuff with my resource manager, it is a nice way to do things IMO..

I guess my dilemma is this..

My resource manager handles pointers, it doesn't handle ID's, thus I can't mix ID creation in with my texture manager, unless maybe I'm returning an observer with a tex ID in it..... Ah yes, that's it.

If I mirror the MS3D setup I can easily add an ID in the info structs and then access the ID of the texture object with methods in that class..

So I'm guessing when I get down to it, it looks like this:

Resource_Manager&lt;BMPTexture&gt; Textures;
Textures.Request_Resource("texture name here");

Then I can access the ID via the return value of the request resource method, which is a resource observer..

Okay, is this making sense to you guys? Am I in rightful reason to want to avoid the auxDIBImageLoad function? Is what I'm proposing making sense to you guys?

Thanks.

EDIT: Really I just need to know how to load a bitmap without using auxDIBImageLoad..
__________________
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Shamino is offline   Reply With Quote
Old 03-12-2006, 05:17 PM   #2
Absent Minded Programmer
 
Join Date: May 2005
Posts: 933
So far this is what I've come up with..

Header
Code:
#ifndef BITMAP_H
#define BITMAP_H

#include <windows.h>        // Windows header file.
#include <stdio.h>          // Standard input/output.
#include <gl\gl.h>
#define BITMAP_ID 0x4D42	// The universal bitmap ID


class Bitmap
{
   public:
      Bitmap();
      ~Bitmap();

      bool Load(const char *filename); // Load a .bmp image file.
      void FreeImage();                // Delete a image.
      void Transparent(int* g_keyColor);

      unsigned int ID;                 // Texture ID.
      int imageWidth;                  // Width of a texture.
      int imageHeight;                 // Height of a texture.
      unsigned char *image;            // Texture image.
      unsigned char *TRANimage;
};

#endif
Source
Code:
#include "Bitmap.h"


Bitmap::Bitmap()
{
   // Give everything default values.
  image = 0;
  TRANimage = 0;
  imageWidth = 0;
  imageHeight = 0;
}


Bitmap::~Bitmap()
{
   FreeImage();
}


bool Bitmap::Load(const char *file)
{
	FILE *pFile = 0;

	// These will hold the bitmap header and file information.
	BITMAPINFOHEADER bitmapInfoHeader;
	BITMAPFILEHEADER header;

   // This will be used to swap the image colors from BGR to RGB.
	unsigned char textureColors = 0;

   // Open the file and make sure no errors.
	pFile = fopen(file, "rb");
	if(pFile == 0) return false;

	// Read in the bitmap header info into the BITMAPFILEHEADER variable.
	fread(&header, sizeof(BITMAPFILEHEADER), 1, pFile);

	// Make sure this is a real bitmap by checking the ID.
	if(header.bfType != BITMAP_ID)
	   {
		   fclose(pFile);
		   return false;
	   }

	// Read in the second header info into the BITMAPINFOHEADER variable.
	fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);

	// Save the width and height.
	imageWidth = bitmapInfoHeader.biWidth;
   imageHeight = bitmapInfoHeader.biHeight;

   // Make sure we read a size out of it.
   if(bitmapInfoHeader.biSizeImage == 0)
      bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *
      bitmapInfoHeader.biHeight * 3;

	// Place the pointer in front of where the image data starts.
	fseek(pFile, header.bfOffBits, SEEK_SET);

	// Dynamically create enough memory for the image.
	image = new unsigned char[bitmapInfoHeader.biSizeImage];

	// Error checking.  Make sure the memory was allocated.
	if(!image)
	   {
		   delete[] image;
		   fclose(pFile);
		   return false;
	   }

	// Read in the image.
	fread(image, 1, bitmapInfoHeader.biSizeImage, pFile);

	// Bitmaps are saved in BGR format so we will make the image RGB by...
	for(int index = 0; index < (int)bitmapInfoHeader.biSizeImage; index+=3)
	   {
		   textureColors = image[index];
		   image[index] = image[index + 2];
		   image[index + 2] = textureColors;
	   }

   // Close the file and return the image.
	fclose(pFile);
	return true;
}


void Bitmap::Transparent(int* g_keyColor)
{

    int imageSize_RGB  = imageWidth * imageHeight * 3;
    int imageSize_RGBA = imageWidth * imageHeight * 4;

     //allocate buffer for a RGBA image
    TRANimage = new unsigned char[imageSize_RGBA];


//     Loop through the original RGB image buffer and copy it over to the
//     new RGBA image buffer setting each pixel that matches the key color
//     transparent.


    int i, j;
    for(i = 0, j = 0; i < imageSize_RGB; i += 3, j += 4 )
    {
//         Does the current pixel match the selected color key?
        if( image[i]   == g_keyColor[0] &&
            image[i+1] == g_keyColor[1] &&
            image[i+2] == g_keyColor[2] )
        {
            TRANimage[j+3] = 0;   // If so, set alpha to fully transparent.
        }
        else
        {
            TRANimage[j+3] = 255; // If not, set alpha to fully opaque.
        }

        TRANimage[j]   = image[i];
        TRANimage[j+1] = image[i+1];
        TRANimage[j+2] = image[i+2];
    }
}


void Bitmap::FreeImage()
{
   // When the application is done delete all memory.
   if(image)
      {
         delete[] image;
         image = NULL;
      }

    if(TRANimage)
      {
         delete[] TRANimage;
         TRANimage = NULL;
      }
}
Now, I need to make it so ID is equal to whatever glGenTexture spits out, and then provide an access function to get the ID of the texture...

So, with my resource manager, I'll be able to pass a texture filename, and it will return a pointer, which I can use to get the ID..

No repeating textures, no dangling memory anywhere..

Hurrah for my resource manager!
__________________
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Shamino is offline   Reply With Quote
Old 03-12-2006, 05:21 PM   #3
Crazy Fool
 
Perspective's Avatar
 
Join Date: Jan 2003
Location: Canada
Posts: 2,596
>>EDIT: Really I just need to know how to load a bitmap without using auxDIBImageLoad..

http://gpwiki.org/index.php/LoadBMPCpp
Perspective is offline   Reply With Quote
Old 03-12-2006, 05:38 PM   #4
Absent Minded Programmer
 
Join Date: May 2005
Posts: 933
Hmm, that might work...

I'd need to modify the main object to store a GL tex id though, shouldn't be difficult..
__________________
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Shamino is offline   Reply With Quote
Old 03-15-2006, 07:26 PM   #5
Registered User
 
Join Date: Mar 2006
Posts: 3
Sometimes BMPs will have spacefillers of a couple of byte at the ends of each row of pixel data. I don't see any compensation for that in the wiki code, it may not be required though since it's reading the BMP data differently than I did. When I wrote my BMP loader I read it in by bytes (it was a while ago...) and I had to calculate how much blank space was at the end of each line to skip over it.

If the images are messing up (diagonally skewed) you'll need to skip over these non-data bytes. In one of the header variables it says how long the image data is. You also have height and width in pixels. If image data length != height * width, you read each rox of pixels to the width of the image, then skip a number of bytes equal to [(data length) - (height * width)]/width

I wish I had my code here, unfortunately it's on a different computer. The wiki code looks much nicer though anyways

~Mith
MithTS is offline   Reply With Quote
Old 03-16-2006, 12:19 AM   #6
Absent Minded Programmer
 
Join Date: May 2005
Posts: 933
Thanks for the heads up Mith
__________________
Sometimes I forget what I am doing when I enter a room, actually, quite often.
Shamino is offline   Reply With Quote
Old 03-16-2006, 02:52 AM   #7
Super Moderator
 
Bubba's Avatar
 
Join Date: Aug 2001
Posts: 7,817
Each row in a BMP is zero-padded to the nearest 4 byte boundary.
BMPs are stored in exact reverse color order as the hardware expects.
BMPs are stored using bottom right corner as starting place or 0.
__________________
If you aim at everything you will hit something but you won't know what it is.
Bubba is offline   Reply With Quote
Old 03-16-2006, 09:43 AM   #8
The Right Honourable
 
psychopath's Avatar
 
Join Date: Mar 2004
Location: Where circles begin.
Posts: 1,068
"BMPs are stored in exact reverse color order as the hardware expects."

Naturally.
__________________
Memorial University of Newfoundland
Computer Science

Mac and OpenGL evangelist.
psychopath is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Loading bitmap file into a HBITMAP wind_addict Windows Programming 9 11-17-2007 10:42 AM
OpenGL -- Bitmaps HQSneaker Game Programming 14 09-06-2004 04:04 PM
Loading a Bitmap resource for OpenGL Texture[x] the dead tree Game Programming 4 08-26-2004 01:12 PM
Loading bitmap in dll Mithoric Windows Programming 2 12-22-2003 01:53 PM
No one can seem to help me, loading bitmap Shadow12345 C++ Programming 7 12-28-2002 01:22 PM


All times are GMT -6. The time now is 02:04 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22