c++ - opengl - 显示的图像剪切
问题描述
我正在尝试使用 OpenGL 来显示 MicrosoftCImage
库从磁盘读取的图像。
现在可以在窗口中大致看到图像,但显然有问题。图像是灰色的,并且被剪切了。我无法弄清楚问题出在哪里,因为每个像素都应该对应于_data
.
OpenGL图像:
原图:
下面是我的代码:
int _w = 300;
int _h = 300;
GLubyte ***_data;
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, _w, 0.0, _h);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glRasterPos2i(0, 0);
glDrawPixels(_w, _h, GL_RGB,
GL_UNSIGNED_BYTE, _data);
glFlush();
}
int main(int argc, char** argv) {
CImage img_handler;
img_handler.Load(_T("bg.jpg"));
_w = img_handler.GetWidth();
_h = img_handler.GetHeight();
COLORREF pixel;
_data = new GLubyte**[_h];
for (int y = 0; y < _h; y++) {
_data[_h-y-1] = new GLubyte*[_w];
for (int x = 0; x < _w; x++) {
pixel = img_handler.GetPixel(x, y);
_data[_h-y-1][x] = new GLubyte[3];
_data[_h-y][x][0] = (GLubyte)GetRValue(pixel);
_data[_h-y][x][1] = (GLubyte)GetGValue(pixel);
_data[_h-y][x][2] = (GLubyte)GetBValue(pixel);
}
}
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH/*enable depth buffer*/);
glutInitWindowSize(_w, _h);
glutCreateWindow("test");
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
解决方案
根据glDrawPixels 上的这个 OpenGL 文档(强调添加):
宽度 x 高度像素从内存中读取,从位置数据开始。默认情况下,这些像素取自相邻的内存位置,除了在读取所有宽度像素之后,读取指针前进到下一个四字节边界。四字节的行对齐由 glPixelStore 用参数 GL_UNPACK_ALIGNMENT 指定,它可以设置为一、二、四或八字节。
请注意,您的颜色被定义为 3 个GLuint
值 - 只有 3 个字节!每行像素包含3 * 897 = 2691
字节。之后的下一个4的倍数2691
是2692
这样glDrawPixels
定义的,GL在每一行之后跳过一个字节。这就是为什么图像被剪切并且它看起来是灰色的原因(如果你放大,你会看到它不是灰色的,而是每隔三行都有正确的颜色,并且中间的颜色偏移了 120 度)。
解决此问题的方法是在glPixelStore
通话之前glDrawPixels
拨打电话。改变就足够了
glDrawPixels(_w, _h, GL_RGB,
GL_UNSIGNED_BYTE, _data);
至
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glDrawPixels(_w, _h, GL_RGB,
GL_UNSIGNED_BYTE, _data);
此外,for
循环内的代码不正确。 _h-y
应该是_h-y-1
这样,当y=0
您不写入数组边界之外时,以及当y=_h-1
您写入0
数组的第 th 索引时也是如此。
另外,请查看动态内存分配,而不是分配静态大小的数组。这将使您的代码不太容易出现访问冲突,即读取/写入实际上不属于您的内存,从而导致崩溃和其他问题。
推荐阅读
- macos - 如何在 macOS 上使用 Lazarus 播放 MP3 文件
- kubernetes - 无法使用 kubeadm init 单个 kubernetes 集群
- makefile - Makefile:假设文件对于特定目标是最新的?
- node.js - Node/Typescript 对象可能为 null 项目不会构建
- c - 使用define将结构成员分配给同一结构的另一个成员
- android - 有没有办法检查应用程序是否被重新安装?
- asp.net-mvc - 如何从控制器调用 SQL 函数
- c - 我的 shell 无法阻止 ctrl+c 杀死自己
- python-3.x - Python为每组多级索引选择不同的行数
- powershell - 在要执行的 PowerShell 脚本中提供凭据