如何使原始(0,0)坐标位于QGLWIdget的左上角?

时间:2013-07-19 21:33:03

标签: qt opengl qglwidget

我想使用QGLWidget显示图像,它没有以正确的方式显示,其中一个问题是原始坐标位于窗口小部件的左下角。 我想知道如何使原始坐标位于左上角并翻转y轴。

enter image description here

这是我的代码:

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

2 个答案:

答案 0 :(得分:3)

OpenGL坐标从底部开始。要解决此问题,您可以在投影矩阵的y轴上进行-1缩放。偏移是相关的。

要解决此问题,请在通话结束后更改您对glOrtho的通话或应用缩放+翻译。

顺便说一下。你也可以使用QPainter并在你真正需要GL的地方使用beginNativePainting()QPainter已经使用了GL本身,并且非常

glDrawPixels是将图像绘制到屏幕上的非常低效的方式。您应该将其加载到纹理中并使用它绘制四边形。 (再次,QPainter也可以为你做到这一点,更容易。)

答案 1 :(得分:2)

谢谢ypnos

最后我翻转投影矩阵gluOrtho2D(0,宽度,高度,0); 并翻转文本坐标。

这是我的代码:

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

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

void GLImageDisplay::DisplayImage(QString img)
{
    myImage.load(img);

    // calculating power-of-two (pow) size
    int xpow = (int) std::pow(2.0, std::ceil(  std::log10((double)myImage.width())/std::log10(2.0)  )   );
    int ypow = (int) std::pow(2.0, std::ceil(  std::log10((double)myImage.height())/std::log10(2.0)  )   );

    // the texture should be square too
    xpow = std::max(xpow, ypow);
    ypow = xpow;

    // shrink if the size is too big
    if(xpow > 1024) 
    {
        xpow = 1024;
        ypow = 1024;
    }

    // transform the image to square pow size
    scaledImage = myImage.scaled(xpow, ypow, Qt::IgnoreAspectRatio);
    glImage = QGLWidget::convertToGLFormat(scaledImage);

    this->setMinimumWidth(myImage.width());
    this->setMinimumHeight(myImage.height());

    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &imageID);
    glBindTexture( GL_TEXTURE_2D, imageID );
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, scaledImage.width(), scaledImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glImage.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);
}

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

void GLImageDisplay::resizeGL(int width, int height) 
{   
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, height, 0);    // flip the y axis
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLImageDisplay::paintGL() 
{
    int width = myImage.width();
    int height = myImage.height();

    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1,0,0);
    glBegin(GL_POLYGON);
    glVertex2f(10,10);
    glVertex2f(10,600);
    glVertex2f(300,10);
    glEnd();

    glEnable(GL_TEXTURE_2D);
    glColor3f(1,1,1);
    glBindTexture( GL_TEXTURE_2D, imageID );
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glImage.width(), glImage.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glImage.bits());

    glBegin(GL_QUADS);

    // text coord is flipped
    glTexCoord2d(0,1); glVertex3d(0,     0,      0);
    glTexCoord2d(1,1); glVertex3d(width, 0,      0);
    glTexCoord2d(1,0); glVertex3d(width, height, 0);
    glTexCoord2d(0,0); glVertex3d(0,     height, 0);

    glEnd();
    glDisable(GL_TEXTURE_2D);
}

但是当我尝试显示一个大图像,其中小部件的底部被剪切并显示黑色区域时,我遇到了另一个问题。似乎小部件最多只渲染我的液晶屏幕的高度(?)我想知道QGLWidget不能轻易放入QScrollArea(?)。但这是一个不同的问题。

enter image description here