这是一段用 OpenGL 显示 BMP 位图的示例代码。程序从本地读取一张名为 1.bmp 的位图文件,解析其宽高信息,按 4 字节对齐计算像素数据长度,再把像素数据整体读入内存,最后通过 glDrawPixels 把图像绘制到 GLUT 窗口中。

实现思路

  • 用 fopen 以二进制方式打开 BMP 文件,失败时直接退出。
  • BMP 文件头中,宽度存放在偏移 0x0012,高度紧随其后,因此用 fseek 定位后连续读出 imagewidth 和 imageheight。
  • 每行像素按 4 字节对齐,计算单行长度时用 while (pixellength % 4 != 0) pixellength++; 进行补齐,再乘以高度得到像素数据总长度。
  • 申请对应大小的缓冲区,跳过 54 字节的文件头后把像素数据一次性读入 pixeldata。
  • 在 display 回调中调用 glDrawPixels,格式使用 GL_BGR_EXT,因为 BMP 文件在磁盘中的通道顺序正是 BGR。

完整代码

static GLint imagewidth;
                static GLint imageheight;
                static GLint pixellength;
                static GLubyte* pixeldata;
                
                
                void display(void)
                {
                	glClear(GL_COLOR_BUFFER_BIT);
                	//绘制像素
                	glDrawPixels(imagewidth, imageheight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixeldata);
                	glutSwapBuffers();
                }
                int main(int argc, char* argv[])
                {
                
                	FILE* pfile = fopen("1.bmp", "rb");
                	if (pfile == 0) exit(0);
                	//读取图像大小
                	fseek(pfile, 0x0012, SEEK_SET);
                	fread(&imagewidth, sizeof(imagewidth), 1, pfile);
                	fread(&imageheight, sizeof(imageheight), 1, pfile);
                	//计算像素数据长度
                	pixellength = imagewidth * 3;
                	while (pixellength % 4 != 0)pixellength++;
                	pixellength *= imageheight;
                	//读取像素数据
                	pixeldata = (GLubyte*)malloc(pixellength);
                	if (pixeldata == 0) exit(0);
                	fseek(pfile, 54, SEEK_SET);
                	fread(pixeldata, pixellength, 1, pfile);
                
                
                	fclose(pfile);
                
                
                	glutInit(&argc, argv);
                	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
                	cout << pixellength;
                	glutInitWindowSize(500, 500);
                	glutCreateWindow("显示bmp");
                	glutDisplayFunc(display);
                	glutMainLoop();
                	free(pixeldata);
                
                	return 0;
                }