Thread: DrawIndexedPrimitive() Failing (DX9)

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    361

    DrawIndexedPrimitive() Failing (DX9)

    EDIT: SOLVED
    But I posted the next part to the problem below. You can skip this post.

    The For Loops in the InitIndexBuffer() were going one too many rounds. (I.e. while: X < (NumCols -1), should have been the case). After writing it out on paper, it made sense.


    Hullo hullo, (again, if anybody's already read this)

    I'm getting some peculiar Index Buffer problems going on.

    First, I'll blatantly post my code (feel free to skip past it), and below I'll talk about/highlight the key points.

    Code:
    bool cTerrain::InitIndexBuffer(void)
    {
    	unsigned char	*BufferIndices	= NULL;
    	unsigned short	*Indices		= NULL;
    	
    	Indices = (unsigned short*)malloc(NumIndices * sizeof(unsigned short));
    	if(Indices == NULL)
    		return false;
    
    	unsigned short A = 0;
    	unsigned short B = A + 1;
    	unsigned short C = NumCols + 1;
    
    	unsigned short X = 0;
    	unsigned short Z = 0;
    	unsigned long I = 0; //<----This here, this is the guy
    
    	//AndyPike's altered idea to meet my own style
    	for(Z = 0; Z < NumRows; Z = Z + 1)
    	{
    		for(X = 0; X < NumCols; X = X + 1)
    		{
    			Indices[ I ]	= A;
    			Indices[I + 1]	= B;
    			Indices[I + 2]	= C;
    			Indices[I + 3]	= C + 1;
    			Indices[I + 4]	= C;
    			Indices[I + 5]	= B;
    
    			A = A + 1;
    			B = B + 1;
    			C = C + 1;
    			I = I + 6;
    		}
    		A = A + 2;
    		B = B + 2;
    		C = C + 2;
    	}
    
    	IndexBuffer->Lock(0, NumIndices * sizeof(unsigned short), (void**)&BufferIndices, 0);
    
    		memcpy(BufferIndices, Indices, NumIndices * sizeof(unsigned short));
    
    	IndexBuffer->Unlock();
    
    	free(Indices);
    	Indices = NULL;
    
    	return true;
    }
    
    void cTerrain::Draw(void)
    {
    	D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(sVertex));
    	D3DDevice->SetFVF(FVF);
    	D3DDevice->SetIndices(IndexBuffer);
    	D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons);
    }
    
    bool cTerrain::LoadTerrainMap(char *FilePath, HWND *hWnd)
    {
    	//Just so you get an idea of what I'm doing, but the itallic part can be skipped
    	HBITMAP TerrainFile;
    
    	TerrainFile = (HBITMAP)LoadImage(0, FilePath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
    	if(TerrainFile == NULL)
    		return false;
    
    	BITMAP TerrainMap;
    
    	if(!(GetObject(TerrainFile, sizeof(BITMAP), &TerrainMap)))
    	{...}
    
    	BITMAPINFO TerrainInfo;
    
    	/*FILL TerrainInfo HERE*/
    
    	unsigned long *Pixels = NULL;
    
    	Pixels = (unsigned long*)malloc(TerrainInfo.bmiHeader.biHeight * TerrainInfo.bmiHeader.biWidth * sizeof(unsigned long));
    	if(Pixels == NULL)
    	{...}
    
    	HDC hDC;
    
    	hDC = GetDC(*hWnd);
    	if(hDC == NULL)
    	{...}
    
    	if(!(GetDIBits(hDC, TerrainFile, 0, TerrainInfo.bmiHeader.biHeight, Pixels, &TerrainInfo, DIB_RGB_COLORS)))
    	{...}
    
    	NumCols = (short)TerrainInfo.bmiHeader.biWidth;
    	NumRows = (short)TerrainInfo.bmiHeader.biHeight;
    
    	NumVertices = NumCols * NumRows;
    	NumPolygons = (NumCols - 1) * (NumRows - 1) * 2;
    	NumIndices  = NumPolygons * 3;
    
    	...
    
    	if(FAILED(D3DDevice->CreateIndexBuffer(NumIndices * sizeof(unsigned short), D3DUSAGE_WRITEONLY,
    		D3DFMT_INDEX16, D3DPOOL_MANAGED, &IndexBuffer, NULL)))
    	{...}
    
    	if(InitIndexBuffer() == false)
    	{...}
    
    	...
    }
    The dots represent edited out code, for the sake of nobody going insane from all the useless code. I tried to keep it condensed to only the important parts.

    If you haven't guess it, I'm loading in a Bitmap and creating vertices based on that Bitmap.

    Okay, so here's the thing, it all comes down to the I variable in the InitIndexBuffer() function.

    I used to be an "unsigned short". However, I have 242406 Indeces. Which I wasn't realizing meant that I would wrap back around to 0 when it hit past 65535. Because of this wrapping, I would never fill in information at the very END of Indeces, therefore my IndexBuffer would be incomplete. This caused the program to crash on:
    D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons); //Can be found in Render()
    (Much of this isn't with a reason, this is just what I've seen when trying to figure my problem out).

    When I realized it was wrapping back around, I changed the "unsigned short" to an "unsigned long". This caused my program to crash on the line:
    free(Indices); //Can be found in InitIndexBuffer()

    After thinking my computer was corrupted (I got something like "Block #43 Damaged" popping up in a MessageBox). For no reason, I changed the "unsigned long" back to "unsigned short". And my problem went away. But, back to the Render() crash.

    So, as it stood, my variable was wrapping around, and this wasn't acceptable (either was the crash).

    So, to test it out, I loaded in a different bitmap, one that would only require 8214 Indeces (definitely reachable by an unsigned short, without wrapping back to 0). The result was the return of my "Block #43 Damaged" error.

    So, my only guess here is that I'm not allocating enough space for my IndexBuffer and when I gets too high, it starts writing things to places it shouldn't. But that doesn't explain to me why the free() line is crashing.

    Perhaps if somebody could look over my allocations, check that I didn't miss anything? (I've double and triple-checked and I just can't find anything that could cause this. Hopefully a new set of eyes can.)

    If nothing else, thanks for reading (or scrolling down to the bottom of) this monstrous post.
    Last edited by Epo; 09-11-2005 at 07:47 PM.
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  2. #2
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Code:
    void cTerrain::Draw(void)
    {
    	D3DDevice->SetStreamSource(0, VertexBuffer, 0, sizeof(sVertex));
    	D3DDevice->SetFVF(FVF);
    	D3DDevice->SetIndices(IndexBuffer);
    	D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons);
    }
    However, I'm getting a crash on the DrawIndexedPrimitive() line again.

    I added a safeguard:
    Code:
    for(Z = 0; Z < (NumRows-1); Z = Z + 1)
    {
    	for(X = 0; X < (NumCols-1); X = X + 1)
    	{
    		if((I + 5) >= NumIndices)
    		{
    			free(Indices);
    			Indices = NULL;
    			return false;
    		}
    
    		Indices[ I ]	= A;
    		Indices[I + 1]	= B;
    		Indices[I + 2]	= C;
    		Indices[I + 3]	= C + 1;
    		Indices[I + 4]	= C;
    		Indices[I + 5]	= B;
    
    		A = A + 1;
    		B = B + 1;
    		C = C + 1;
    		I = I + 6;
    	}
    	A = A + 2;
    	B = B + 2;
    	C = C + 2;
    }
    In the blue. A "false" return quits the program. And it doesn't quit. So I know I'm not overwriting any memory I shouldn't. So, I'm back to the problem. Any clues out there as to why that line could bomb like that?
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  3. #3
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    I'm a moron:
    Code:
    NumIndices  = NumPolygons * 3;
    Is what it should be. I added a "- 1" to the end of it cause the mouse in my room told me to. It works now. Not rendering as hoped, but rendering.

    See, sometimes you just gotta talk the problem out to yourself.
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Why not use D3DXCreateTextureFromFile()? and use the IDirect3DTexture9 interface created in the call to access the texture? You are using Windows API which I don't recommend.

    I used to be an "unsigned short". However, I have 242406 Indeces. Which I wasn't realizing meant that I would wrap back around to 0 when it hit past 65535. Because of this wrapping, I would never fill in information at the very END of Indeces, therefore my IndexBuffer would be incomplete. This caused the program to crash on:
    D3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, NumVertices, 0, NumPolygons); //Can be found in Render()
    (Much of this isn't with a reason, this is just what I've seen when trying to figure my problem out).
    Also I'm not sure what "isn't with a reason" means?
    The function DrawIndexedPrimitive is described in the SDK if the w/o reason means you are not sure what's going on in the function.

    Also that sounds like a lot of indices if this is for one object. If this is for your entire scene then kudos to you for sticking it all in one buffer. This is something I'm still trying to sort out myself.

  5. #5
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    I'll just say it right now, sorry for another lengthy post

    The "isn't for a reason" was me jumping to conclusions about what was actually going wrong in my program without actually knowing

    I'll try and explain the program again...

    The Bitmap that I'm loading in isn't a texture for my quad here, it's a representation of heights. If you look below, the first picture represent my "Terrain Map". By this, dark squares represent lower altitudes. So RGB(0, 0, 0) is the lowest point possible, while RGB(255, 255, 255) will be the highest point possible. Therefore, each pixel's position in the Terrain Map represents the X, Z coordinate of the vertex, while the colour represents the Y value.

    With a lot of searching, I came up with:
    Code:
    ...
    	HBITMAP TerrainFile;
    
    	TerrainFile = (HBITMAP)LoadImage(0, FilePath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
    	if(TerrainFile == NULL)
    		return false;
    
    	BITMAP TerrainMap;
    
    	if(!(GetObject(TerrainFile, sizeof(BITMAP), &TerrainMap)))
    	{	
    		DeleteObject(TerrainFile);
    		return false;
    	}
    
    	BITMAPINFO TerrainInfo;
    
    	TerrainInfo.bmiHeader.biBitCount		= TerrainMap.bmBitsPixel;
    	TerrainInfo.bmiHeader.biClrImportant	= 0;
    	TerrainInfo.bmiHeader.biClrUsed			= 0;
    	TerrainInfo.bmiHeader.biCompression		= BI_RGB;
    	TerrainInfo.bmiHeader.biHeight			= TerrainMap.bmHeight;
    	TerrainInfo.bmiHeader.biPlanes			= TerrainMap.bmPlanes;
    	TerrainInfo.bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
    	TerrainInfo.bmiHeader.biSizeImage		= 0;
    	TerrainInfo.bmiHeader.biWidth			= TerrainMap.bmWidth;
    	//TerrainInfo.bmiHeader.biXPelsPerMeter	=;
    	//TerrainInfo.bmiHeader.biYPelsPerMeter	=;
    	TerrainInfo.bmiColors->rgbRed		= NULL;
    	TerrainInfo.bmiColors->rgbGreen		= NULL;
    	TerrainInfo.bmiColors->rgbBlue		= NULL;
    	TerrainInfo.bmiColors->rgbReserved	= NULL;
    
    	unsigned long *Pixels = NULL;
    
    	Pixels = (unsigned long*)malloc(TerrainInfo.bmiHeader.biHeight * TerrainInfo.bmiHeader.biWidth * sizeof(unsigned long));
    	if(Pixels == NULL)
    	{
    		DeleteObject(TerrainFile);
    		return false;
    	}
    ...
    To open a Bitmap file, and load each Pixel's colour into my array. Currently I'm working with a smaller bitmap for the sake of rendering (38 by 38 pixels = 38 by 38 vertices). You can see that "Map" in the second picture.

    Now, the code above for my Index Buffer is working correctly (as far as I can tell) as in wireframe, I'm getting a successful rendering of a grid. Regardless of the Bitmap loaded, the pattern will always be the same for the Index Buffer, which is why I like it so much (it's a slightly edited version of AndyPike's algorithm to match my style) You can see the flatly rendered grid in the third picture. (Perhaps slightly tough to see).

    The code to initialize the vertex buffer is:
    Code:
    ...
    	sVertex *Terrain; //Private Member of my Class
    ...
    	Terrain = (sVertex*)malloc(NumVertices * sizeof(sVertex));
    
    	unsigned long Colour;
    	unsigned long I = 0;
    
    	for(int ZPos = 0; ZPos < NumRows; ZPos = ZPos + 1)
    	{
    		for(int XPos = 0; XPos < NumCols; XPos = XPos + 1)
    		{
    			Colour = Pixels[I];
    			//The X,Z is just based off the Pixel's position on the bitmap
    			Terrain[I].X		= (float)(XPos * 1.0f);
    			Terrain[I].Y		= (float)0.0f; //No Height
    			Terrain[I].Z		= (float)(ZPos * 1.0f);
    			Terrain[(ZPos * NumCols) + XPos].colour	= 0xFFFFFFFF;
    			//Terrain[(ZPos * NumCols) + XPos].colour	= Colour;
    
    			I = I + 1;
    		}
    	}
    
    	unsigned char *Vertices;
    
    	if(FAILED(VertexBuffer->Lock(0, NumVertices * sizeof(sVertex), (void**)&Vertices, 0)))
    	{
    		...
    	}
    	else
    	{
    		memcpy(Vertices, Terrain, NumVertices * sizeof(sVertex));
    		VertexBuffer->Unlock();
    	}
    
    	free(Terrain);
    	Terrain = NULL;
    ...
    So, in the code above, I'm using the colour 0xFFFFFFFF while ignoring the actual extracted Bitmap pixels (I'm not that far in yet).

    My next step was to, instead of using the 0xFFFFFFFF colour, to use the extracted Bitmap colour, by switching to the commented line:
    //Terrain[(ZPos * NumCols) + XPos].colour = Colour;
    Technically, what I should get in the end, is my "Terrain Map" Bitmap displayed on the screen (since the vertices match colours). I want to get this working before I start interpreting heights.

    However, I get what is rendered in my last attached picture. Not the hoped for result. And that's where I am now, trying to find a solution to that.

    Why not use D3DXCreateTextureFromFile()?
    Are you saying I can load my Bitmap in with that (well, I know THAT'S doable), but after that, I can extract individual Pixel information from the texture file? Cause if that's what you're saying, that would be swell, and I'll drop the Windows API like a hot, heavy brick.

    It's just that when I did all my searching, this was the method I found on extracting pixel information from a bitmap.
    Last edited by Epo; 09-12-2005 at 09:47 PM. Reason: Added some code
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Yes.

    I've used heightmaps quite extensively so I completely understand what you are trying to do.

    D3DXCreateTextureFromFile() will create an IDirect3DTexture9 interface pointer for you and return it back to you. Then using that interface you can gain access to IDirect3DSurface9 (or something like that) and then from there you can lock the surface and access it just like you would any other bitmap - either in linear fashion (a little like old 320x200x256 VGA mode) or in 2D using u and v. Your choice.

    Try it and see what you come up with. So far I've not used any color bitmaps for heightmaps in my code. What I do is create a 32-bit color map for the terrain and a 256 color greyscale map for the heights. The heightmaps are stored as RAW files with a proprietary header that holds important information pertinent to the engine using the file. The RAW file is loaded using C's I/O library of functions and the bitmap is loaded using my own scaled-down BMP loader. The API has too much crapola to support when it comes to BMPs and most BMPs, if not all by today's standards, can be loaded with a simple BMP loader. The code for a very simple BMP loader can be found at www.brackeen.com - if the guy's site is still up.

    I would recommend using 256 color greyscales for your heightmaps. It is cool to attempt to store both color and height in the same file, however it creates more problems than it alleviates.

    Just my opinion.


    On a side note I've come acrossed a very cool spheres algorithm which generates some very nice terrains - far better than I've ever achieved with the recursive subdivision method(s). Here is one example with texture and fog. There is normal information for each triangle in the terrain, but I've yet to enable the lighting system.
    Last edited by VirtualAce; 09-13-2005 at 04:54 PM.

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    And here it is in wireframe so you can see more of the underlying structure.

    I do apologize for the complete lack of efficiency displayed here. This is a brute force rendering algorithm.

  8. #8
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Bubba, thanks alot for the point in the right direction. I've been busy at school for a while, so I haven't gotten to work on this too much. I am getting there though. I like the idea of the RAW file format.

    I'll post again when I have something a bit more meaningful. But I just wanted to say thanks.
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  9. #9
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Okay, I've made some progress.

    The task I'm working on now is to create a convertor for any BMP file into RAW format (Since I like drawing in MS Paint and learning something new never hurts). I believe I'm pretty close.

    To do this, I've opened the BMP file in Binary mode, and found that the pixel information starts after the first 54 bytes. After searching this board (and wotsit.org), I realized that it was the BITMAPFILEHEADER and BITMAPINFOHEADER that take up those 54 bytes.

    So, currently I've read in both headers, and then the pixel information.

    Now, the buffer for my pixels is of the type unsigned long. My array is dynamically created, and each element represents one Pixel's colour.

    I've tried approach after approach to extracting the RGB values from my array. A few include:

    Code:
    printf("%d ", (Buffer[I] & 0x00FF0000)); //RED
    printf("%d ", (Buffer[I] & 0x0000FF00)); //GREEN
    printf("%d ", (Buffer[I] & 0x000000FF)); //BLUE
    
    printf("%d ", (Buffer[I] & 0xFFFF0000)); //RED
    printf("%d ", (Buffer[I] & 0xFF00FF00)); //GREEN
    printf("%d ", (Buffer[I] & 0xFF0000FF)); //BLUE
    
    printf("%d ", (Buffer[I] & /*Insert Decimal Counterpart Here*/)); //RED
    printf("%d ", (Buffer[I] & /*Insert Decimal Counterpart Here*/)); //GREEN
    printf("%d ", (Buffer[I] & /*Insert Decimal Counterpart Here*/)); //BLUE
    I've also tried Bitshifting with any appropriate numbers I could think of/read about on these boards.

    Still, nothing is getting me the correct outputs. If anybody could lend some idea, I would really appreciate this.

    Incase you're wondering, my Pixel Reading function is:
    Code:
    unsigned long * CompletePixels(BITMAPINFOHEADER *BitmapInfoHeader, FILE *BinaryIFile)
    {
    	unsigned long *Buffer = (unsigned long *)malloc(BitmapInfoHeader->biSizeImage);
    
    	printf("Requesting:\t%ld Bytes\n", BitmapInfoHeader->biSizeImage);
    	printf("Received:\t%ld Bytes\n", fread(Buffer, 1, BitmapInfoHeader->biSizeImage + 1, BinaryIFile));
    	printf("\nReceiving Image Data: ");
    
    	if(feof(BinaryIFile) == false)
    	{
    		printf("Failed\n");
    		free(Buffer);
    		Buffer = NULL;
    	}
    	else
    	{
    		printf("Succeeded\n");
    		fclose(BinaryIFile);
    		BinaryIFile = NULL;
    	}
    
    	return Buffer;
    }
    Thanks for any comments
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The solution to this is actually simpler than you might think.

    Since an RGB quad is really RGBX in a BMP file you can do this:

    Code:
    struct RGBA
    {
      unsigned char red;
      unsigned char green;
      unsigned char blue;
      unsigned char alpha;
    };
    Now the reason I wrote my own BMP loader is because I thought it was assinine the way MS did it with BitmapInfoHeader and all that crap.

    So I put all of the info into one header called BMP. www.brackeen.com has the full BMP header in case you are interested. Now read from the file into the header - the following code is assuming you have a valid file handle.

    Code:
    BMP MyHeader;
    
    _read(handle,MyHeader,sizeof(BMP));
    
    DWORD dwImageSize=MyHeader.bmWidth*MyHeader.bmHeight*sizeof(DWORD);
    
    RGBA *Image=new RGBA[dwImageSize];
    
    if (Image)
    {
      _read(handle,&Image,dwImageSize);
    } else return;
    
    _close(handle);
    Now to access the red green blues simply do:

    Code:
    unsigned char red=Image[offset].red;
    unsigned char green=Image[offset].green;
    unsigned char blue=Image[offset].blue;
    unsigned char alpha=Image[offset].alpha;

    This eases the pain of doing all the bitmasking. The reading and loading times should be identical since in theory RGBA is exactly the same size as a DWORD - so you are really just breaking the DWORD up into smaller parts by using a structure instead of an unsigned long or DWORD.

    This also makes bi linear interpolation and linear interpolations much easier.

    Note that even if you have a RAW format you can still use the RGBA/RGBX structure to load the data. The only diff between the two is that in RGBX the fourth component is discarded and in RGBA it is used as alpha. In your case you could store the actual height data in the alpha channel since the heights in a greyscale image will always fall in range 0 to 255 or 00h to FFh.

    So your structure might look like this if you want to store all info in the same file.

    Code:
    struct RGBH
    {
      unsigned char red;
      unsigned char green;
      unsigned char blue;
      unsigned char height;
    };
    Now you can use PaintShop or PhotoShop or DirectX Texture Tool to create the heightmap, greyscale it, and use it as the alpha channel for the picture.

    www.flipcode.com has a very good tutorial on how to blend terrain types using alpha values - you may want to do a search for it there.

    Hope this helps.

  11. #11
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Bubba, you've got this genius way of finding a one-step solution to any problem. I went with your RGBH struct approach (which makes sense to be now, but there's no way I would've thought of it myself), and it works alot better so far, however, I'm having a slight problem...

    (I'll post the code/output and outline the problems below, feel free to skip the code for now)

    Code:
    #define WIN_32_LEAN_AND_MEAN
    
    #include <Stdlib.h>
    #include <Stdio.h>
    #include <IO.h>
    #include <FCNTL.h>
    
    struct CUSTOMBITMAPHEADER
    {
    	unsigned short	Type;
    	unsigned long	Size;
    	unsigned short	Reserved1;
    	unsigned short	Reserved2;
    	unsigned long	OffBits;
    	unsigned long	RemainingSize;
    	unsigned long	Width;
    	unsigned long	Height;
    	unsigned short	Planes;
    	unsigned short	BitCount;
    	unsigned long	Compression;
    	unsigned long	SizeImage;
    	unsigned long	XPelsPerMeter;
    	unsigned long	YPelsPerMeter;
    	unsigned long	ClrUsed;
    	unsigned long	ClrImportant;
    };
    
    struct RGBH
    {
    	unsigned char R;
    	unsigned char G;
    	unsigned char B;
    	unsigned char H;
    };
    
    void	CompleteHeader(CUSTOMBITMAPHEADER *BitmapHeader, int FileHandle);
    RGBH *	CompletePixels(CUSTOMBITMAPHEADER *BitmapHeader, int FileHandle);
    void	DisplayHeader(CUSTOMBITMAPHEADER *BitmapHeader, FILE *Outstream);
    void	DisplayPixels(CUSTOMBITMAPHEADER *BitmapHeader, RGBH *Buffer, FILE *Outstream);
    
    int main(void)
    {
    	CUSTOMBITMAPHEADER BitmapHeader;
    
    	char	iPath[250];
    	int	FileHandle	= 0;
    	RGBH	*Buffer		= NULL;
    
    	printf("Enter Input Path: ");
    	fscanf(stdin, "%s", iPath);
    	printf("\n");
    
    	printf("Opening File:\t");
    	FileHandle = _open(iPath, _O_TEXT|_O_RDONLY);
    	
    	if(FileHandle != 0)
    	{
    		printf("Succeeded\n");
    		
    		CompleteHeader(&BitmapHeader, FileHandle);
    		Buffer = CompletePixels(&BitmapHeader, FileHandle);
    
    		if(Buffer != NULL)
    		{
    			DisplayHeader(&BitmapHeader, stdout);
    			DisplayPixels(&BitmapHeader, Buffer, stdout);
    		}
    	}
    	else
    	{
    		printf("Failed\n");
    	}
    
    	if(Buffer != NULL)
    	{
    		free(Buffer);
    		Buffer = NULL;
    	}
    
    	if(FileHandle != 0)
    		_close(FileHandle);
    
    	printf("\n\n");
    	return 0;
    }
    
    void CompleteHeader(CUSTOMBITMAPHEADER *BitmapHeader, int FileHandle)
    {
    	_read(FileHandle, &(BitmapHeader->Type),		sizeof(BitmapHeader->Type));
    	_read(FileHandle, &(BitmapHeader->Size),		sizeof(BitmapHeader->Size));
    	_read(FileHandle, &(BitmapHeader->Reserved1),		sizeof(BitmapHeader->Reserved1));
    	_read(FileHandle, &(BitmapHeader->Reserved2),		sizeof(BitmapHeader->Reserved2));
    	_read(FileHandle, &(BitmapHeader->OffBits),		sizeof(BitmapHeader->OffBits));
    	_read(FileHandle, &(BitmapHeader->RemainingSize),	sizeof(BitmapHeader->Size));
    	_read(FileHandle, &(BitmapHeader->Width),		sizeof(BitmapHeader->Width));
    	_read(FileHandle, &(BitmapHeader->Height),		sizeof(BitmapHeader->Height));
    	_read(FileHandle, &(BitmapHeader->Planes),		sizeof(BitmapHeader->Planes));
    	_read(FileHandle, &(BitmapHeader->BitCount),		sizeof(BitmapHeader->BitCount));
    	_read(FileHandle, &(BitmapHeader->Compression),		sizeof(BitmapHeader->Compression));
    	_read(FileHandle, &(BitmapHeader->SizeImage),		sizeof(BitmapHeader->SizeImage));
    	_read(FileHandle, &(BitmapHeader->XPelsPerMeter),	sizeof(BitmapHeader->XPelsPerMeter));
    	_read(FileHandle, &(BitmapHeader->YPelsPerMeter),	sizeof(BitmapHeader->YPelsPerMeter));
    	_read(FileHandle, &(BitmapHeader->ClrUsed),		sizeof(BitmapHeader->ClrUsed));
    	_read(FileHandle, &(BitmapHeader->ClrImportant),	sizeof(BitmapHeader->ClrImportant));
    }
    
    RGBH * CompletePixels(CUSTOMBITMAPHEADER *BitmapHeader, int FileHandle)
    {
    	RGBH *Buffer = (RGBH *)malloc(BitmapHeader->SizeImage);
    
    	printf("Requesting:\t%ld Bytes\n", BitmapHeader->SizeImage);
    	printf("Received:\t%ld Bytes\n", _read(FileHandle, Buffer, BitmapHeader->SizeImage));
    	printf("\nReceiving Image Data: ");
    
    	if(_eof(FileHandle) == false)
    	{
    		printf("Failed\n");
    		free(Buffer);
    		Buffer = NULL;
    	}
    	else
    	{
    		printf("Succeeded\n");
    		_close(FileHandle);
    	}
    
    	return Buffer;
    }
    
    void DisplayHeader(CUSTOMBITMAPHEADER *BitmapHeader, FILE *Outstream)
    {
    	fprintf(Outstream, "\n\n");
    	fprintf(Outstream, "Type:\t\t%hd\n", BitmapHeader->Type);
    	fprintf(Outstream, "Size:\t\t%ld\n", BitmapHeader->Size);
    	fprintf(Outstream, "Reserved1:\t%hd\n", BitmapHeader->Reserved1);
    	fprintf(Outstream, "Reserved2:\t%hd\n", BitmapHeader->Reserved2);
    	fprintf(Outstream, "OffBits:\t%ld\n", BitmapHeader->OffBits);
    	fprintf(Outstream, "Size:\t\t%ld\n", BitmapHeader->RemainingSize);
    	fprintf(Outstream, "Width:\t\t%ld\n", BitmapHeader->Width);
    	fprintf(Outstream, "Height:\t\t%ld\n", BitmapHeader->Height);
    	fprintf(Outstream, "Planes:\t\t%hd\n", BitmapHeader->Planes);
    	fprintf(Outstream, "BitCount:\t%hd\n", BitmapHeader->BitCount);
    	fprintf(Outstream, "Compression:\t%ld\n", BitmapHeader->Compression);
    	fprintf(Outstream, "SizeImage:\t%ld\n", BitmapHeader->SizeImage);
    	fprintf(Outstream, "XPelsPerMeter:\t%ld\n", BitmapHeader->XPelsPerMeter);
    	fprintf(Outstream, "YPelsPerMeter:\t%ld\n", BitmapHeader->YPelsPerMeter);
    	fprintf(Outstream, "ClrUsed:\t%ld\n", BitmapHeader->ClrUsed);
    	fprintf(Outstream, "ClrImportant:\t%ld\n", BitmapHeader->ClrImportant);
    	fprintf(Outstream, "\n\n");
    }
    
    void DisplayPixels(CUSTOMBITMAPHEADER *BitmapHeader, RGBH *Buffer, FILE *Outstream)
    {
    	fprintf(Outstream, "Pixel Information:\n");
    	int I = 0;
    	for(unsigned int Y = 0; Y < BitmapHeader->Height; Y++)
    	{
    		for(unsigned int X = 0; X < BitmapHeader->Width; X++)
    		{
    			printf("%ld %ld %ld %ld | ", Buffer[I].R, Buffer[I].G, Buffer[I].B, Buffer[I].H);
    			I++;
    		}
    		printf("\n");
    	}
    }
    With output:
    Enter Input Path: c:\2.bmp

    Opening File: Succeeded
    Requesting: 16 Bytes
    Received: 16 Bytes

    Receiving Image Data: Succeeded


    Type: 19778
    Size: 70
    Reserved1: 0
    Reserved2: 0
    OffBits: 54
    Size: 40
    Width: 2
    Height: 2
    Planes: 1
    BitCount: 24
    Compression: 0
    SizeImage: 16
    XPelsPerMeter: 0
    YPelsPerMeter: 0
    ClrUsed: 0
    ClrImportant: 0


    Pixel Information:
    192 192 192 192 | 192 192 0 0 |
    192 192 192 192 | 192 192 0 0 |


    Press any key to continue
    Note: I'm using a 2x2 Bitmap with all RGB(192, 192, 192) pixels.

    Firstly, I tried to use a single _read():
    _read(FileHandle, &BitmapHeader, sizeof(BitmapHeader));
    However, that gave me some pretty crazy results when it came to displaying the header information. It seems it must be read in variable by variable. Have you gotten your Bitmap Loader working with just _read() line?

    I found that _read() and fread() are both accomplishing the same thing, under Binary or just standard ASCII mode.

    Using the RGBH struct however HAS significantly improved my output.

    This may or may not be a good time to mention I'm using a 24-Bit BMP, could some of the problems be arising from this do you think?
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  12. #12
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Try this:

    Code:
    #pragma pack(1)
    struct RGBH
    {
      unsigned char red;
      unsigned char green;
      unsigned char blue;
      unsigned char height;
    }
    
    struct BMP
    {
       ....
       ....
    };
    
    #pragma
    I think your byte alignment is off which is causing the read to fail. The read just reads bytes - fread is not all that much different - in fact none of the approaches are that much different. Whether you choose to use C I/O or C++ I/O (ala streams) - either way you are basically doing the same thing.

    If the byte alignment is off it will cause portions of the DWORDs to be stored in the wrong places - essentially the data is all jumbled up.

    Try the pragma pack and see what you get.

    If that doesn't work I'll post my loader here.

  13. #13
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    Hey Bubba

    I threw the two pragmas in around my structure definitions:
    Code:
    #pragma pack(1)
    
    struct CUSTOMBITMAPHEADER
    {
    	unsigned short	Type;
    	unsigned long	Size;
    	unsigned short	Reserved1;
    	unsigned short	Reserved2;
    	unsigned long	OffBits;
    	unsigned long	RemainingSize;
    	unsigned long	Width;
    	unsigned long	Height;
    	unsigned short	Planes;
    	unsigned short	BitCount;
    	unsigned long	Compression;
    	unsigned long	SizeImage;
    	unsigned long	XPelsPerMeter;
    	unsigned long	YPelsPerMeter;
    	unsigned long	ClrUsed;
    	unsigned long	ClrImportant;
    };
    
    struct RGBH
    {
    	unsigned char R;
    	unsigned char G;
    	unsigned char B;
    	unsigned char H;
    };
    
    #pragma
    But I am still getting the same output. Just out of curiosity, what were the pragmas supposed to do? Specify the correct size of a byte? Or similar idea? (I'm shootin' in the dark here)

    I did however, come across something that may or may not make sense...

    I opened up the Bitmap file with Textpad (image attached), and lo and behold, it is displaying it in the same way as my program. The "C0"s and "00"s match to my display.

    Perhaps this IS actually being read in correctly? And I'm just parsing the info incorrectly?

    I was thinking that it may be of the form (for, let's say a 2x2 Bitmap, R = Red, G = Green, B = Blue, A = Alpha):
    R G B R G B A A R G B R G B A A
    Where the Alpha's are stored at the end of each row...

    However, when I opened up a larger Bitmap (16x16) I only got "C0"s all the way through the whole file (With Textpad, once the pixel information section starts), and with my program, I get:
    Enter Input Path: c:\16.bmp

    Opening File: Succeeded
    Requesting: 768 Bytes
    Received: 768 Bytes

    Receiving Image Data: Succeeded


    Type: 19778
    Size: 822
    Reserved1: 0
    Reserved2: 0
    OffBits: 54
    Size: 40
    Width: 16
    Height: 16
    Planes: 1
    BitCount: 24
    Compression: 0
    SizeImage: 768
    XPelsPerMeter: 0
    YPelsPerMeter: 0
    ClrUsed: 0
    ClrImportant: 0


    Pixel Information:
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192
    192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192
    | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 192 192 192 | 192 19
    2 192 192 | 192 192 192 192 | 192 192 192 192 |
    253 253 253 253 | 0 0 0 0 | 49 3 0 0 | 65 0 0 0 | 64 29 67 0 | 104 73 50 0 | 200
    77 66 0 | 121 0 0 0 | 18 0 0 0 | 2 0 0 0 | 40 0 0 0 | 253 253 253 253 | 95 77 8
    3 68 | 69 86 95 66 | 76 68 95 69 | 78 86 95 61 |
    49 0 253 253 | 253 253 0 0 | 65 0 0 0 | 161 1 0 0 | 224 30 67 0 | 0 29 67 0 | 20
    0 77 66 0 | 121 0 0 0 | 102 1 0 0 | 2 0 0 0 | 39 0 0 0 | 253 253 253 253 | 95 65
    67 80 | 95 80 65 84 | 72 61 67 58 | 92 80 114 111 |
    103 114 97 109 | 32 70 105 108 | 101 115 92 77 | 105 99 114 111 | 115 111 102 11
    6 | 32 68 105 114 | 101 99 116 88 | 32 57 46 48 | 32 83 68 75 | 32 40 79 99 | 11
    6 111 98 101 | 114 32 50 48 | 48 52 41 92 | 85 116 105 108 | 105 116 105 101 | 1
    15 59 67 58 |
    92 80 114 111 | 103 114 97 109 | 32 70 105 108 | 101 115 92 77 | 105 99 114 111
    | 115 111 102 116 | 32 86 105 115 | 117 97 108 32 | 83 116 117 100 | 105 111 92
    67 | 111 109 109 111 | 110 92 77 83 | 68 101 118 57 | 56 92 66 105 | 110 59 67 5
    8 | 92 80 114 111 |
    As you can see, it just falls apart towards the end there.

    I'm going to keep on trying to figure this out, but right now I just need some sleep. Thanks for the ideas so far though, if you get anymore, I'm always happy to hear them. If I figure anything out, I'll post an update.
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It should be noted that BMP files are 0 padded to the nearest 4 byte boundary. This means each scanline of pixels is padded and that if your bitmap width is not a factor of 4, your image won't be read into the array correctly and thus it won't be displayed correctly.

    To account for this I use a simple modulo operation - or I just ensure when I make the bmp that it's width is a factor of 4.

    I suggest attempting to display the bmp on your screen. If it looks garbled, then this is your problem.

  15. #15
    Registered User
    Join Date
    Jun 2003
    Posts
    361
    It's all making sense now

    You're right about the padding, however, I don't think there's an Alpha channel. I've been using a 2x2 bitmap until now:
    192 192 192 192 | 192 192 0 0 |
    192 192 192 192 | 192 192 0 0 |
    From above.

    Which is making sense for the padding:
    R G B R | G B PAD PAD |
    R G B R | G B PAD PAD |
    Where the PADs are the 0s, and you get the lovely Width multiple of 4 thing.

    I switched to a 4x4 bitmap, with R = 100, G = 150, and B = 200, and got the output:
    Opening File: Succeeded
    File Status: Valid
    Creating Pixels: Succeeded

    | 200 150 100 | 200 150 100 | 200 150 100 | 200 150 100
    | 200 150 100 | 200 150 100 | 200 150 100 | 200 150 100
    | 200 150 100 | 200 150 100 | 200 150 100 | 200 150 100
    | 200 150 100 | 200 150 100 | 200 150 100 | 200 150 100
    Press any key to continue
    Integer then Hex printed out

    And the larger images aren't going haywire near the end.

    Here is the sourcecode for my current loader:
    Code:
    #include <Stdlib.h>
    #include <Stdio.h>
    
    #define INPUT_PATH "C:\\4.bmp"
    
    struct CUSTOMBITMAPHEADER
    {
    	unsigned short	Type;
    	unsigned long	Size;
    	unsigned short	Reserved1;
    	unsigned short	Reserved2;
    	unsigned long	OffBits;
    	unsigned long	RemainingSize;
    	unsigned long	Width;
    	unsigned long	Height;
    	unsigned short	Planes;
    	unsigned short	BitCount;
    	unsigned long	Compression;
    	unsigned long	SizeImage;
    	unsigned long	XPelsPerMeter;
    	unsigned long	YPelsPerMeter;
    	unsigned long	ClrUsed;
    	unsigned long	ClrImportant;
    };
    
    void CompleteHeader(CUSTOMBITMAPHEADER *BitmapHeader, FILE *BinaryIFile);
    
    int main(void)
    {
    	CUSTOMBITMAPHEADER CustomBitmapHeader;
    	unsigned char *Pixels = NULL;
    
    	FILE *InputFile = NULL;
    	unsigned long	FileSize = 0;
    
    	printf("Opening File: ");
    	InputFile = fopen(INPUT_PATH, "rb");
    	if(InputFile == NULL)
    	{
    		printf("Failed\n");
    	}
    	else
    	{
    		printf("Succeeded\n");
    
    		fseek(InputFile, 0, SEEK_END);
    		FileSize = ftell(InputFile);
    		rewind(InputFile);
    
    		printf("File Status: ");
    		if(FileSize < sizeof(CUSTOMBITMAPHEADER))
    		{
    			printf("Invalid\n");
    		}
    		else
    		{
    			printf("Valid\n");
    			
    			CompleteHeader(&CustomBitmapHeader, InputFile);
    
    			printf("Creating Pixels: ");
    			Pixels = (unsigned char *)malloc(CustomBitmapHeader.SizeImage);
    			if(Pixels == NULL)
    			{
    				printf("Failed\n");
    			}
    			else
    			{
    				printf("Succeeded\n");
    
    				fread(&(Pixels[0]), sizeof(Pixels[0]), 1, InputFile);
    				for(int I = 0; feof(InputFile) == false; I++)
    				{
    					if(I % (CustomBitmapHeader.Width * 3) == 0)
    						printf("\n");
    
    					if(I % 3 == 0)
    						printf("| ");
    
    					printf("%d ", Pixels[I]);
    					fread(&(Pixels[I+1]), sizeof(Pixels[I+1]), 1, InputFile);
    				}
    				printf("\n");
    			}
    		}
    	}
    
    	if(Pixels != NULL)
    	{
    		free(Pixels);
    		Pixels = NULL;
    	}
    
    	if(InputFile != NULL)
    	{
    		fclose(InputFile);
    		InputFile = NULL;
    	}
    
    	return 0;
    }
    
    void CompleteHeader(CUSTOMBITMAPHEADER *BitmapHeader, FILE *BinaryIFile)
    {
    	fread(&(BitmapHeader->Type), sizeof(BitmapHeader->Type), 1, BinaryIFile);
    	fread(&(BitmapHeader->Size), sizeof(BitmapHeader->Size), 1, BinaryIFile);
    	fread(&(BitmapHeader->Reserved1), sizeof(BitmapHeader->Reserved1), 1, BinaryIFile);
    	fread(&(BitmapHeader->Reserved2), sizeof(BitmapHeader->Reserved2), 1, BinaryIFile);
    	fread(&(BitmapHeader->OffBits), sizeof(BitmapHeader->OffBits), 1, BinaryIFile);
    	fread(&(BitmapHeader->RemainingSize), sizeof(BitmapHeader->Size), 1, BinaryIFile);
    	fread(&(BitmapHeader->Width), sizeof(BitmapHeader->Width), 1, BinaryIFile);
    	fread(&(BitmapHeader->Height), sizeof(BitmapHeader->Height), 1, BinaryIFile);
    	fread(&(BitmapHeader->Planes), sizeof(BitmapHeader->Planes), 1, BinaryIFile);
    	fread(&(BitmapHeader->BitCount), sizeof(BitmapHeader->BitCount), 1, BinaryIFile);
    	fread(&(BitmapHeader->Compression), sizeof(BitmapHeader->Compression), 1, BinaryIFile);
    	fread(&(BitmapHeader->SizeImage), sizeof(BitmapHeader->SizeImage), 1, BinaryIFile);
    	fread(&(BitmapHeader->XPelsPerMeter), sizeof(BitmapHeader->XPelsPerMeter), 1, BinaryIFile);
    	fread(&(BitmapHeader->YPelsPerMeter), sizeof(BitmapHeader->YPelsPerMeter), 1, BinaryIFile);
    	fread(&(BitmapHeader->ClrUsed), sizeof(BitmapHeader->ClrUsed), 1, BinaryIFile);
    	fread(&(BitmapHeader->ClrImportant), sizeof(BitmapHeader->ClrImportant), 1, BinaryIFile);
    }
    Which I believe is working correctly now, and I will move to implementing it in my Terrain Program and hopefully get some nice Terrain's in there.

    I would guess that my 24-Bit BMP is the reason for not having an Alpha Channel? 8 Red, 8 Green, 8 Blue?
    Last edited by Epo; 09-23-2005 at 09:03 PM.
    Pentium 4 - 2.0GHz, 512MB RAM
    NVIDIA GeForce4 MX 440
    WinXP
    Visual Studio .Net 2003
    DX9 October 2004 Update (R.I.P. VC++ 6.0 Compatability)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 09-23-2008, 03:32 AM
  2. pointer comparison failing
    By Bleech in forum C Programming
    Replies: 4
    Last Post: 08-11-2007, 06:33 PM
  3. CreateDevice failing
    By MadCow257 in forum Game Programming
    Replies: 6
    Last Post: 03-14-2006, 09:03 PM
  4. initializes all components of failing to false
    By romeoz in forum C++ Programming
    Replies: 21
    Last Post: 08-01-2003, 09:30 PM
  5. DX9 and Dev-C++
    By Ashes999 in forum Windows Programming
    Replies: 5
    Last Post: 06-10-2003, 12:19 AM