Render QImage with OpenGL
Asked Answered
R

2

7

Related to my other question, I think the more central question would be, how you render a QImage with OpenGL?

I think the code has to look something like this, but I'm not sure what else I need, besides maybe convertToGLFormat(img).

glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glGenTextures(1, &offscreenBufferTexture);
glBindTexture(GL_TEXTURE_2D, offscreenBufferTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgGL.width(),
         imgGL.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
         imgGL.bits());

glBegin(GL_QUADS);
  glTexCoord2d(0,0); glVertex2d(0, 0);
  glTexCoord2d(1,0); glVertex2d(windowSize.width(), 0);
  glTexCoord2d(1,1); glVertex2d(windowSize.width(), windowSize.height());
  glTexCoord2d(0,1); glVertex2d(0, windowSize.height());
glEnd();
glDisable(GL_TEXTURE_2D);

Also, I thought quick and dirty you could use glDrawPixels() (although you shouldn't), like

glDrawPixels(imgGL.width(), imgGL.height(), GL_RGBA,
         GL_UNSIGNED_BYTE, imgGL.bits());

But either way I can't see the image, just a white square with the size of it. I'm missing something here.

Reinold answered 27/11, 2013 at 15:3 Comment(2)
Have you confirmed that imgGL has the same format as GL_RGBA/GL_UNSIGNED_BYTE?Seditious
Yes, because I create the QImage from the SoOffscreenRenderer buffer that uses GL_UNSIGNED_BYTE and where I can set if it uses RGB or RGBA. I tried both versions, but it won't display either way.Reinold
R
4

I managed to draw a QImage with OpenGL from a picture source, but not from the SoOffscreenRenderer as described here.

void init(){
    loadTexture2("kitten.png", backgroundimage);
}

QImage loadTexture2(char *filename, GLuint &textureID){
    glEnable(GL_TEXTURE_2D); // Enable texturing

    glGenTextures(1, &textureID); // Obtain an id for the texture
    glBindTexture(GL_TEXTURE_2D, textureID); // Set as the current texture

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    QImage im(filename);
    QImage tex = QGLWidget::convertToGLFormat(im);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

    glDisable(GL_TEXTURE_2D);

    return tex;
}

void renderSceneGL2(){
    glClearColor(0.4f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, backgroundimage);

    glBegin(GL_QUADS);
        glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
        glTexCoord2f(1,0); glVertex3f(1, -1, -1);
        glTexCoord2f(1,1); glVertex3f(1, 1, -1);
        glTexCoord2f(0,1); glVertex3f(-1, 1, -1);

    glEnd();

    glDisable(GL_TEXTURE_2D);
}

Also QGLWidget::convertToGLFormat throws random Access violation errors from time to time.

Reinold answered 6/12, 2013 at 14:1 Comment(0)
S
3

Nowadays, with Qt 5.11, the easiest way is to use QOpenGLWidget and override its paintEvent method.

In the following code OpenGLWidget inherite from QOpenGLWidget, and display(const QImage& img) is a slot triggered whenever I need to update the image.

No matter how many times display() is called between two OpenGL rendering, the update() call doesn't trig rendering directly, it just marks widget dirty for redrawing on next loop.

This method is actually pretty fast, I'm using it to display camera frames at 240fps (although not all frames are displayed on screen).

void OpenGLWidget::display(const QImage& img)
{
  image = img;
  this->update();
}

void OpenGLWidget::paintEvent(QPaintEvent*)
{
  QPainter painter(this);
  painter.drawImage(this->rect(),image);
}
Sherman answered 3/8, 2018 at 6:24 Comment(3)
Thanks. If i have a video wall, let's say 3 by 3, should every video wall camera image holder be a QOpenGLWidget(now they are qwidgets with qlabels and work really slow). Or, should just the wall itself be a QOpenGLWidget? or they both have to be? Shall I make the main window also a QOpenGlWidget? Where can I read about these topics (children and parents between QOpenglWidget and QWidget)? Best regards! Mat.Rubidium
heh, I don't think you wanted me to look at movidious )Rubidium
video wall is not related in any way to QOpenGLWidget. The way you should setup your device (with only one OpenGL for all parts, or one openGL window per part) depends on many things (at first your OS and graphic card). Concerning your last question, you will find the Qt5 documentation here : doc.qt.io/qt-5.11. It's worth reading itSherman

© 2022 - 2024 — McMap. All rights reserved.