www.pudn.com > Gimcrack-v0.0051-Source.zip > targa.cpp
#include#include #include #include "targa.h" #include "tgaformat.h" using namespace std; /////////////////////////////////////////////////////////////////////////// GcTarga::GcTarga(): imageTypeCode(0), imageWidth(0), imageHeight(0), bitCount(0), imageData(NULL) { // Constructing the targa object } /////////////////////////////////////////////////////////////////////////// GcTarga::~GcTarga() { // Free memmory Destroy(); } /////////////////////////////////////////////////////////////////////////// bool GcTarga::Load(char *fileName) { TGAHeader header; // Open the TGA file ifstream file(fileName, ios::in | ios::binary); // Check to see if opened if(!file) { MessageBox(NULL, "Failed to open TGA file.", "ERROR", MB_OK); return false; } // Read the header file.read((char*)&header, sizeof(TGAHeader)); // Sasve neccessary data imageTypeCode = header.imageTypeCode; imageWidth = header.imageWidth; imageHeight = header.imageHeight; bitCount = header.bitCount; // Check that it's the corect type if((imageTypeCode != 2) && (imageTypeCode != 3) && (imageTypeCode != 10)) { file.close(); MessageBox(NULL, "The TGA file is not of a suported format", "ERROR", MB_OK); return false; } if(imageTypeCode != 10) { // Load a normal, non compressed tga if(!LoadNormal(file)) { file.close(); return false; } } else { // Load a RLE compressed tga if(!LoadRLE(file)) { file.close(); return false; } } // Close the file file.close(); return true; } /////////////////////////////////////////////////////////////////////////// bool GcTarga::Write(char *fileName, uint width, uint height, uint screenBpp) { TGAHeader header; int colorMode; byte colorSwap; long imageSize; // Create file ofr writing ofstream file(fileName, ios::out | ios::binary); // Check to make sure it's opened corectly if(!file) { file.close(); return false; } // Clear the header memset(&header, 0, sizeof(TGAHeader)); // Fill the header with correct data header.bitCount = screenBpp; header.colorMapEntrySize = 0; header.colorMapLenght = 0; header.colorMapOrgin = 0; header.colorMapType = 0; header.imageDescriptor = 0; header.imageHeight = height; header.imageIDLenght = 0; header.imageTypeCode = 2; header.imageWidth = width; header.imageXOrgin = 0; header.imageYOrgin = 0; // Get the color mode colorMode = screenBpp / 8; // Write the header data to the file file.write((char*)&header, sizeof(TGAHeader)); // Calculate the image size imageSize = width * height * colorMode; // Change image data from RGB to BGR for(int i = 0; i < imageSize; i += colorMode) { colorSwap = imageData[i]; imageData[i] = imageData[i + 2]; imageData[i + 2] = colorSwap; } // Write the image data file.write((char*)imageData, imageSize); // Close the file file.close(); return true; } /////////////////////////////////////////////////////////////////////////// void GcTarga::Screenshot(char *fileName, uint winWidth, uint winHeight, uint screenBpp) { /* WARNING! DO NOT USE THIS IF THE BITMAP ARE TO BE USED FURTHER ON */ // Make sure that the memmory is freed if(imageData != NULL) { delete [] imageData; imageData = NULL; } // Allocate and reset the memory imageData = new byte[winWidth * winHeight * (screenBpp / 8)]; memset(imageData, 0, sizeof(winWidth * winHeight * (screenBpp / 8))); // Check for format if(screenBpp == 32) { // Read the image data from the window glReadPixels(0, 0, winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, imageData); } else { // Read the image data from the window glReadPixels(0, 0, winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, imageData); } // Write to TGA file Write(fileName, winWidth, winHeight, screenBpp); // Make sure that the memmory is freed if(imageData != NULL) { delete [] imageData; imageData = NULL; } } /////////////////////////////////////////////////////////////////////////// void GcTarga::Draw(uint xPos, uint yPos) { // Bind a null texture to "disable texturing glBindTexture(GL_TEXTURE_2D, NULL); // Set the correct drawing options glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Set the position glRasterPos2i(xPos, yPos); // Draw the TGA if(bitCount == 32) { glDrawPixels(imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE, imageData); } else { glDrawPixels(imageWidth, imageHeight, GL_RGB, GL_UNSIGNED_BYTE, imageData); } } /////////////////////////////////////////////////////////////////////////// void GcTarga::Destroy() { if(imageData != NULL) { delete [] imageData; imageData = NULL; } } /////////////////////////////////////////////////////////////////////////// bool GcTarga::LoadNormal(ifstream &file) { byte colorMode; byte colorSwap; // Check for depth if((bitCount == 24) || (bitCount == 32)) { // Get the color mode colorMode = bitCount / 8; // Calculate the size of the image imageSize = imageWidth * imageHeight * colorMode; // Allocate memory for image data imageData = new byte[imageSize]; // Read image data file.read((char*)imageData, imageSize); // Change BGR to RGB (BGRA to RGBA) for(int i = 0; i < imageSize; i += colorMode) { colorSwap = imageData[i]; imageData[i] = imageData[i + 2]; imageData[i + 2] = colorSwap; } } else if(bitCount == 16) { ushort *pixels; int r = 0, g = 0, b = 0; // RGB color mode (after conversion) imageSize = imageWidth * imageHeight * 3; // Allocate memory for image data imageData = new byte[imageSize]; byte *buffer = new byte[imageSize]; // Read the image data file.read((char*)buffer, imageSize); // Set pointer to first group of pixles pixels = (ushort*)buffer; // Convert to 24 bit RGB for(int i = 0; i < imageWidth * imageHeight; i++) { // Change the pixel to 24 bit b = (pixels[i] & 0x1f) << 3; g = ((pixels[i] >> 5) & 0x1f) << 3; r = ((pixels[i] >> 10) & 0x1f) << 3; // Swap to RGB and save in array imageData[i * 3 + 0] = r; imageData[i * 3 + 1] = g; imageData[i * 3 + 2] = b; } // Free upp the memory delete [] buffer; } else { MessageBox(NULL, "TGA file of a not suported bpp", "Error", MB_OK); return false; } return true; } /////////////////////////////////////////////////////////////////////////// bool GcTarga::LoadRLE(ifstream &file) { /* This code is based on gametutorials.com's tutorial */ /* on loading a RLE TGA file. */ byte rleID = 0; byte colorCount = 0; byte colorMode = bitCount / 8; int colorsRead = 0; int stride = colorMode * imageWidth; int pixels = 0, j = 0; int counter = 0; int dataSize; // Find the size of the image data file.seekg(0, ios::end); dataSize = file.tellg(); dataSize -= sizeof(TGAHeader); // Set position for data reading file.seekg(sizeof(TGAHeader), ios::beg); // Allocate memory for image data imageData = new byte[stride * imageHeight]; byte *color = new byte[colorMode]; byte *buffer = new byte[dataSize]; // Read all image data to the buffer file.read((char*)buffer, dataSize); // Read the image data while(pixels < imageWidth * imageHeight) { // Read in the current color count + 1 rleID = buffer[counter++]; if(rleID < 128) { /* The colroCount number of colors are uniqe */ // Calculate the number of colors to be read colorCount = rleID + 1; // Go through and read all the unique colors found while(colorCount) { // Read in the current color for(j = 0; j < colorMode; j++) { color[j] = buffer[counter++]; } // Store the current pixel in our image array imageData[colorsRead + 0] = color[2]; imageData[colorsRead + 1] = color[1]; imageData[colorsRead + 2] = color[0]; // Is this a RGBA file? if(bitCount == 32) { imageData[colorsRead + 3] = color[3]; } pixels++; colorCount--; colorsRead += colorMode; } } else { /* The colroCount number of colors are the same */ // Calculate the number of colors to be read colorCount = rleID - 127; // Read in the current color for(j = 0; j < colorMode; j++) { color[j] = buffer[counter++]; } // Write colorCount pixels of the smae color to the imageData while(colorCount) { // Swap to RGB form BGR imageData[colorsRead + 0] = color[2]; imageData[colorsRead + 1] = color[1]; imageData[colorsRead + 2] = color[0]; // Is this a RGBA file? if(bitCount == 32) { imageData[colorsRead + 3] = color[3]; } pixels++; colorCount--; colorsRead += colorMode; } } } // Free up the memory delete [] color; delete [] buffer; return true; } ///////////////////////////////////////////////////////////////////////////