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

来源:互联网 发布:网络理财哪里做得好 编辑:程序博客网 时间:2024/06/07 12:19

在缺省情况下,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{GLbyteidentsize;              // Size of ID field that follows header (0)GLbytecolorMapType;           // 0 = None, 1 = palettedGLbyteimageType;              // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rleunsigned shortcolorMapStart;          // First colour map entryunsigned shortcolorMapLength;         // Number of colorsunsigned char colorMapBits;   // bits per palette entryunsigned shortxstart;                 // image x originunsigned shortystart;                 // image y originunsigned shortwidth;                  // width in pixelsunsigned shortheight;                 // height in pixelsGLbytebits;                   // bits per pixel (8 16, 24, 32)GLbytedescriptor;             // image descriptor} TGAHEADER;#pragma pack()

GLubyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat){FILE *pFile;// File pointerTGAHEADER tgaHeader;// TGA file headerunsigned long lImageSize;// Size in bytes of imageshort 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 filfopen_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 bufferlImageSize = tgaHeader.width * tgaHeader.height * sDepth;// Allocate memory and check for successpBits = (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 recognizeif (fread(pBits, lImageSize, 1, pFile) != 1){free(pBits);return NULL;}// Set OpenGL format expectedswitch (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 Filefclose(pFile);// Return pointer to image datareturn pBits;}

#pragma pack未定义导致TGAHEADER的读数错误
-tgaHeader{identsize=0 '\0' colorMapType=0 '\0' imageType=2 '\x2' ...}TGAHEADERidentsize0 '\0'charcolorMapType0 '\0'charimageType2 '\x2'charcolorMapStart0unsigned short //双字节对齐边界. 其偏移地址为4。第四个字节被舍弃colorMapLength0unsigned shortcolorMapBits0 '\0'unsigned charxstart0unsigned shortystart1024unsigned shortwidth1024unsigned shortheight24unsigned shortbits-116 '?'chardescriptor117 'u'char

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

 00 00 02 00 00 00 00 00 00 00 00 00 00 04 00 04 18 00


0 0
原创粉丝点击