2013-07-19 55 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

相關問題