这种图像格式在BMP格式的基础上添加了一个alpha通道,这非常有用,特别是在一些游戏设计里头。
Targa文件格式也主要分为两个部分:头部跟图像数据部分。其中头部数据如下定义
typedef struct tagTARGAFILEHEADER
{
unsigned char imageIDLength; //标识(ID)数据项中的字符数
//0表示么有标识(ID)数据项
unsigned char colorMapType; //颜色位图的类型,必须为
unsigned char imageTypeCode; //未压缩的RGB为
//未压缩的灰度为
short int colorMapOrigin; //颜色图(低---高)的原点(起点);总为
short int colorMapLength; //颜色图(低---高)的长度,总为
short int colorMapEntrySize; //颜色图元素大小尺寸(低---高),总为
short int imageXOrigin; //颜色图(低---高)左下角的X坐标,总为
short int imageYOrigin; //颜色图(低---高)左下角的Y坐标,总为
short int imageWidth; //颜色图(低---高)的像素宽度
short int imageHeight; //颜色图(低---高)的像素高度
unsigned char bitCount; //位数;,24,32
unsigned char imageDescriptor; //24位=0x00,位=0x08
}TARGAFILEHEADER;
知道了文件结构,加载进去就好办了。与BMP位图有点不同的是,我们需要注意每个像素有4个字节大小,分别为BGRA.
首先我们先定义一个结构体保存TGA文件有用的数据。
typedef struct
{
unsigned char imageTypeCode;
short int imageWidth;
short int imageHeight;
unsigned char bitCount;
unsigned char *imageData;
} TGAFILE;
接下来看下读取TGA文件的图像数据的函数。
// LoadTGAFile()
// desc: loads the TGA file "filename" into the tgaFile data structure
int LoadTGAFile(char *filename, TGAFILE *tgaFile)
{
FILE *filePtr;
unsigned char ucharBad; // garbage unsigned char data
short int sintBad; // garbage short int data
long imageSize; // size of the TGA image
int colorMode; // 4 for RGBA or 3 for RGB
long imageIdx; // counter variable
unsigned char colorSwap; // swap variable
// open the TGA file
filePtr = fopen(filename, "rb");
if (!filePtr)
return 0;
// read first two bytes of garbage
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
// read in the image type
fread(&tgaFile->imageTypeCode, sizeof(unsigned char), 1, filePtr);
// for our purposes, the image type should be either a 2 (color) or a 3 (greyscale)
if ((tgaFile->imageTypeCode != 2) && (tgaFile->imageTypeCode != 3))
{
fclose(filePtr);
return 0;
}
// read 13 bytes of garbage data
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
fread(&sintBad, sizeof(short int), 1, filePtr);
// read image dimensions
fread(&tgaFile->imageWidth, sizeof(short int), 1, filePtr);
fread(&tgaFile->imageHeight, sizeof(short int), 1, filePtr);
// read image bit depth
fread(&tgaFile->bitCount, sizeof(unsigned char), 1, filePtr);
// read 1 byte of garbage data
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
// colorMode -> 3 = BGR, 4 = BGRA
colorMode = tgaFile->bitCount / 8;
imageSize = tgaFile->imageWidth * tgaFile->imageHeight * colorMode;
// allocate memory for image data
tgaFile->imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
// read in image data
fread(tgaFile->imageData, sizeof(unsigned char), imageSize, filePtr);
// change BGR to RGB so OpenGL can read the image data
for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode)
{
colorSwap = tgaFile->imageData[imageIdx];
tgaFile->imageData[imageIdx] = tgaFile->imageData[imageIdx + 2];
tgaFile->imageData[imageIdx + 2] = colorSwap;
}
// close the file
fclose(filePtr);
return 1;
}
下面看下怎么使用
typedef struct
{
unsigned char imageTypeCode;
short int imageWidth;
short int imageHeight;
unsigned char bitCount;
unsigned char *imageData;
} TGAFILE;
TGAFILE *myTGA;
myTGA = (TGAFILE*)malloc(sizeof(TGAFILE));
LoadTGAFile("test.tga", myTGA);
// draw the bitmap image
DrawBitmap(myTGA->imageWidth, myTGA->imageHeight, myTGA->imageData);
其中DrawBitmap如下:
// DrawBitmap
// desc: draws the bitmap image data in bitmapImage at the location
// (0,0) in the window. (200,200) is the lower-left corner
// of the bitmap.
void DrawBitmap(long width, long height, unsigned char* bitmapImage)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glRasterPos2i(0,0);
// 这里使用的是GL_RGB,若tga文件是位的(有alpha通道),就改为GL_RGBA
glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, bitmapImage);
}
下面的是将TGA图像数据写进文件中的函数
// saves an array of pixels as a TGA image
int WriteTGAFile(char *filename, short int width, short int height, unsigned char* imageData)
{
unsigned char byteSkip; // used to fill in the data fields that we don't care about
short int shortSkip;
unsigned char imageType; // type of image we're writing to file
int colorMode;
unsigned char colorSwap;
int imageIdx;
unsigned char bitDepth;
long imageSize;
FILE *filePtr;
// create file for writing binary mode
filePtr = fopen(filename, "wb");
if (!filePtr)
{
fclose(filePtr);
return 0;
}
imageType = 2; // RGB, uncompressed
bitDepth = 24; // 24-bitdepth
colorMode = 3; // RGB color mode
byteSkip = 0;
shortSkip = 0;
// write 2 bytes of blank data
fwrite(&byteSkip, sizeof(unsigned char), 1, filePtr);
fwrite(&byteSkip, sizeof(unsigned char), 1, filePtr);
// write imageType
fwrite(&imageType, sizeof(unsigned char), 1, filePtr);
fwrite(&shortSkip, sizeof(short int), 1, filePtr);
fwrite(&shortSkip, sizeof(short int), 1, filePtr);
fwrite(&byteSkip, sizeof(unsigned char), 1, filePtr);
fwrite(&shortSkip, sizeof(short int), 1, filePtr);
fwrite(&shortSkip, sizeof(short int), 1, filePtr);
// write image dimensions
fwrite(&width, sizeof(short int), 1, filePtr);
fwrite(&height, sizeof(short int), 1, filePtr);
fwrite(&bitDepth, sizeof(unsigned char), 1, filePtr);
// write 1 byte of blank data
fwrite(&byteSkip, sizeof(unsigned char), 1, filePtr);
// calculate the image size
imageSize = width * height * colorMode;
// change image data from RGB to BGR
for (imageIdx = 0; imageIdx < imageSize ; imageIdx += colorMode)
{
colorSwap = imageData[imageIdx];
imageData[imageIdx] = imageData[imageIdx + 2];
imageData[imageIdx + 2] = colorSwap;
}
// write the image data
fwrite(imageData, sizeof(unsigned char), imageSize, filePtr);
// close the file
fclose(filePtr);
return 1;
}