qtopenglqglwidget

How to make original (0,0) coordinate to be on the top left of QGLWIdget?


I want to display an image using QGLWidget, it doesn't show in the correct way, one of the problems is the original coordinate is on the bottom left of the widget. I would like to know how to make the original coordinate to be on the top left and flip the y axis.

enter image description here

here's my code:

header

#ifndef _GLImageDisplay_H_
#define _GLImageDisplay_H_

#include "stdafx.h"

class GLImageDisplay : public QGLWidget
{
    Q_OBJECT

public:
    GLImageDisplay(QWidget *parent = 0);

    void DisplayImage(QString img);

protected:
    void initializeGL();
    void resizeGL(int w, int h);
    void paintGL();

private:
    QImage svgImage;
    GLubyte* gluImage;
};

#endif

cpp

#include "stdafx.h"
#include "GLImageDisplay.h"

GLImageDisplay::GLImageDisplay(QWidget *parent) : QGLWidget (parent) 
{
}

void GLImageDisplay::DisplayImage(QString img)
{
    svgImage.load(img);
    resize(svgImage.size());

    gluImage = new GLubyte[svgImage.height() * svgImage.width() * 3];
    for (int a = 0; a < svgImage.width(); ++a)  
    {
        for (int b = 0; b < svgImage.height(); ++b) 
        {
            QColor color = svgImage.pixel(a, b);
            gluImage[3 * (a + b * svgImage.width()) + 0] = (GLubyte) color.red();
            gluImage[3 * (a + b * svgImage.width()) + 1] = (GLubyte) color.green();
            gluImage[3 * (a + b * svgImage.width()) + 2] = (GLubyte) color.blue();
        }
    }

    this->setMinimumWidth(svgImage.width());
    this->setMinimumHeight(svgImage.height());
}

void GLImageDisplay::initializeGL() 
{
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}

void GLImageDisplay::resizeGL(int w, int h) 
{
    glViewport(0, 0, svgImage.width(), svgImage.height());

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, svgImage.width(), 0, svgImage.height(), 0, 1);   
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLImageDisplay::paintGL() 
{
    glClear(GL_COLOR_BUFFER_BIT);
    glRasterPos2i(0, 0);
    glDrawPixels(svgImage.width(), svgImage.height(), GL_RGB, GL_UNSIGNED_BYTE, gluImage);
}

Solution

  • OpenGL coordinates start at the bottom. To fix this, you can do a -1 scaling in the y axis in your projection matrix. The offset is related.

    To fix this, alter your call to glOrtho or apply a scaling + translation just after the call.

    Btw. you could also use QPainter and use beginNativePainting() wherever you really need GL. QPainter will already use GL itself and perform very well.

    glDrawPixels is a very inefficient way of drawing an image onto screen. You should rather load it into a texture and draw a quad with it. (Yet again, QPainter can do that for you, too, much more easily.)