本文主要是介绍使用Gdi+加载tga图片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在csdn找到一份加载tga的代码,下来后少许改造,就能将tga图片加载的Gdiplus::Bitmap中了,于是分享一下代码
加载tga代码的头文件,Tga.h:
#ifndef __TGA_H__
#define __TGA_H__
//
//#pragma comment(lib, "Opengl32.lib") //Link to OpenGL32.lib so we can use OpenGL stuff#include <windows.h> // Standard windows header
#include <stdio.h> // Standard I/O header
#include <gl\gl.h> // Header for OpenGL32 librarytypedef struct
{GLubyte * imageData; // Image Data (Up To 32 Bits)GLuint bpp; // Image Color Depth In Bits Per PixelGLuint width; // Image WidthGLuint height; // Image HeightGLuint texID; // Texture ID Used To Select A TextureGLuint type; // Image Type (GL_RGB, GL_RGBA)
} Texture; typedef struct
{GLubyte Header[12]; // TGA File Header
} TGAHeader;typedef struct
{GLubyte header[6]; // First 6 Useful Bytes From The HeaderGLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA FileGLuint imageSize; // Used To Store The Image Size When Setting Aside RamGLuint temp; // Temporary VariableGLuint type; GLuint Height; //Height of ImageGLuint Width; //Width ofImageGLuint Bpp; // Bits Per Pixel
} TGA;bool LoadUncompressedTGA(Texture *, const TCHAR *, FILE *); // Load an Uncompressed file
bool LoadCompressedTGA(Texture *, const TCHAR *, FILE *); // Load a Compressed file
bool LoadTGA(Texture * texture, const TCHAR * filename);#endif
加载tga代码的执行文件,TGALoader.cpp:
/********************************************************************************
/Name: TGA.cpp *
/Header: tga.h *
/Purpose: Load Compressed and Uncompressed TGA files *
/Functions: LoadTGA(Texture * texture, TCHAR * filename) *
/ LoadCompressedTGA(Texture * texture, TCHAR * filename, FILE * fTGA) *
/ LoadUncompressedTGA(Texture * texture, TCHAR * filename, FILE * fTGA)*
/*******************************************************************************/
#include "stdafx.h"
#include "Tga.h"TGAHeader tgaheader; // TGA header
TGA tga; // TGA image dataGLubyte 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/********************************************************************************
/name : LoadTGA(Texture * texture, TCHAR * 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 *
/********************************************************************************/bool LoadTGA(Texture * texture, const TCHAR * filename) // Load a TGA file
{FILE * fTGA; // File pointer to texture fileerrno_t err = _tfopen_s(&fTGA, filename, _T("rb")); // Open file for readingif(err != 0 || fTGA == NULL) // If it didn't open....{MessageBoxA(NULL, "Could not open texture file", "ERROR", MB_OK); // Display an error messagereturn false; // Exit function}if(fread(&tgaheader, sizeof(TGAHeader), 1, fTGA) == 0) // Attempt to read 12 byte header from file{MessageBoxA(NULL, "Could not read file header", "ERROR", MB_OK); // If it fails, display an error message if(fTGA != NULL) // Check to seeiffile is still open{fclose(fTGA); // If it is, close it}return false; // Exit function}if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of { // an Uncompressed TGA imagereturn LoadUncompressedTGA(texture, filename, fTGA); // If so, jump to Uncompressed TGA loading code}else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0) // See if header matches the predefined header of{ // an RLE compressed TGA imagereturn LoadCompressedTGA(texture, filename, fTGA); // If so, jump to Compressed TGA loading code}MessageBoxA(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK); // Display an errorfclose(fTGA);return false; // Exit function
}bool LoadUncompressedTGA(Texture * texture, const TCHAR * filename, FILE * fTGA) // Load an uncompressed TGA (note, much of this code is based on NeHe's
{ // TGA Loading code nehe.gamedev.net)if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0) // Read TGA header{ MessageBoxA(NULL, "Could not read info header", "ERROR", MB_OK); // Display errorif(fTGA != NULL) // if file is still open{fclose(fTGA); // Close it}return false; // Return failular} texture->width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)texture->height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)texture->bpp = tga.header[4]; // Determine the bits per pixeltga.Width = texture->width; // Copy width into local structure tga.Height = texture->height; // Copy height into local structuretga.Bpp = texture->bpp; // Copy BPP into local structureif((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) // Make sure all information is valid{MessageBoxA(NULL, "Invalid texture information", "ERROR", MB_OK); // Display Errorif(fTGA != NULL) // Check if file is still open{fclose(fTGA); // If so, close it}return false; // Return failed}if(texture->bpp == 24) // If the BPP of the image is 24...texture->type = GL_RGB; // Set Image type to GL_RGBelse // Else if its 32 BPPtexture->type = GL_RGBA; // Set image type to GL_RGBAtga.bytesPerPixel = (tga.Bpp / 8); // Compute the number of BYTES per pixeltga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute the total amout ofmemory needed to store datatexture->imageData = (GLubyte *)malloc(tga.imageSize); // Allocate that much memoryif(texture->imageData == NULL) // If no space was allocated{MessageBoxA(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Errorfclose(fTGA); // Close the filereturn false; // Return failed}if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize) // Attempt to read image data{MessageBoxA(NULL, "Could not read image data", "ERROR", MB_OK); // Display Errorif(texture->imageData != NULL) // If imagedata has data in it{free(texture->imageData); // Delete data from memory}fclose(fTGA); // Close filereturn false; // Return failed}// Byte Swapping Optimized By Steve Thomasfor(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel){texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=texture->imageData[cswap] ^= texture->imageData[cswap+2];}fclose(fTGA); // Close filereturn true; // Return success
}bool LoadCompressedTGA(Texture * texture, const TCHAR * filename, FILE * fTGA) // Load COMPRESSED TGAs
{ if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0) // Attempt to read header{MessageBoxA(NULL, "Could not read info header", "ERROR", MB_OK); // Display Errorif(fTGA != NULL) // If file is open{fclose(fTGA); // Close it}return false; // Return failed}texture->width = tga.header[1] * 256 + tga.header[0]; // Determine The TGA Width (highbyte*256+lowbyte)texture->height = tga.header[3] * 256 + tga.header[2]; // Determine The TGA Height (highbyte*256+lowbyte)texture->bpp = tga.header[4]; // Determine Bits Per Pixeltga.Width = texture->width; // Copy width to local structuretga.Height = texture->height; // Copy width to local structuretga.Bpp = texture->bpp; // Copy width to local structureif((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) //Make sure all texture info is ok{MessageBoxA(NULL, "Invalid texture information", "ERROR", MB_OK); // If it isnt...Display errorif(fTGA != NULL) // Check if file is open{fclose(fTGA); // Ifit is, close it}return false; // Return failed}if(texture->bpp == 24) // If the BPP of the image is 24...texture->type = GL_RGB; // Set Image type to GL_RGBelse // Else if its 32 BPPtexture->type = GL_RGBA; // Set image type to GL_RGBAtga.bytesPerPixel = (tga.Bpp / 8); // Compute BYTES per pixeltga.imageSize = (tga.bytesPerPixel * tga.Width * tga.Height); // Compute amout of memory needed to store imagetexture->imageData = (GLubyte *)malloc(tga.imageSize); // Allocate that much memoryif(texture->imageData == NULL) // If it wasnt allocated correctly..{MessageBoxA(NULL, "Could not allocate memory for image", "ERROR", MB_OK); // Display Errorfclose(fTGA); // Close filereturn false; // Return failed}GLuint pixelcount = tga.Height * tga.Width; // Nuber of pixels in the imageGLuint currentpixel = 0; // Current pixel being readGLuint currentbyte = 0; // Current byte GLubyte * colorbuffer = (GLubyte *)malloc(tga.bytesPerPixel); // Storage for 1 pixeldo{GLubyte chunkheader = 0; // Storage for "chunk" headerif(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0) // Read in the 1 byte header{MessageBoxA(NULL, "Could not read RLE header", "ERROR", MB_OK); // Display Errorif(fTGA != NULL) // If file is open{fclose(fTGA); // Close file}if(texture->imageData != NULL) // If there is stored image data{free(texture->imageData); // 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 headerchunkheader++; // add 1 to get number of following color valuesfor(short counter = 0; counter < chunkheader; counter++) // Read RAW color values{if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Try to read 1 pixel{MessageBoxA(NULL, "Could not read image data", "ERROR", MB_OK); // IF we cant, display an errorif(fTGA != NULL) // See if file is open{fclose(fTGA); // If so, close file}if(colorbuffer != NULL) // See if colorbuffer has data in it{free(colorbuffer); // If so, delete it}if(texture->imageData != NULL) // See if there is stored Image data{free(texture->imageData); // If so, delete it too}return false; // Return failed}// write to memorytexture->imageData[currentbyte ] = colorbuffer[2]; // Flip R and B vcolor values around in the process texture->imageData[currentbyte + 1 ] = colorbuffer[1];texture->imageData[currentbyte + 2 ] = colorbuffer[0];if(tga.bytesPerPixel == 4) // if its a 32 bpp image{texture->imageData[currentbyte + 3] = colorbuffer[3]; // copy the 4th byte}currentbyte += tga.bytesPerPixel; // Increase thecurrent byte by the number of bytes per pixelcurrentpixel++; // Increase current pixel by 1if(currentpixel > pixelcount) // Make sure we havent read too many pixels{MessageBoxA(NULL, "Too many pixels read", "ERROR", NULL); // if there is too many... Display an error!if(fTGA != NULL) // If there is a file open{fclose(fTGA); // Close file} if(colorbuffer != NULL) // If there is data in colorbuffer{free(colorbuffer); // Delete it}if(texture->imageData != NULL) // If there is Image data{free(texture->imageData); // 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 bitif(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Attempt to read following color values{ MessageBoxA(NULL, "Could not read from file", "ERROR", MB_OK); // If attempt fails.. Display error (again)if(fTGA != NULL) // If thereis a file open{fclose(fTGA); // Close it}if(colorbuffer != NULL) // If there is data in the colorbuffer{free(colorbuffer); // delete it}if(texture->imageData != NULL) // If thereis image data{free(texture->imageData); // 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 headertexture->imageData[currentbyte ] = colorbuffer[2]; // switch R and B bytes areound while copyingtexture->imageData[currentbyte + 1 ] = colorbuffer[1];texture->imageData[currentbyte + 2 ] = colorbuffer[0];if(tga.bytesPerPixel == 4) // If TGA images is 32 bpp{texture->imageData[currentbyte + 3] = colorbuffer[3]; // Copy 4th byte}currentbyte += tga.bytesPerPixel; // Increase current byte by the number of bytes per pixelcurrentpixel++; // Increase pixel count by 1if(currentpixel > pixelcount) // Make sure we havent written too many pixels{MessageBoxA(NULL, "Too many pixels read", "ERROR", NULL); // if there is too many... Display an error!if(fTGA != NULL) // If there is a file open{fclose(fTGA); // Close file} if(colorbuffer != NULL) // If there is data in colorbuffer{free(colorbuffer); // Delete it}if(texture->imageData != NULL) // If there is Image data{free(texture->imageData); // delete it}return false; // Return failed}}}}while(currentpixel < pixelcount); // Loop while there are still pixels leftif(colorbuffer != NULL) // If there is data in colorbuffer{free(colorbuffer); // Delete it}fclose(fTGA); // Close the filereturn true; // return success
}
然后将所得的Texture结构再转换为Gdiplus::Bitmap的相关代码:
typedef boost::shared_ptr<Gdiplus::Image> ImagePtr;ImagePtr CMainApp::OpenTgaImage(const CString & strImg)
{Texture texTga;if(!LoadTGA(&texTga, strImg))return ImagePtr();boost::shared_ptr<Gdiplus::Bitmap> bmp;Gdiplus::BitmapData bd;switch(texTga.bpp){case 32:bmp.reset(new Gdiplus::Bitmap(texTga.width, texTga.height, PixelFormat32bppARGB));if(Gdiplus::Ok == bmp->LockBits(NULL, Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &bd)){for(UINT y = 0; y < texTga.height; y++){for(UINT x = 0; x < texTga.width; x++){BYTE * pSrc = texTga.imageData + ((texTga.height - y - 1) * texTga.width + x) * 4;BYTE * pDst = (BYTE *)bd.Scan0 + (y * bd.Stride + x * 4);pDst[0] = pSrc[2];pDst[1] = pSrc[1];pDst[2] = pSrc[0];pDst[3] = pSrc[3];}}bmp->UnlockBits(&bd);}break;case 24:bmp.reset(new Gdiplus::Bitmap(texTga.width, texTga.height, PixelFormat24bppRGB));if(Gdiplus::Ok == bmp->LockBits(NULL, Gdiplus::ImageLockModeWrite, PixelFormat24bppRGB, &bd)){for(UINT y = 0; y < texTga.height; y++){for(UINT x = 0; x < texTga.width; x++){BYTE * pSrc = texTga.imageData + ((texTga.height - y - 1) * texTga.width + x) * 3;BYTE * pDst = (BYTE *)bd.Scan0 + (y * bd.Stride + x * 3);pDst[0] = pSrc[2];pDst[1] = pSrc[1];pDst[2] = pSrc[0];}}bmp->UnlockBits(&bd);}break;case 16:ASSERT(false);break;}free(texTga.imageData);return bmp;
}
这篇关于使用Gdi+加载tga图片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!