Im very confuse with Loading TGA machanism.
There is no Loading TGA in Redbook. But I do have a killer book (Beginning OpenGL Game programming by Dave Astle). And I have reached TGA Image Loading.
And I dont understand the mechanism to load TGA. Any simple steps to load uncompress and compress TGA Images?
I don't remember what resources I used to code this (I think it might be similar to tutorials on nehe) but this is the code I use to load TGA and TGA_RLE textures.
It's pretty sloppy in general but it works.
I included the function "generateInternalTexture" but it's pretty poor design (I should not have hard coded all of those parameters for texture generation).
It's pretty sloppy in general but it works.
I included the function "generateInternalTexture" but it's pretty poor design (I should not have hard coded all of those parameters for texture generation).
UINT TextureManager::LoadTGA(char *FileName){ int i; //counter WORD width, height; byte *data = NULL; byte type, bits, length; int rowlength, channels, filesize; byte *pBuffer = NULL; byte *ptr = NULL; FILE *pFile = fopen(FileName, "rb"); if(!pFile) { TextureData << "TextureManager::LoadTGA: could not load tga file: " << FileName << "\n"; return NULL; //FIXME: some sort of error log or notification needed } fseek(pFile, 0, SEEK_END); filesize = ftell(pFile); fseek(pFile, 0, SEEK_SET); pBuffer = new byte[filesize]; fread(pBuffer, 1, filesize, pFile); fclose(pFile); ptr = pBuffer; length = *(byte*)ptr; ptr+=2; type = *(byte*)ptr; ptr += 10; width = *(WORD*)ptr; ptr += sizeof(WORD); height = *(WORD*)ptr; ptr += sizeof(WORD); bits = *(byte*)ptr; ptr++; ptr += length+1; if(bits == 16) { MessageBox(NULL, "LoadTGA: Doesn't support 16bit","ERROR", MB_OK); return NULL; } channels = bits / 8; rowlength = channels * width;//length of a row in bytes data = new byte[rowlength * height]; unsigned int y;if(type != TGA_RLE){ if(channels == 3) { for(i = 0; i < height; i++) { for(y = 0; y < rowlength; y++) { data[(i*rowlength)+y] = *(byte*)ptr; ptr++; } } GLenum GLtype = GL_BGR_EXT; return GenerateInternalTexture(data, channels, width, height, GLtype); } else { if(channels == 4) { for(i = 0; i < height; i++) { for(y = 0; y < rowlength; y++) { data[(i*rowlength)+y] = *(byte*)ptr; ptr++; } } } GLenum GLtype = GL_BGRA_EXT; ptr = NULL; delete [] pBuffer; delete ptr; return GenerateInternalTexture(data, channels, width, height, GLtype); } //FIXME: make sure all of the data is cleaned up! }else if(type == TGA_RLE) //NOTE: LoadTGA_RLE must delete data when done! return LoadTGA_RLE(pBuffer, ptr, bits, channels, width, height, data);}UINT TextureManager::LoadTGA_RLE(byte*pBuffer, byte*ptr, byte bits, byte channels, WORD width, WORD height, byte *data){ byte *pColor = new byte[channels]; int pixelsleft = 0; int colorsread = 0; int pixelsread = 0; int totalpixels = width * height; unsigned int y; //counter //FIXME: must have an error logging system! if(!ptr) return NULL; if(!pBuffer) return NULL; while(pixelsread < totalpixels) { pixelsleft = *(byte*)ptr; ptr++; if(pixelsleft < 128) { pixelsleft++; if(channels == 4) { while(pixelsleft) { for(y = 0; y < channels; y++) { pColor[y] = *(byte*)ptr; ptr++; } data[colorsread + 0] = pColor[0]; data[colorsread + 1] = pColor[1]; data[colorsread + 2] = pColor[2]; data[colorsread + 3] = pColor[3]; pixelsread++; pixelsleft--; colorsread += channels; } } else if(channels == 3) { while(pixelsleft) { for(y = 0; y < channels; y++) { pColor[y] = *(byte*)ptr; ptr++; } data[colorsread + 0] = pColor[0]; data[colorsread + 1] = pColor[1]; data[colorsread + 2] = pColor[2]; pixelsread++; pixelsleft--; colorsread += channels; } } } else { pixelsleft -= 127; for(y = 0; y < channels; y++) { pColor[y] = *(byte*)ptr; ptr++; } if(channels == 4) { while(pixelsleft) { data[colorsread + 0] = pColor[0]; data[colorsread + 1] = pColor[1]; data[colorsread + 2] = pColor[2]; data[colorsread + 3] = pColor[3]; pixelsread++; pixelsleft--; colorsread += channels; } } else if(channels == 3) { while(pixelsleft) { data[colorsread + 0] = pColor[0]; data[colorsread + 1] = pColor[1]; data[colorsread + 2] = pColor[2]; pixelsread++; pixelsleft--; colorsread += channels; } } } } ptr=NULL; delete [] pBuffer; delete ptr; GLenum GLtype; if(channels == 4) GLtype = GL_BGRA_EXT; if(channels == 3) GLtype = GL_BGR_EXT; return GenerateInternalTexture(data, channels, width, height, GLtype); }UINT TextureManager::GenerateInternalTexture(byte * data, int channels, int width, int height, GLenum type){ UINT texture; gpNTGLAPI->ntglGenTextures(1, &texture); gpNTGLAPI->ntglPixelStorei (GL_UNPACK_ALIGNMENT, 1); gpNTGLAPI->ntglBindTexture(GL_TEXTURE_2D, texture); gluBuild2DMipmaps(GL_TEXTURE_2D, channels,width,height, type, GL_UNSIGNED_BYTE, data); gpNTGLAPI->ntglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //GL_LINEAR_MIPMAP_NEAREST is faster than GL_LINEAR_MIPMAP_LINEAR gpNTGLAPI->ntglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); gpNTGLAPI->ntglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); return texture;}
I used this link to work from, plus a bunch of others from a Google of "TGA file format".
Here is my uncompressed/compressed loader code. Hopefully the comments are descriptive enough and make sense after reading the info at the link above. If not, let me know what part is unclear and I will explain it more.
hth
F451
Here is my uncompressed/compressed loader code. Hopefully the comments are descriptive enough and make sense after reading the info at the link above. If not, let me know what part is unclear and I will explain it more.
// Load uncompressed image databool FImageTGA::LoadUncompressed(){ // so far so good, so allocate memory for image data // calculate byte multiplier for data array bytesPP = spec.bpp / 8; imageSize = spec.width * spec.height * bytesPP; imageData = new unsigned char[imageSize]; if (imageData == NULL) { PrintDebug("[FImageTGA] Error: Failed to allocate %d bytes for image pixel data\n", imageSize); return false; } PrintDebug("[FImageTGA] Allocated %d bytes for image pixel data\n", imageSize); // attempt to load our image data if (!file.read((char *)imageData, imageSize)) { // failed, release resources PrintDebug("[FImageTGA] ERROR: failed to read image pixel data from %s\n", filename.c_str()); delete imageData; imageData = NULL; return false; } // all ok return true;}// Load compressed image databool FImageTGA::LoadCompressed(){ // so far so good, so allocate memory for final image data // calculate byte multiplier for data array bytesPP = spec.bpp / 8; imageSize = spec.width * spec.height * bytesPP; imageData = new unsigned char[imageSize]; if (imageData == NULL) { PrintDebug("[FImageTGA] Error: Failed to allocate %d bytes for image pixel data\n", imageSize); return false; } PrintDebug("[FImageTGA] Allocated %d bytes for image pixel data\n", imageSize); // temporary variables for decoding RLE data unsigned int numPixels = spec.width * spec.height; // number of pixels we expect to read unsigned int pixelCount = 0; // current pixel we are dealing with unsigned int currentByte = 0; // current byte we are dealing with unsigned char * colorBuffer = new unsigned char[bytesPP]; // temp store for current pixel and chunk data unsigned char * chunkByte = new unsigned char[sizeof(unsigned char)]; // keep reading a chunk and pixel data until we have accumulated // enough pixels with the pixel count do { // reset chunk byte each chunk read chunkByte[0] = 0; // read chunk byte if (!file.read((char *)chunkByte, sizeof(unsigned char))) { PrintDebug("[FImageTGA] ERROR: Failed to read RLE chunk byte\n"); // release resources delete colorBuffer; delete chunkByte; return false; } // check if we need to read raw or pixel data next if(chunkByte[0] < 128) { // Raw data! increase chunk value by one to know how many pixels to reproduce chunkByte[0]++; // read in necessary number of pixels and populate the final image data array for (int counter = 0; counter < chunkByte[0]; counter++) { // read pixel data if (!file.read((char *)colorBuffer,bytesPP)) { PrintDebug("[FImageTGA] ERROR: Failed to read necessary raw pixel data\n"); // release resources delete colorBuffer; delete chunkByte; return false; } //transfer pixel colour to final image array imageData[currentByte+0]=colorBuffer[0]; imageData[currentByte+1]=colorBuffer[1]; imageData[currentByte+2]=colorBuffer[2]; if (spec.bpp == 32) imageData[currentByte+3]=colorBuffer[3]; // increase current byte to point to next spot in building our image currentByte += bytesPP; // increase our pixel count pixelCount++; } } else { // Pixel data! calculate how many of the following pixel we need to duplicate chunkByte[0] -= 127; // read pixel data if (!file.read((char *)colorBuffer,bytesPP)) { PrintDebug("[FImageTGA] ERROR: Failed to read necessary pixel data\n"); // release resources delete colorBuffer; delete chunkByte; return false; } // duplicate pixel data as many times as necessary for (int counter = 0; counter < chunkByte[0]; ++counter) { imageData[currentByte+0]=colorBuffer[0]; imageData[currentByte+1]=colorBuffer[1]; imageData[currentByte+2]=colorBuffer[2]; if (spec.bpp == 32) imageData[currentByte+3]=colorBuffer[3]; // increase current byte to point to next spot currentByte += bytesPP; // increase our pixel count pixelCount++; } } } while (pixelCount < numPixels); PrintDebug("[FImageTGA] Read %d pixels in agaist expected %d pixels\n",pixelCount,numPixels); // release resources delete colorBuffer; delete chunkByte; // all ok return true;}
hth
F451
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement