1

QGLWidget を使用して画像を表示したいのですが、正しく表示されません。問題の 1 つは、元の座標がウィジェットの左下にあることです。元の座標を左上にしてy軸を反転させる方法を知りたいです。

ここに画像の説明を入力

ここに私のコードがあります:

ヘッダ

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

2 に答える 2

3

OpenGL 座標は下から始まります。これを修正するには、射影行列の y 軸で -1 スケーリングを実行します。オフセットが関係しています。

これを修正するには、呼び出しを変更するglOrthoか、呼び出しの直後にスケーリング + 変換を適用します。

ところで。本当にGLが必要な場所ならどこでもQPainter使用できます。すでにGL自体を使用しており、非常にうまく機能します。beginNativePainting()QPainter

glDrawPixels画面に画像を描画する方法としては非常に非効率的です。それをテクスチャにロードし、それでクワッドを描画する必要があります。(繰り返しにQPainterなりますが、これもはるかに簡単に行うことができます。)

于 2013-07-19T23:38:57.843 に答える
2

ありがとうイプノス

最後に、射影行列 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 画面の高さ (?) でレンダリングされるようです。別の問題ですけどね。

ここに画像の説明を入力

于 2013-07-20T10:07:18.310 に答える