Advertisement

Texture loading and tutorials

Started by August 23, 2002 09:58 PM
2 comments, last by CaptainJester 22 years, 6 months ago
WARNING semi-large post follows. As an exercise for myself, I wrote a class to load a .bmp image for use as a texture. Once I had it working, I went to NeHe''s tutorials to use it to load the textures. The first one I tried it on was number 10. It work great on this one. I then tried it on number 23 and started getting some weird error, not related to my code, but only happened when my code was in there. I then tried it on the first texture tutorial, number 6. The same weird error occured. Not a compilation error, but a runtime error. Here''s the error:

Debug error!

Program:.....lesson6.exe

DAMGE: After Normal block (#23) at 0x007252c8

(Press retry to debug the application.
When I try to debug, it just brings me into an assembly listing that is not any of my code. The funny thing is, when I try it in an OpenGL program of my own to load 3 textures, it works fine. It seems to be hit and miss. Anyone have any ideas? Here is my bitmap.h file:
  
#ifndef _BITMAP_H
#define _BITMAP_H
//File: Bitmap.h

//Written by:     Mark Bernard

//on GameDev.net: Captain Jester

//e-mail: mark.bernard@rogers.com

//Please feel free to use and abuse this code as much

//as you like.  But, please give me some credit for 

//starting you off on the right track.

//

//The file Bitmap.cpp goes along with this file

//


#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
#include <windows.h>

const WORD BITMAP_MAGIC_NUMBER=19778;

class Bitmap {
public:
    //variables

    RGBQUAD *colours;
    BYTE *pixelData;
    bool loaded;
    LONG width,height;
    WORD bpp;
    string error;
    //methods

    Bitmap(void);
    Bitmap(char *);
    ~Bitmap();
    bool loadBMP(char *);
private:
    //variables

    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    //methods

    void reset(void);
};

#endif //_BITMAP_H

  
And my bitmap.cpp
  
//File: Bitmap.cpp

//Written by:     Mark Bernard

//on GameDev.net: Captain Jester

//e-mail: mark.bernard@rogers.com

//Please feel free to use and abuse this code as much

//as you like.  But, please give me some credit for

//starting you off on the right track.

//

//The file Bitmap.h goes along with this file

//

#include "Bitmap.h"

//basic constructor

Bitmap::Bitmap(){
    reset();
}

//constructor loads the bitmap when it is created

Bitmap::Bitmap(char *file){
    reset();
    loadBMP(file);
}

//destructor

Bitmap::~Bitmap(){
    if(colours!=0) {
        delete[] colours;
    }
    if(pixelData!=0) {
        delete[] pixelData;
    }
}

//load a bitmap from a file and represent it correctly

//in memory

bool Bitmap::loadBMP(char *file) {
    FILE *in;                  //file stream for reading

    DWORD size;                //size of the file

    DWORD diff;                //size of the image data

    BYTE *tempPixelData;       //temp storage for image data

    LONG byteWidth;            //the width in bytes of the image

    LONG padWidth;             //the width in bytes of the added image

    int offset;                //used for parsing the image data

    int numColours;            //total available colours


    //bitmap is not loaded yet

    loaded=false;
    //make sure memory is not lost

    if(colours!=0) {
        delete[] colours;
    }
    if(pixelData!=0) {
        delete[] pixelData;
    }

    //open the file for reading in binary mode

    in=fopen(file,"rb");

    //if the file does not exist return in error

    if(in==NULL) {
        error="File not found";
        fclose(in);
        return false;
    }

    //read in the entire BITMAPFILEHEADER

    fread(&bmfh,sizeof(BITMAPFILEHEADER),1,in);

    //check for the magic number that says this is a bitmap

    if(bmfh.bfType!=BITMAP_MAGIC_NUMBER) {
        error="File is not in DIB format";
        fclose(in);
        return false;
    }

    //read in the entire BITMAPINFOHEADER

    fread(&bmih,sizeof(BITMAPINFOHEADER),1,in);

    //save the width, height and bits per pixel for external use

    width=bmih.biWidth;
    height=bmih.biHeight;
    bpp=bmih.biBitCount;

    //calculate the size of the image data with padding

    size=bmfh.bfSize-bmfh.bfOffBits;

    //calculate the number of available colours

    numColours=1<<bmih.biBitCount;

    //if the bitmap is not 8 bits per pixel or more

    //return in error

    if(bpp<8) {
        error="File is not 8 or 24 bits per pixel";
        fclose(in);
        return false;
    }

    //load the palette for 8 bits per pixel

    if(bpp==8) {
    	colours=new RGBQUAD[numColours];
    	fread(colours,sizeof(RGBQUAD),numColours,in);
    }

    //set up the temporary buffer for the image data

    tempPixelData=new BYTE[size];

    //exit if there is not enough memory

    if(tempPixelData==NULL) {
        error="Not enough memory to allocate a temporary buffer";
        fclose(in);
        return false;
    }

    //read in the entire image

    fread(tempPixelData,sizeof(BYTE),size,in);

    //close the file now that we have all the info

    fclose(in);

    //calculate the witdh of the final image in bytes

    byteWidth=padWidth=(LONG)((float)width*(float)bpp/8.0);

    //adjust the width for padding as necessary

    while(padWidth%4!=0) {
        padWidth++;
    }

    //calculate the actual size of the image

    diff=height*byteWidth;

    //allocate the buffer for the final image data

    pixelData=new BYTE[diff];

    //exit if there is not enough memory

    if(pixelData==NULL) {
        error="Not enough memory to allocate an image buffer";
        delete[] tempPixelData;
        fclose(in);
        return false;
    }

    //image parser for a reversed image

    if(height>0) {
        int j=0;
        //set the offset equal to the padding size

        offset=padWidth-byteWidth;
        //count backwards so you start at the front of the image

        for(int i=size-1;i>=0;i--) {
            //jump over the padding at the start of a new line

            if((i+1)%padWidth==0) {
                i-=offset;
            }
            //transfer the data

            *(pixelData+j)=*(tempPixelData+i);
            //counter to count forward in the final buffer

            j++;
        }
    }

    //image parser for a forward image

    else {
        //get the absolute value of height

        height=height*-1;
        //offset is used to count lines

        offset=0;
        do {
            //copy one line and ignore the padding

            memcpy((pixelData+(offset*byteWidth)),(tempPixelData+(offset*padWidth)),byteWidth);
            //next line

            offset++;
        } while(offset<height);
    }

    //clean up memory

    delete[] tempPixelData;

    //bitmap is now loaded

    loaded=true;
    error="Bitmap loaded";

    //return success

    return true;
}

//function to set the inital values

void Bitmap::reset(void) {
    loaded=false;
    colours=0;
    pixelData=0;
    error="";
}
  
And my changes for lesson6:
  
#include "Bitmap.h"
  .
  .
  .
int LoadGLTextures()									// Load Bitmaps And Convert To Textures

{
	int Status=FALSE;									// Status Indicator


	Bitmap image;					// Create Storage Space For The Texture


	// Load The Bitmap, Check For Errors, If Bitmap''s Not Found Quit

	if (image.loadBMP("Data\\NeHe.bmp"))
	{
		Status=TRUE;									// Set The Status To TRUE


		glGenTextures(1, &texture[0]);					// Create The Texture


		// Typical Texture Generation Using Data From The Bitmap

		glBindTexture(GL_TEXTURE_2D, texture[0]);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, image.pixelData);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	}

	return Status;										// Return The Status

}

  
And here is lesson10 for comparison.
  
#include "Bitmap.h"
  .
  .
  .
int LoadGLTextures()                                    // Load Bitmaps And Convert To Textures

{
        int Status=FALSE;                               // Status Indicator


		Bitmap image;

        // Load The Bitmap, Check For Errors, If Bitmap''s Not Found Quit

        if (image.loadBMP("Data/Mud.bmp"))
        {
                Status=TRUE;                            // Set The Status To TRUE


                glGenTextures(3, &texture[0]);          // Create Three Textures


				// Create Nearest Filtered Texture

				glBindTexture(GL_TEXTURE_2D, texture[0]);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
				glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, image.pixelData);

                // Create Linear Filtered Texture

                glBindTexture(GL_TEXTURE_2D, texture[1]);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
                glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width, image.height, 0, GL_RGB, GL_UNSIGNED_BYTE, image.pixelData);

				// Create MipMapped Texture

				glBindTexture(GL_TEXTURE_2D, texture[2]);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
				gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image.width, image.height, GL_RGB, GL_UNSIGNED_BYTE, image.pixelData);
        }

        return Status;                                  // Return The Status

}
  
Maybe it is something simple that I overlooked. Anyway thanks for looking. --- Make it work. Make it fast. "I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
I didn''t look, but I get this message when I try to delete something that has already been deleted, try to take all of the deletes out of your code and see if that works, then slowely replace them until you find the one causing your error...

It might also be a good idea to reboot once in a while, since this process will be memory leak city :-P
~~~~~Screaming Statue Software. | OpenGL FontLibWhy does Data talk to the computer? Surely he's Wi-Fi enabled... - phaseburn
Advertisement
All the deletes are carefully checked before performed, I do not see any that could be deleting anything that was already deleted.

The first rule is to find a pattern. There is ALWAYS a pattern. I would look at the bit depth of the images involved first.
Thanks guys. I never thought to look into bitmap formats. I swapped lesson 6 and lesson 10 bitmaps and now lesson 10 crapped out and lesson 6 worked.

I knew my loader wasn''t complete, but I thought the NeHe ones were basic bitmaps. I''ll have to check them out and fix my loader.


Thanks again.

---
Make it work.
Make it fast.

"I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]

This topic is closed to new replies.

Advertisement