Advertisement

Loading a Compressed TGA file

Started by September 25, 2002 09:01 PM
3 comments, last by Nukem 22 years, 5 months ago
I read the NeHe tutorial on reading tga files(compressed and uncompressed) I changed the code a lil since I also have my class reading a BMP. It reads the BMP and uncompressed tga files fine but everytime I goto read a compressed tga my program gives me the same error, "Error reading pixel". Ive gone over the code countless times I have no idea whats wrong. Can someone please help me? Thanks, Nuke P.S: The error is in the LoadCompressed I commented out the line that gives me the error
  
class TEXTURE
{
  private:

  typedef struct
  {
    GLubyte Header[6]; //holds the first 6 useful bytes of the file

    GLuint bytesPerPixel; //number of BYTES Per Pixel (3 or 4)

    GLuint imagesize; //amount of memory needed to hold the image

    GLuint temp;
    GLuint type; //the type of image, GL_RGB or GL_RGBA

    GLuint h; //height of image

    GLuint w; //width of image

    GLuint bpp; //number of BITS Per Pixel (24, or 32)

  } TGA;

  TGA tga; //used to store file info


  bool LoadUncompressedTGA(FILE* file)
  {
    if(fread(tga.Header, sizeof(tga.Header), 1, file) == 0)
    {
      fprintf(stderr, "Error Opening UnCompressed TGA File\n");
      return false;
    }

    x = tga.Header[1] * 256 + tga.Header[0];
    y = tga.Header[3] * 256 + tga.Header[2];
    bpp = tga.Header[4];
    tga.w = x;
    tga.h = y;
    tga.bpp = bpp;

    if((x <= 0) || (y <= 0) || ((bpp != 24) && (bpp != 32)))
    {
      fprintf(stderr, "Error x, y, and/or, bpp has in invalid value\n");
      return false;
    }

    if(bpp == 24)
    {
      type = GL_RGB;
    }else{
      type = GL_RGBA;
    }

    tga.bytesPerPixel = (tga.bpp / 8);
    tga.imagesize = (tga.bytesPerPixel * tga.w * tga.h);

    //data = (GLubyte*)malloc(tga.imagesize);

    data = (char*)malloc(tga.imagesize);

    if(data == 0)
    {
      fprintf(stderr, "Error in memory!");
      return false;
    }

    if(fread(data, 1, tga.imagesize, file) != tga.imagesize)
    {
      fprintf(stderr, "Image not the right size\n", file);
      return false;
    }

    return true;
  }

  bool LoadCompressedTGA(FILE* file)
  {
    if(fread(tga.Header, sizeof(tga.Header), 1, file) == 0)
    {
      fprintf(stderr, "Error Opening UnCompressed TGA File\n");
      return false;
    }

    x = tga.Header[1] * 256 + tga.Header[0];
    y = tga.Header[3] * 256 + tga.Header[2];
    bpp = tga.Header[4];
    tga.w = x;
    tga.h = y;
    tga.bpp = bpp;

    if((x <= 0) || (y <= 0) || ((bpp != 24) && (bpp != 32)))
    {
      fprintf(stderr, "Error x, y, and/or, bpp has in invalid value\n");
      return false;
    }

    if(bpp == 24)
    {
      type = GL_RGB;
    }else{
      type = GL_RGBA;
    }

    tga.bytesPerPixel = (tga.bpp / 8);
    tga.imagesize = (tga.bytesPerPixel * tga.w * tga.h);

    //data = (GLubyte*)malloc(tga.imagesize);

    data = (char*)malloc(tga.imagesize);

    if(data == 0)
    {
      fprintf(stderr, "Error in memory!\n");
      return false;
    }

    GLuint pixelcount = tga.h * tga.w; //number of pixels in the image

    GLuint currentpixel = 0; //current pixel we are reading data from

    GLuint currentbyte = 0; //current byte we are writing into imagedata


    //try char ! GLubyte

    GLubyte* colorbuffer = (GLubyte*)malloc(tga.bytesPerPixel); //storage for one pixel


    do
    {
      GLubyte chunkheader = 0; //var to store the value of the id chunk


      if(fread(&chunkheader, sizeof(GLubyte), 1, file) == 0) //try to read the chunks header

      {
        fprintf(stderr, "Error reading chunks header!\n");
        return false;
      }

      if(chunkheader < 128) //if the chunk is a RAW chunk

      {
        chunkheader++; //add 1 to the value to get the total number of raw pixels


        //start pixel reading loop

        for(short counter = 0; counter < chunkheader; counter++)
        {
          //try to read 1 pixel

          if(fread(colorbuffer, 1, tga.bytesPerPixel, file) != tga.bytesPerPixel)
          {
            fprintf(stderr, "Error reading pixel 1\n"); //the error is here

            return false;
          }

          data[currentbyte] = colorbuffer[2]; //write the 'R' byte

          data[currentbyte + 1] = colorbuffer[1]; //write the 'G' byte

          data[currentbyte + 2] = colorbuffer[0]; //write the 'B' byte


          //if its a 32bpp image

          if(tga.bytesPerPixel == 4)
          {
            data[currentbyte + 3] = colorbuffer[3]; //write the 'A' byte

          }

          currentbyte += tga.bytesPerPixel; //increment teh byte counter by the number of bytes per pixel

          currentpixel++; //increment by 1


        }

      }else{

        chunkheader -= 127; //subtract 127 to get rid of the id bit


        //read the next pixel

        if(fread(colorbuffer, 1, tga.bytesPerPixel, file) != tga.bytesPerPixel)
        {
          fprintf(stderr, "Error Reading Pixel 2\n");
          return false;
        }

        //start the loop

        for(short counter =0; counter < chunkheader; counter++)
        {
          data[currentbyte] = colorbuffer[2]; //cpy the 'R' byte

          data[currentbyte + 1] = colorbuffer[1]; //cpy the 'G' byte

          data[currentbyte + 2] = colorbuffer[0]; // cpy the 'B' byte


          if(tga.bytesPerPixel == 4)
          {
            data[currentbyte + 3] = colorbuffer[3];
          }
        }

          currentbyte += tga.bytesPerPixel;
          currentpixel++;
      }

    }while(currentpixel < pixelcount);

    fclose(file);

    return true;
  }

  public:

  unsigned long x;
  unsigned long y;
  unsigned short int bpp;
  char* data;
  unsigned int ID;
  GLuint type;

  TEXTURE()
  {
    type = GL_RGB;
  }

  bool LoadTGA(char* FileName)
  {
    //find out if its compressed or not

    GLubyte tgaheader[12];
    //uncompressed tga header

    GLubyte uTGAcompare[12] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    //compressed tga header

    GLubyte cTGAcompare[12] = {0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0 ,0};
    FILE* file;

    file = fopen(FileName, "rb");

    if(file == 0)
    {
      fprintf(stderr, "Error invalid TGA file: %s\n", FileName);
      return false;
    }

    if(fread(&tgaheader, sizeof(tgaheader), 1, file) == 0)
    {
       fprintf(stderr, "Error invalid TGA file: %s\n", FileName);
       fclose(file);
       return false;
    }

    if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
    {
      fprintf(stderr, "loading uncompressed...\n");
      //load an uncompressed tga

      if(LoadUncompressedTGA(file) == false)
      {
        fprintf(stderr, "Error Loading UnCompressed TGA File: %s\n", FileName);
        fclose(file);
        return false;
      }
    }else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)
    {
      fprintf(stderr, "loading compressed...\n");
      //load compressed tga

      if(LoadCompressedTGA(file) == false)
      {
        fprintf(stderr, "Error Loading Compressed TGA File: %s\n", FileName);
        fclose(file);
        return false;
      }
    }else{
        fprintf(stderr, "Error invalid TGA file: %s\n", FileName);
        fclose(file);
        return false;
    }

     fclose(file);
     return true;
  }
  /*
    "Both width and height must have the form 2^m + 2b, where m is a non-negative integer (which can have a
    different value for width than for height) and b is the value of border. The maximum size of a texture
    map depends on the implementation of OpenGL, but it must be at least 64 x 64 (or 66 x 66 with borders)."
    --OpenGL Programming Guide

    Meaning:

    You can use width or height of 2, 4, 8, 16, 32, 64, (on new video cards) 128, 256, 512 (They dont have
    to be the same)

    If you have a texture border you add 2 to the size.
*/
  int LoadTexture(char* FileName)
  {

    if(LoadTGA(FileName) == 0)
    {
      return 0;
    }

    glGenTextures(1, &ID);
    glBindTexture(GL_TEXTURE_2D, ID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, 3, x, y, 0, type, GL_UNSIGNED_BYTE, data);

    return 1;
  }
};
  
[edited by - nukem on September 25, 2002 10:17:00 PM]
--------------------------Nukemmsn: nukem996@hotmail.comaim: nukem996open source open mind
dude, use the [ source] and [ /source] tags (minus the space of course).
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Advertisement
heh sorry I used < source > < /source >
--------------------------Nukemmsn: nukem996@hotmail.comaim: nukem996open source open mind
wow is this really a whole class for each texture????

just a little tipp:

think of a program that is going to load hundrets of textures... for each texture you would build an instance of your class which is going to take an awesome amount of bytes in comparison what you would need. for texture loading functions it is recommened to write c only so that you can build a dll out of your source without using the mfc. the export function could f.e. look like this:

bool LoadTexture( const char *Filename, GLubyte *memory );

you give the filename of the texture and a memory "slot". more you do not need to load a texture and use them later. ( dont tell me other things im doing it this way )

ok, but i cant find the error in your source code. everything seems ok so far imho. do you always allocate memory without multiply the size you want with the size of the var type? ok, its not the error in your code because malloc allocates memorys in bytes.. so there would be no change at all.

[edited by - cANaBiTz on September 26, 2002 1:30:56 PM]
Ya I know it takes up a huge amount of memory. Currently Im just trying to get it load the graphics then im gona work on it so it can load hundreads of graphics. Currently its only loading one since im still building the engine. I cannt do a DLL since I use linux, but I can make a lib file .

Thanks for the tip!
--------------------------Nukemmsn: nukem996@hotmail.comaim: nukem996open source open mind

This topic is closed to new replies.

Advertisement