TGALoader.cpp
上传用户:arsena_zhu
上传日期:2022-07-12
资源大小:399k
文件大小:16k
- /********************************************************************************
- * Name: TGA.cpp *
- * Header: tga.h *
- * Purpose: Load Compressed and Uncompressed TGA files *
- * Functions: LoadTGA(TGATexture * texture, char * filename) *
- * LoadCompressedTGA(TGATexture * texture, char * filename, FILE * fTGA) *
- * LoadUncompressedTGA(TGATexture * texture, char * filename, FILE * fTGA)*
- ********************************************************************************/
- #include "main.h"
- /********************************************************************************
- * name : LoadTGA(TGATexture * texture, char * filename) *
- * function: Open and test the file to make sure it is a valid TGA file *
- * parems: texture, pointer to a Texture structure *
- * filename, string pointing to file to open *
- ********************************************************************************/
- /*******************************************************************************
- * TGA LOADER
- *******************************************************************************/
- bool LoadTGA(TGATexture *tgatex, char *filename)
- {
- strcpy(tgatex->filename, filename);
- GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
- tgatex->file = fopen(tgatex->filename, "rb"); // Open file for reading
- if(tgatex->file == NULL) // If it didn't open....
- {
- MessageBox(NULL, "Could not open texture file", filename, MB_OK); // Display an error message
- return false; // Exit function
- }
- fread(tgatex->versionHeader, 1, sizeof(tgatex->versionHeader), tgatex->file);
- if (memcmp(uTGAcompare, tgatex->versionHeader, sizeof(tgatex->versionHeader)) == 0) // See if header matches the predefined header of
- {
- fread(tgatex->header, 1, sizeof(tgatex->header), tgatex->file);
- if(!LoadUncompressedTGAData(tgatex))
- {
- MessageBox(NULL, "error while loading image", "error", MB_OK); // Display an error
- return false;
- }
- }
- else // If header matches neither type
- {
- MessageBox(NULL, "bad TGA file", "Invalid Image", MB_OK); // Display an error
- return false; // Exit function
- }
- fclose(tgatex->file);
- return true;
- }
- GLuint LoadTGAIntoGL(char *filename)
- {
- ////////////////////////////////////////////////////////////////////////////////
- // !! THIS NEEDS TO BE FIXED !!
- ////////////////////////////////////////////////////////////////////////////////
- char brm[128];
- char fname[128];
- char file_name[128];
- strcpy(file_name, filename);
- // MessageBox(NULL, file_name, "filename",MB_OK|MB_ICONEXCLAMATION);
- for (int i=0; i < 128 ; i++)
- {
- fname[i]=file_name[i+1];
- }
- // MessageBox(NULL, fname, "fname",MB_OK|MB_ICONEXCLAMATION);
- strcpy(brm, "data\models");
- strcat(brm, fname);
- // MessageBox(NULL, brm, "fname",MB_OK|MB_ICONEXCLAMATION);
- ////////////////////////////////////////////////////////////////////////////////
- return LoadTGAIntoGL(brm, NULL, NULL);
- }
- GLuint LoadTGAIntoGL(char *filename, int *get_x, int *get_y) // Load a TGA file
- {
- TGATexture t;
- GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
- GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0}; // Compressed TGA Header
- t.file = fopen(t.filename, "rb"); // Open file for reading
- if(t.file == NULL) // If it didn't open....
- {
- MessageBox(NULL, "Could not open texture file", filename, MB_OK); // Display an error message
- return false; // Exit function
- }
- if(fread(t.header, sizeof(t.header), 1, t.file) == 0) // Attempt to read 12 byte header from file
- {
- MessageBox(NULL, "Could not read file header", "ERROR", MB_OK); // If it fails, display an error message
- if(t.file != NULL) // Check to seeiffile is still open
- {
- fclose(t.file); // If it is, close it
- }
- return false; // Exit function
- }
- if(memcmp(uTGAcompare, &t.header, sizeof(t.header)) == 0) // See if header matches the predefined header of
- { // an Uncompressed TGA image
- LoadUncompressedTGAData(&t); // If so, jump to Uncompressed TGA loading code
- }
- else if(memcmp(cTGAcompare, &t.header, sizeof(t.header)) == 0) // See if header matches the predefined header of
- { // an RLE compressed TGA image
- LoadCompressedTGAData(&t); // If so, jump to Compressed TGA loading code
- }
- else // If header matches neither type
- {
- MessageBox(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK); // Display an error
- return false; // Exit function
- }
- fclose(t.file);
- if (get_x != NULL && get_y != NULL)
- {
- *get_x = t.width;
- *get_y = t.height;
- }
- // textures on models were vertically inverted without this
- // (by psycho ;] (proud of this unique 'low level' function, lol))
- // by the way, it's inverted only on models, not in normal gui pictures :/
- if (t.bpp == 24 && get_x == NULL && get_y == NULL)
- {
- TGATexture tex;
- tex.image = (GLubyte *)malloc(t.size);
- int yy = t.height;
- int xx = t.width*3;
- for(GLuint i=0; i<yy; i++)
- {
- for(GLuint j=0; j<xx; j+=(t.bpp/8))
- {
- tex.image[ (i*xx) + j ] = t.image[ (yy-1-i)*xx + j ];
- tex.image[ (i*xx) + j + 1] = t.image[ (yy-1-i)*xx + j + 1];
- tex.image[ (i*xx) + j + 2] = t.image[ (yy-1-i)*xx + j + 2];
- }
- }
- delete [] t.image;
- t.image = tex.image;
- }
- return GenerateTexture(&t);
- }
- int GenerateTexture(TGATexture *t)
- {
- glGenTextures(1, &t->texID);
- glBindTexture(GL_TEXTURE_2D, t->texID);
- glTexImage2D(GL_TEXTURE_2D, 0, t->bpp / 8, t->width, t->height, 0,
- t->type, GL_UNSIGNED_BYTE, t->image);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
- return t->texID;
- }
- bool LoadUncompressedTGAData(TGATexture *t) // Load an uncompressed TGA (note, much of this code is based on NeHe's
- { // TGA Loading code nehe.gamedev.net)
- /*
- if(fread(t->header, sizeof(t->header), 1, t->file) == 0) // Read TGA header
- {
- MessageBox(NULL, "Could not read info header", "ERROR", MB_OK); // Display error
- if(t->file != NULL) // if file is still open
- {
- fclose(t->file); // Close it
- }
- return false; // Return failular
- }
- */
- t->width = t->header[1] * 256 + t->header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
- t->height = t->header[3] * 256 + t->header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
- t->bpp = t->header[4]; // Determine the bits per pixel
- if((t->width <= 0) || (t->height <= 0) || ((t->bpp != 24) && (t->bpp !=32))) // Make sure all information is valid
- {
- MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); // Display Error
- if(t->file != NULL) // Check if file is still open
- {
- fclose(t->file); // If so, close it
- }
- return false; // Return failed
- }
- if(t->bpp == 24) // If the BPP of the image is 24...
- t->type = GL_RGB; // Set Image type to GL_RGB
- else // Else if its 32 BPP
- t->type = GL_RGBA; // Set image type to GL_RGBA
- t->size = (t->bpp/8 * t->width * t->height); // Compute the total amout ofmemory needed to store data
- t->image = (GLubyte *)malloc(t->size); // Allocate that much memory
- if(t->image == NULL) // If no space was allocated
- {
- MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Error
- fclose(t->file); // Close the file
- return false; // Return failed
- }
- if(fread(t->image, 1, t->size, t->file) != t->size) // Attempt to read image data
- {
- MessageBox(NULL, "Could not read image data", "ERROR", MB_OK); // Display Error
- if(t->image != NULL) // If imagedata has data in it
- {
- free(t->image); // Delete data from memory
- }
- fclose(t->file); // Close file
- return false; // Return failed
- }
- // Byte Swapping Optimized By Steve Thomas
- for(GLuint cswap = 0; cswap < t->size; cswap += t->bpp/8)
- {
- t->image[cswap] ^= t->image[cswap+2] ^=
- t->image[cswap] ^= t->image[cswap+2];
- }
- fclose(t->file); // Close file
- return true; // Return success
- }
- bool LoadCompressedTGAData(TGATexture *t) // Load COMPRESSED TGAs
- {
- if(fread(t->header, sizeof(t->header), 1, t->file) == 0) // Attempt to read header
- {
- MessageBox(NULL, "Could not read info header", "ERROR", MB_OK); // Display Error
- if(t->file != NULL) // If file is open
- {
- fclose(t->file); // Close it
- }
- return false; // Return failed
- }
- t->width = t->header[1] * 256 + t->header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
- t->height = t->header[3] * 256 + t->header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
- t->bpp = t->header[4]; // Determine Bits Per Pixel
- if((t->width <= 0) || (t->height <= 0) || ((t->bpp != 24) && (t->bpp !=32))) //Make sure all texture info is ok
- {
- MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); // If it isnt...Display error
- if(t->file != NULL) // Check if file is open
- {
- fclose(t->file); // Ifit is, close it
- }
- return false; // Return failed
- }
- if(t->bpp == 24) // If the BPP of the image is 24...
- t->type = GL_RGB; // Set Image type to GL_RGB
- else // Else if its 32 BPP
- t->type = GL_RGBA; // Set image type to GL_RGBA
- t->size = (t->bpp/8 * t->width * t->height); // Compute amout of memory needed to store image
- t->image = (GLubyte *)malloc(t->size); // Allocate that much memory
- if(t->image == NULL) // If it wasnt allocated correctly..
- {
- MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Error
- fclose(t->file); // Close file
- return false; // Return failed
- }
- GLuint pixelcount = t->height * t->width; // Nuber of pixels in the image
- GLuint currentpixel = 0; // Current pixel being read
- GLuint currentbyte = 0; // Current byte
- GLubyte * colorbuffer = (GLubyte *)malloc(t->bpp/8); // Storage for 1 pixel
- do
- {
- GLubyte chunkheader = 0; // Storage for "chunk" header
- if(fread(&chunkheader, sizeof(GLubyte), 1, t->file) == 0) // Read in the 1 byte header
- {
- MessageBox(NULL, "Could not read RLE header", "ERROR", MB_OK); // Display Error
- if(t->file != NULL) // If file is open
- {
- fclose(t->file); // Close file
- }
- if(t->image != NULL) // If there is stored image data
- {
- free(t->image); // Delete image data
- }
- return false; // Return failed
- }
- if(chunkheader < 128) // If the ehader is < 128, it means the that is the number of RAW color packets minus 1
- { // that follow the header
- chunkheader++; // add 1 to get number of following color values
- for(short counter = 0; counter < chunkheader; counter++) // Read RAW color values
- {
- if(fread(colorbuffer, 1, t->bpp/8, t->file) != t->bpp/8) // Try to read 1 pixel
- {
- MessageBox(NULL, "Could not read image data", "ERROR", MB_OK); // IF we cant, display an error
- if(t->file != NULL) // See if file is open
- {
- fclose(t->file); // If so, close file
- }
- if(colorbuffer != NULL) // See if colorbuffer has data in it
- {
- free(colorbuffer); // If so, delete it
- }
- if(t->image != NULL) // See if there is stored Image data
- {
- free(t->image); // If so, delete it too
- }
- return false; // Return failed
- }
- // write to memory
- t->image[currentbyte ] = colorbuffer[2]; // Flip R and B vcolor values around in the process
- t->image[currentbyte + 1 ] = colorbuffer[1];
- t->image[currentbyte + 2 ] = colorbuffer[0];
- if(t->bpp/8 == 4) // if its a 32 bpp image
- {
- t->image[currentbyte + 3] = colorbuffer[3]; // copy the 4th byte
- }
- currentbyte += t->bpp/8; // Increase thecurrent byte by the number of bytes per pixel
- currentpixel++; // Increase current pixel by 1
- if(currentpixel > pixelcount) // Make sure we havent read too many pixels
- {
- MessageBox(NULL, "Too many pixels read", "ERROR", MB_OK | MB_ICONERROR ); // if there is too many... Display an error!
- if(t->file != NULL) // If there is a file open
- {
- fclose(t->file); // Close file
- }
- if(colorbuffer != NULL) // If there is data in colorbuffer
- {
- free(colorbuffer); // Delete it
- }
- if(t->image != NULL) // If there is Image data
- {
- free(t->image); // delete it
- }
- return false; // Return failed
- }
- }
- }
- else // chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
- {
- chunkheader -= 127; // Subteact 127 to get rid of the ID bit
- if(fread(colorbuffer, 1, t->bpp/8, t->file) != t->bpp/8) // Attempt to read following color values
- {
- MessageBox(NULL, "Could not read from file", "ERROR", MB_OK); // If attempt fails.. Display error (again)
- if(t->file != NULL) // If thereis a file open
- {
- fclose(t->file); // Close it
- }
- if(colorbuffer != NULL) // If there is data in the colorbuffer
- {
- free(colorbuffer); // delete it
- }
- if(t->image != NULL) // If thereis image data
- {
- free(t->image); // delete it
- }
- return false; // return failed
- }
- for(short counter = 0; counter < chunkheader; counter++) // copy the color into the image data as many times as dictated
- { // by the header
- t->image[currentbyte ] = colorbuffer[2]; // switch R and B bytes areound while copying
- t->image[currentbyte + 1 ] = colorbuffer[1];
- t->image[currentbyte + 2 ] = colorbuffer[0];
- if(t->bpp/8 == 4) // If TGA images is 32 bpp
- {
- t->image[currentbyte + 3] = colorbuffer[3]; // Copy 4th byte
- }
- currentbyte += t->bpp/8; // Increase current byte by the number of bytes per pixel
- currentpixel++; // Increase pixel count by 1
- if(currentpixel > pixelcount) // Make sure we havent written too many pixels
- {
- MessageBox(NULL, "Too many pixels read", "ERROR", MB_OK | MB_ICONERROR ); // if there is too many... Display an error!
- if(t->file != NULL) // If there is a file open
- {
- fclose(t->file); // Close file
- }
- if(colorbuffer != NULL) // If there is data in colorbuffer
- {
- free(colorbuffer); // Delete it
- }
- if(t->image != NULL) // If there is Image data
- {
- free(t->image); // delete it
- }
- return false; // Return failed
- }
- }
- }
- }
- while(currentpixel < pixelcount); // Loop while there are still pixels left
- fclose(t->file); // Close the file
- return true; // return success
- }