您的位置:首页 > 运维架构

TGA图像头文件拾取的字节对齐及#pragma pack的使用

2017-04-29 14:58 387 查看
在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。

在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。

例1:

struct Test
{
char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0

char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1

float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4

char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8
};


在学习OpenGL蓝宝书的例子中,由于漏掉了gltLoadTGA函数头文件中#pragma pack的定义,导致图像数据头参数错误,OpenGL不能正常显示。

改变缺省的对界条件(指定对界)

· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。

· 使用伪指令#pragma pack (),取消自定义字节对齐方式。


#pragma pack(1)
typedef struct
{
GLbyte	identsize;              // Size of ID field that follows header (0)
GLbyte	colorMapType;           // 0 = None, 1 = paletted
GLbyte	imageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle
unsigned short	colorMapStart;          // First colour map entry
unsigned short	colorMapLength;         // Number of colors
unsigned char 	colorMapBits;   // bits per palette entry
unsigned short	xstart;                 // image x origin
unsigned short	ystart;                 // image y origin
unsigned short	width;                  // width in pixels
unsigned short	height;                 // height in pixels
GLbyte	bits;                   // bits per pixel (8 16, 24, 32)
GLbyte	descriptor;             // image descriptor
} TGAHEADER;
#pragma pack()


GLubyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat)
{
FILE *pFile;			// File pointer
TGAHEADER tgaHeader;		// TGA file header
unsigned long lImageSize;		// Size in bytes of image
short sDepth;			// Pixel depth;
GLubyte	*pBits = NULL;          // Pointer to bits

// Default/Failed values
*iWidth = 0;
*iHeight = 0;
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;

// Attempt to open the fil
fopen_s(&pFile,szFileName, "rb");
if (pFile == NULL)
return NULL;

// Read in header (binary)
fread(&tgaHeader, sizeof(TGAHEADER), 1, pFile);

// Do byte swap for big vs little endian
#ifdef __APPLE__
LITTLE_ENDIAN_WORD(&tgaHeader.colorMapStart);
LITTLE_ENDIAN_WORD(&tgaHeader.colorMapLength);
LITTLE_ENDIAN_WORD(&tgaHeader.xstart);
LITTLE_ENDIAN_WORD(&tgaHeader.ystart);
LITTLE_ENDIAN_WORD(&tgaHeader.width);
LITTLE_ENDIAN_WORD(&tgaHeader.height);
#endif

// Get width, height, and depth of texture
*iWidth = tgaHeader.width;
*iHeight = tgaHeader.height;
sDepth = tgaHeader.bits / 8;

// Put some validity checks here. Very simply, I only understand
// or care about 8, 24, or 32 bit targa's.
if (tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32)
return NULL;

// Calculate size of image buffer
lImageSize = tgaHeader.width * tgaHeader.height * sDepth;

// Allocate memory and check for success
pBits = (GLubyte*)malloc(lImageSize * sizeof(GLubyte));
if (pBits == NULL)
return NULL;

// Read in the bits
// Check for read error. This should catch RLE or other
// weird formats that I don't want to recognize
if (fread(pBits, lImageSize, 1, pFile) != 1)
{
free(pBits);
return NULL;
}

// Set OpenGL format expected
switch (sDepth)
{
case 3:     // Most likely case
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;
break;
case 4:
*eFormat = GL_BGRA_EXT;
*iComponents = GL_RGBA8;
break;
case 1:
*eFormat = GL_LUMINANCE;
*iComponents = GL_LUMINANCE8;
break;
};

// Done with File
fclose(pFile);

// Return pointer to image data
return pBits;
}


#pragma pack未定义导致TGAHEADER的读数错误
-	tgaHeader	{identsize=0 '\0' colorMapType=0 '\0' imageType=2 '\x2' ...}	TGAHEADER
identsize	0 '\0'	char
colorMapType	0 '\0'	char
imageType	2 '\x2'	char
colorMapStart	0	unsigned short //双字节对齐边界. 其偏移地址为4。第四个字节被舍弃
colorMapLength	0	unsigned short
colorMapBits	0 '\0'	unsigned char
xstart	0	unsigned short
ystart	1024	unsigned short
width	1024	unsigned short
height	24	unsigned short
bits	-116 '?'	char
descriptor	117 'u'	char


body.tga中18个字节的文件头

 00 00 02 00 00 00 00 00 00 00 00 00 00 04 00 04 18 00
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opengl loadimage tga