2013-07-19 52 views
1

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

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

回答

3

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

要解决此问题,请将您的呼叫更改为glOrtho或在呼叫之后应用缩放+翻译。

Btw。您也可以使用QPainter并使用beginNativePainting(),无论您真正需要GL。 QPainter将已经使用GL本身并且很好地执行非常

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

2

谢谢ypnos

最后我翻转投影矩阵gluOrtho2D(0,width,height,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); 
} 

但我遇到另一个问题,当我尝试显示在窗口小部件的底部被切断,并显示黑区的大型图像。看来这个小部件最多只能显示在我的LCD屏幕的高度(?)我想知道QGLWidget不能轻易放入QScrollArea(?)。不过这是一个不同的问题。

enter image description here

+0

为了解决这个问题,您应该切换到QGraphicsScene和的QGraphicsView设置。当您将目标设置为QGraphicsView到QGLWidget时,您可以使用GL。这里有一些示例代码:http://qt.gitorious.org/qt-labs/modelviewer它非常强大,虽然有点复杂,我不得不承认。否则,当滚动或者渲染到FBO(QGLBuffer)并相应地在滚动区域中显示那个时,您将需要完成整个GL重绘。 – ypnos

+0

请注意,在modelviewer示例中,他们让QGraphicsScene始终是QGraphicsView的大小以避免滚动。相反,您只需将QGraphicsScene尺寸设置为图像/内容的尺寸即可。 – ypnos

+0

我会看看modelviewer。人们建议使用qglwidget将qabstractscrollarea分类,并使用滚动条位置设置视口位置。你认为这会起作用,我仍然试图实施它。 – azer89

相关问题