OpenGL加载与显示Targa位图文件

这种图像格式在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;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值