TGA图像头文件拾取的字节对齐及#pragma pack的使用
2017-04-29 14:58
387 查看
在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。
在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。
例1:
在学习OpenGL蓝宝书的例子中,由于漏掉了gltLoadTGA函数头文件中#pragma pack的定义,导致图像数据头参数错误,OpenGL不能正常显示。
改变缺省的对界条件(指定对界)
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。
#pragma pack未定义导致TGAHEADER的读数错误
body.tga中18个字节的文件头
00 00 02 00 00 00 00 00 00 00 00 00 00 04 00 04 18 00
在结构中,编译器为结构的每个成员按其自然对界(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
相关文章推荐
- struct和 union用 sizeof 看字节对齐,以及__declspec( align( # ) ) 和 #pragma pack()的使用方式
- C语言sizeof空洞之字节对齐(#pragma pack使用)
- C语言的字节对齐及#pragma pack的使用
- C语言的字节对齐及#pragma pack的使用
- C语言的字节对齐及#pragma pack的使用
- 转载:C语言的字节对齐及#pragma pack的使用
- C语言的字节对齐及#pragma pack的使用
- C语言的字节对齐及#pragma pack的使用
- (经典)struct和 union用 sizeof 看字节对齐,以及__declspec( align( # ) ) 和 #pragma pack()的使用方式
- stm32中使用#pragma pack(非常有用的字节对齐用法说明)
- C语言的字节对齐及#pragma pack的使用
- C语言的字节对齐以及#pragma pack的使用
- C语言的字节对齐及#pragma pack的使用
- 关于sizeof与#pragma pack 以及网络上关于字节对齐的一点感想
- 字节对齐 #pragma pack(n)
- #pragma pack(1) 的用法 强制单字节对齐
- #pragma pack 字节对齐预编译指令说明
- 关于pragma pack的用法 字节对齐
- 字节对齐 pragma pack
- pragma pack(非常有用的字节对齐用法说明)