为啥在 glfw 窗口上没有使用 opengl 显示位图图像?在 C++ 中读取位图图像文件时出现问题
Posted
技术标签:
【中文标题】为啥在 glfw 窗口上没有使用 opengl 显示位图图像?在 C++ 中读取位图图像文件时出现问题【英文标题】:Why is bitmap image not showing with opengl on glfw window? Problem reading bitmap image file in C++为什么在 glfw 窗口上没有使用 opengl 显示位图图像?在 C++ 中读取位图图像文件时出现问题 【发布时间】:2020-08-26 05:40:09 【问题描述】:#include<GLFW/glfw3.h>
#include<stdio.h>
#include<GL/glu.h>
#include<vector>
using namespace std;
typedef struct __attribute__((__packed__))
unsigned short type;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offsetbits;
BITMAPFILEHEADER1;
typedef struct __attribute__((__packed__))
unsigned long size;
unsigned long width;
unsigned long height;
unsigned short planes;
unsigned short bitcount;
unsigned long compression;
unsigned long sizeimage;
long xpelspermeter;
long ypelspermeter;
unsigned long colorsused;
unsigned long colorsimportant;
BITMAPINFOHEADER1;
typedef struct
unsigned char blue;
unsigned char green;
unsigned char red;
SINGLE_PIXEL1;
void draw_all()
FILE *fp;
unsigned char p;
int x=0,y=0,c=0;
float r,g,b;
float rowsize,pixelarraysize;
int datasize;
BITMAPFILEHEADER1 bitmp;
BITMAPINFOHEADER1 bitm;
glClearColor(1.0,1.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
fp = fopen("free.bmp","rb");//Filename is given
//fread(&bitmp,14,1,fp);
//fread(&bitm,40,1,fp);
printf("sizeheader: %d\n", sizeof(BITMAPFILEHEADER1));
fread(&bitmp,sizeof(BITMAPFILEHEADER1),1,fp);
fread(&bitm,sizeof(BITMAPINFOHEADER1),1,fp);
printf("Type in hexadecimal: %x\n",bitmp.type);
printf("Size in hexadecimal: %x\n",bitmp.size);
printf("Reserved1 in hexadecimal: %x\n",bitmp.reserved1);
printf("Reserved2 in hexadecimal: %x\n",bitmp.reserved2);
printf("Offsetbits in hexadecimal: %x\n",bitmp.offsetbits);
//printf("Width: %x, Height: %x\n",bitm.width,bitm.height);
printf("Width: %d, Height: %d\n",bitm.width,bitm.height);
printf("Bitcount: %d\n",bitm.bitcount);
glViewport(0,0,bitm.width,bitm.height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,bitm.width,0.0,bitm.height);
vector<float> v_data;
int width,height;
width=bitm.width;
height=bitm.height;
//width=800;
//height=600;
//rowsize=((24*734+31)/32)*4;
rowsize=((24*800+31)/32)*4;
//rowsize=((bitm.bitcount*bitm.width+31)/32)*4;
pixelarraysize=rowsize*bitm.height;
printf("Rowsize: %f\n",rowsize);
printf("pixelarraysize: %f\n",pixelarraysize);
//datasize=3*734;
//datasize=3*800;
//datasize=3*bitm.width;
datasize=(bitm.bitcount/8.0)*bitm.width;
printf("Datasize: %d\n",datasize);
int padding;
padding = rowsize - (width * 3);
//glBegin(GL_POINTS);
while(!feof(fp))
fread(&p,1,1,fp);
b = p/255.0;
fread(&p,1,1,fp);
g = p/255.0;
fread(&p,1,1,fp);
r = p/255.0;
v_data.push_back(r);
v_data.push_back(g);
v_data.push_back(b);
/*
glColor3f(r,g,b);
glVertex2i(x++,y);
*/
x++;
if(x == bitm.width)
//fseek(fp,2,SEEK_CUR);
fseek(fp,padding,SEEK_CUR);
x = 0;
y++;
//glEnd();
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,width,height,0,GL_RGB,GL_FLOAT,&v_data[0]);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE);
glBegin(GL_QUADS);
glTexCoord2i(0,0);
glVertex2i(0,0);
glTexCoord2i(0,1);
glVertex2i(0,height);
glTexCoord2i(1,1);
glVertex2i(width,height);
glTexCoord2i(1,0);
glVertex2i(width,0);
glEnd();
glFlush();
fclose(fp);
int main(void)
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
glfwTerminate();
return -1;
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
draw_all();
while (!glfwWindowShouldClose(window))
//gladLoadGL();
/* Render here */
//draw_all();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
glfwTerminate();
return 0;
g++ glfw.cpp -o glfw -lglfw -lGL -lGLU
./glfw
谁能解决读取位图文件(free.bmp)的问题?它没有得到图像的宽度和高度。
【问题讨论】:
【参考方案1】:rowsize
的计算肯定是错误的。一行中的行数对齐为4:
rowsize=((24*64+31)/32)*4;
rowsize = (bitm.width*3*4+3)/4;
我建议使用STB library
来加载位图。在How to load a bmp on GLUT to use it as a texture?问题的答案中可以找到不同的解决方案。
无论如何,没有必要将纹理图像转换为浮动品脱数据。纹理可以直接加载:
vector<unsigned char> v_data(pixelarraysize);
fread(v_data.data(), 1, pixelarraysize, fp);
// [...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, &v_data[0]);
不要每帧连续加载纹理。在应用循环之前加载一次纹理:
int width, height;
unsigned int load_texture(const char *filename)
FILE *fp;
float rowsize,pixelarraysize;
BITMAPFILEHEADER1 bitmp;
BITMAPINFOHEADER1 bitm;
fp = fopen(filename,"rb");//Filename is given
printf("sizeheader: %d\n", sizeof(BITMAPFILEHEADER1));
fread(&bitmp,sizeof(BITMAPFILEHEADER1),1,fp);
fread(&bitm,sizeof(BITMAPINFOHEADER1),1,fp);
printf("Type in hexadecimal: %x\n",bitmp.type);
printf("Size in hexadecimal: %x\n",bitmp.size);
printf("Reserved1 in hexadecimal: %x\n",bitmp.reserved1);
printf("Reserved2 in hexadecimal: %x\n",bitmp.reserved2);
printf("Offsetbits in hexadecimal: %x\n",bitmp.offsetbits);
printf("Width: %d, Height: %d\n",bitm.width,bitm.height);
printf("Bitcount: %d\n",bitm.bitcount);
rowsize = (bitm.width*3*4+3)/4;
pixelarraysize = rowsize*bitm.height;
printf("Rowsize: %f\n",rowsize);
printf("pixelarraysize: %f\n",pixelarraysize);
vector<unsigned char> v_data(pixelarraysize);
fread(v_data.data(), 1, pixelarraysize, fp);
fclose(fp);
width = bitm.width;
height = bitm.height;
unsigned int texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, &v_data[0]);
return texture;
void draw_all()
glClearColor(1.0,1.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0,0,640, 480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,640,0.0,480);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2i(0,0);
glVertex2i(0,0);
glTexCoord2i(0,1);
glVertex2i(0,height);
glTexCoord2i(1,1);
glVertex2i(width,height);
glTexCoord2i(1,0);
glVertex2i(width,0);
glEnd();
glFlush();
int main(void)
// [...]
int textureobject = load_texture("free.bmp");
while (!glfwWindowShouldClose(window))
/* Render here */
draw_all();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
// [...]
【讨论】:
以上是关于为啥在 glfw 窗口上没有使用 opengl 显示位图图像?在 C++ 中读取位图图像文件时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 GLFW 窗口中使用此代码在我的屏幕上没有绘制立方体?