opengl-剪切后的显示图像

时间:2019-01-13 03:50:12

标签: c++ opengl

我正在尝试使用OpenGL显示Microsoft CImage库从磁盘读取的图像。

现在可以在窗口中大致看到该图像,但显然有问题。图像是灰色的,并且被剪切了。我不知道问题出在哪里,因为每个像素都应与其在_data中的位置相对应。

OpenGL图片: opengl image

原始图片: original image

下面是我的代码:

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;
}

1 个答案:

答案 0 :(得分:4)

根据glDrawPixels上的this OpenGL doc(添加了强调):

  从位置数据开始,从存储器读取

宽x高像素。默认情况下,这些像素取自相邻的内存位置,除非在读取所有宽度像素之后,读取指针前进到下一个四字节边界。 glPixelStore使用参数GL_UNPACK_ALIGNMENT指定四字节的行对齐方式,可以将其设置为一个,两个,四个或八个字节。

请注意,您的颜色定义为3个GLuint值-仅3个字节!每行像素包含3 * 897 = 2691个字节。 2691之后的下一个4的倍数是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个索引数组。

此外,请查看动态内存分配,而不是分配静态大小的数组。这将使您的代码不太容易发生访问冲突,即读/写实际上并不属于您的内存,从而导致崩溃和其他问题。