Uncompressed TGAs

本文介绍如何利用TGA文件格式的内置Alpha通道来创建透明效果,通过加载和处理TGA文件,实现比传统遮罩更为简便的图像合成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

Uncompressed TGAsIn the previous tutorial, we used 2 images to create transparency. This was achieved with blending and is known as masking.

This tutorial will explain how to create the same effect but instead this time we will be using a different technique. This tutorial will use targa images. These images have a .tga extension.

TGA file has a built in alpha layer. This image essentially contains the mask as part of the image. We therefore only need 1 image file instead of 2.

There are a number of types of TGA files. They can either contain only red green and blue values or they can contain red, green and blue values along with an additional alpha value. Black and white TGAs can also be created. The TGA can also be either compressed or uncompressed. This allows a number of different types. We will only be discussing uncompressed TGAs in this tutorial as they are far easier to load.

This tutorial is a modified version of the previous tutorial. You may also want to review the Texture Mapping tutorial as a lot of the bitmap loading code is reused here.

Contents of main.cpp :


We will be loading 2 textures. These will be the background and checker images. The backgroud image contains no alpha layer and the checker pattern does.

GLuint texture[2];

char *tgas[] = {
	"zeus.tga",
	"rockchecker.tga"
};

There is no standard structure to store a TGA file like there is for a bitmap file. We therefore create our own structure to contain the information we desire.

struct TGAFile
{

The typeCode will hold whether the image has an alpha layer and if the image is compressed or not.

	unsigned char typeCode;

We will also need to store the width, height and bits per pixel for the image.

	short int width;
	short int height;
	unsigned char bpp;

When setting up the texture, we need to know whether the image has an alpha layer. This will be stored in the format variable and can have a value of either GL_RGB orGL_RGBA.

	GLenum format;

Lastly we need to store the actual image data.

	unsigned char *imageData;
};

The next step is to load a TGA and to store the data in the structure declared above.

Before we can load a TGA image, we need to understand the structure of it. A TGA file has the following data :

unsigned char idLength;
unsigned char colorMapType;
unsigned char imageType;
short int colorMapOrigin;
short int colorMapLength;
unsigned char colorMapEntrySize;
short int originX;
short int originY;
short int width;
short int height;
unsigned char bits;
unsigned char descriptor;

Each one of these will be discussed as we are loading the file.

bool loadUncompressedTGA(char *filename, TGAFile *tgaFile)
{

We need to create a pointer to a FILE structure to point to the TGA file.

	FILE *file;

We also need a temporary variable to hold an unsigned char because like the bitmap, the color values are represented in a blue-green-red order instead of a red-green-blue order.

	unsigned char tmpRGB;

We do not need all of the data in a TGA file. The individual elements of a TGA file are made up of both unsigned char and unsigned short values. We create 2 temporary variables of these types to discard certain values.

	unsigned char ucNull;
	unsigned short usNull;

This sneaky code that I came up with will add the current directory onto the filename. It has not changed since the Texture Mapping tutorial.

	TCHAR path[256];
	char fullPath[256];
	GetModuleFileName(NULL, path, 256);

	TCHAR *pos = wcsrchr(path, '\\');
	*(pos + 1) = '\0';
	
	wcstombs(fullPath, path, 256);
	
	strcat(fullPath, filename);

	file = fopen(fullPath,"rb");

	if (!file)
	{
		MessageBox(NULL, L"Can't Find TGA", L"Error", MB_OK);
		return false;
	}

The idLength variable specifies the number of characters in the identification field. A 0specifies that no identification field is included. The colorMapType specifies the type of color map and this is always 0. Neither of these variables are particularly useful, so we simply discard them by reading them into the ucNull variable.

	fread(&ucNull,sizeof(unsigned char),1,file);
	fread(&ucNull,sizeof(unsigned char),1,file);

The imageType variable is very important. This specifies what type of TGA is being processed. The possible values are shown in the table below :

imageType Description
2 Uncompressed RGB Image
3 Uncompressed Black and White Image
10 Run-length Encoded RGB Image
11 Compressed Black and White Image

We want to store this value in our TGAFile structure.

	fread(&tgaFile->typeCode,sizeof(unsigned char),1,file);

We make sure that an uncompressed TGA is being loaded and display an error if not.

	if (tgaFile->typeCode != 2 && tgaFile->typeCode != 3)
	{
		MessageBox(NULL, L"Incorrect texture type", L"Error", MB_OK);
		fclose(file);
		return false;
	}

The colorMapOrigin value is always 0 as well as the colorMapLength andcolorMapEntrySize variables. We want to simply discard these values.

	fread(&usNull,sizeof(unsigned short),1,file);
	fread(&usNull,sizeof(unsigned short),1,file);
	fread(&ucNull,sizeof(unsigned char),1,file);

The originX and originY values specify the lower-left coordinate of the image. This is always (0,0). Once again this is of no use to us, so we discard them.

	fread(&usNull,sizeof(unsigned short),1,file);
	fread(&usNull,sizeof(unsigned short),1,file);

The widthheight and bits per pixel is extremely important, so we load those into ourTGAFile structure.

	fread(&tgaFile->width, sizeof(unsigned short), 1, file);
	fread(&tgaFile->height, sizeof(unsigned short), 1, file);
	fread(&tgaFile->bpp, sizeof(unsigned char), 1, file);

The descriptor specifies whether the image is a 24 bit(0x00) or 32 bit(0x08) image. We could use this for our format variable or we can use the method that will be discussed shortly. As we are using a different method, we will discard this variable.

	fread(&ucNull,sizeof(unsigned char),1,file);

As we are dealing with variables of sizes in bytes and not bits, it is more convenient to convert the bits per pixel to bytes per pixel. This is a simple division by 8.

	int colorMode = tgaFile->bpp / 8;

If there is an extra byte for the alpha layer, we set the format variable to GL_RGBA. If not, we use the standard GL_RGB flag.

	if (colorMode == 3)
		tgaFile->format = GL_RGB;
	else
		tgaFile->format = GL_RGBA;

The next step is to allocate enough memory for all pixels of the image. We multiply the number of pixels by the number of bytes per pixel to get the total image size in bytes.

	long imageSize = tgaFile->width * tgaFile->height * colorMode;

	tgaFile->imageData = new unsigned char[imageSize];

	if (!tgaFile->imageData)
	{
		MessageBox(NULL, L"Out of Memory", L"Error", MB_OK);
		delete[] tgaFile->imageData;
		fclose(file);
		return false;
	}

The image data follows the TGA header. Now that we have allocated the memory, we can load the image data.

	fread(tgaFile->imageData,sizeof(unsigned char),imageSize,file);

	if (!tgaFile->imageData)
	{
		MessageBox(NULL, L"Error reading TGA", L"Error", MB_OK);
		fclose(file);
		return false;
	}

Like the bitmap, we need to swap all red and blue values to get the standard RGB order.

	for (int i = 0; i < imageSize; i += colorMode)
	{
		tmpRGB = tgaFile->imageData[i];
		tgaFile->imageData[i] = tgaFile->imageData[i+2];
		tgaFile->imageData[i+2] = tmpRGB;
	}

	fclose(file);

	return true;
}

Now that we have the ability to load our TGA, we can use OpenGL ES to generate our texture. The beginning of our loadTextures function remains the same. One difference is the TGAFile structure that is created to hold our TGA.

bool loadTextures()
{
	TGAFile tgaFile;

	glGenTextures(2, texture);

	for (int i = 0; i < 2; i++)
	{

Our new function is now called.

		if (!loadUncompressedTGA(tgas[i], &tgaFile))
			return false;

		glBindTexture(GL_TEXTURE_2D, texture[i]);

The same data is passed onto the glTexImage2D, except now the data from theTGAFile structure is used. This generic method will allow the use of RGB and RGBAimages.

		glTexImage2D(GL_TEXTURE_2D, 0, tgaFile.format, tgaFile.width,
			tgaFile.height, 0, tgaFile.format, GL_UNSIGNED_BYTE,
			tgaFile.imageData);

		glTexParameterf(GL_TEXTURE_2D, 
			GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D,
			GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		delete[] tgaFile.imageData;
	}

	return true;
}

An advantage of using TGA files is that you do not need to disable depth testing. The only differences in the init is to enable blending and to set the blending function.

The blending function is set to (GL_SRC_ALPHAGL_ONE_MINUS_SRC_ALPHA). This is our standard blending function for transparency.

bool init()
{
	.
	.
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
	return true;
}

Our display function now only needs to render the textures normally without worrying about any extra blending or masking.

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glTranslatef(0.0f, 0.0f, -2.0f);

	glTexCoordPointer(2, GL_FLOAT, 0, bgTexCoords);
	glBindTexture(GL_TEXTURE_2D, texture[0]);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	glTexCoordPointer(2, GL_FLOAT, 0, checkerCoords);
	glBindTexture(GL_TEXTURE_2D, texture[1]);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	glFlush();
	glutSwapBuffers();
}

Congratulations. You can now create transparency effects using TGA files. You now also have the ability to load TGA files. You may agree that this is a much easier method than having separate image files for masking.

Please let me know of any comments you may have : Contact Me

GLUT|ES Source Files :Embedded Visual C++ 4.0 
UG Source Files :
内容概要:本文围绕直流微电网中带有恒功率负载(CPL)的DC/DC升压转换器的稳定控制问题展开研究,提出了一种复合预设性能控制策略。首先,通过精确反馈线性化技术将非线性不确定的DC转换器系统转化为Brunovsky标准型,然后利用非线性扰动观测器评估负载功率的动态变化和输出电压的调节精度。基于反步设计方法,设计了具有预设性能的复合非线性控制器,确保输出电压跟踪误差始终在预定义误差范围内。文章还对比了多种DC/DC转换器控制技术如脉冲调整技术、反馈线性化、滑模控制(SMC)、主动阻尼法和基于无源性的控制,并分析了它们的优缺点。最后,通过数值仿真验证了所提控制器的有效性和优越性。 适合人群:从事电力电子、自动控制领域研究的学者和工程师,以及对先进控制算法感兴趣的研究生及以上学历人员。 使用场景及目标:①适用于需要精确控制输出电压并处理恒功率负载的应用场景;②旨在实现快速稳定的电压跟踪,同时保证系统的鲁棒性和抗干扰能力;③为DC微电网中的功率转换系统提供兼顾瞬态性能和稳态精度的解决方案。 其他说明:文中不仅提供了详细的理论推导和算法实现,还通过Python代码演示了控制策略的具体实现过程,便于读者理解和实践。此外,文章还讨论了不同控制方法的特点和适用范围,为实际工程项目提供了有价值的参考。
内容概要:该论文介绍了一种名为偏振敏感强度衍射断层扫描(PS-IDT)的新型无参考三维偏振敏感计算成像技术。PS-IDT通过多角度圆偏振光照射样品,利用矢量多层光束传播模型(MSBP)和梯度下降算法迭代重建样品的三维各向异性分布。该技术无需干涉参考光或机械扫描,能够处理多重散射样品,并通过强度测量实现3D成像。文中展示了对马铃薯淀粉颗粒和缓步类动物等样品的成功成像实验,并提供了Python代码实现,包括系统初始化、前向传播、多层传播、重建算法以及数字体模验证等模块。 适用人群:具备一定光学成像和编程基础的研究人员,尤其是从事生物医学成像、材料科学成像领域的科研工作者。 使用场景及目标:①研究复杂散射样品(如生物组织、复合材料)的三维各向异性结构;②开发新型偏振敏感成像系统,提高成像分辨率和对比度;③验证和优化计算成像算法,应用于实际样品的高精度成像。 其他说明:PS-IDT技术相比传统偏振成像方法具有明显优势,如无需干涉装置、无需机械扫描、可处理多重散射等。然而,该技术也面临计算复杂度高、需要多角度数据采集等挑战。文中还提出了改进方向,如采用更高数值孔径(NA)物镜、引入深度学习超分辨率技术等,以进一步提升成像质量和效率。此外,文中提供的Python代码框架为研究人员提供了实用的工具,便于理解和应用该技术。
内容概要:本文详细介绍了机械运转振动数据分析与处理的方法,重点研究了转子试验台、齿轮箱和滚动轴承的振动数据。文章涵盖了频谱分析、时域和频域特征计算,以及常见故障(如不平衡、不对中、齿轮啮合故障、轴承内外圈故障)的诊断方法。文中还探讨了采样频率和采样点的设置原则、全周期采样机制,并扩展了多种信号分析方法(如频谱细化、希尔伯特包络谱分析、经验模态分解、小波变换)和人工智能方法(如卷积神经网络)的应用。通过详细的代码实现,展示了从数据加载与预处理到基于CNN的故障诊断的完整流程。 适合人群:具备一定机械工程和编程基础,从事机械设备维护、故障诊断的研究人员和技术人员。 使用场景及目标:①通过频谱分析、时域和频域特征计算,识别机械设备的常见故障;②利用包络分析、小波变换等高级信号处理方法,检测早期故障;③结合深度学习方法,实现自动化故障分类和诊断。 阅读建议:本文不仅提供了理论分析,还包含了大量可运行的Python代码示例。读者应在实践中结合这些代码,进行数据处理和模型训练,以便更好地理解和掌握各种故障诊断方法。此外,建议读者根据具体的设备和应用场景,灵活选择和组合不同的分析方法,以提高故障诊断的准确性和可靠性。
内容概要:本文详细描述了一个基于论文“具有批处理到达的服务器群的优先级排队”的服务器群模拟系统的实现。系统采用离散事件仿真方法,通过Python代码实现,涵盖作业到达、优先级队列管理、作业完成处理、合并器工作机制以及响应时间计算等功能。模拟系统支持随机模式和轨迹驱动模式,能够生成详细的运行日志和性能统计,如平均响应时间、服务器利用率等。此外,还实现了设计问题优化,通过多次重复运行和置信区间分析来确定最优的优先级阈值h,以最小化平均响应时间。最后,系统能够按照要求的格式生成输出文件,包括平均响应时间文件、子作业离开时间文件和作业完成时间文件。 适合人群:计算机科学及相关领域的研究人员、研究生以及从事分布式系统、排队论研究的专业人士。 使用场景及目标:①研究服务器群系统中不同参数(如优先级阈值h)对系统性能的影响;②分析批处理到达模式下的作业调度策略;③评估不同配置下的系统响应时间和服务器利用率;④提供一个可扩展的平台,用于进一步的研究和开发。 其他说明:本文不仅提供了完整的代码实现,还深入探讨了关键机制的设计原理和实现细节,如优先级队列处理、合并器逻辑、事件处理流程等。通过阅读本文,读者不仅可以理解服务器群模拟系统的运作原理,还能掌握如何应用离散事件仿真方法解决实际问题。此外,本文还强调了统计可靠性和性能优化的重要性,为后续研究提供了坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值