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

问题描述 投票:0回答:3

我想使用 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);
}
qt opengl qglwidget
3个回答
3
投票

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

要解决此问题,请将您的呼叫更改为

glOrtho
或在呼叫后立即应用缩放 + 平移。

顺便说一句。您还可以使用

QPainter
并在真正需要 GL 的地方使用
beginNativePainting()
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
投票

QImage 垂直镜像是为了说明 OpenGL 和 QImage 使用相反的 y 轴方向。修复它的简单方法:

QImage image(":/Resources/imageName.png");
QImage yAxisInvertedImage = image.mirrored();
© www.soinside.com 2019 - 2024. All rights reserved.