[Solved]A class inherited from QGLwidget to display an image (the image can not be displaed)



  • Hello, everyone.

    I am trying to write a class inherited from QGLWidget to display an image using openGL with basic pan & zoom etc. functions.
    (I have realized one before, but I am trying to write a more clear one.)
    Can anyone help me out of the problem?
    The following includes all source code. Thank you in advance.
    @
    #include <QtOpenGL>
    class FrameGLWidget : public QGLWidget
    {
    public:
    FrameGLWidget(QWidget *parent);
    ~FrameGLWidget();
    protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);

    public:
    void loadImage(QImage &img);
    void loadImage(const QString &filename);

    void setBackgroundColor(QColor color);
    

    private:
    void showImage();
    void showTitlePage();

    private:
    QColor bg_color; //background color
    float XPan_Ratio,YPan_Ratio,Zoom_Ratio;
    int width_img,height_img; //image size

    bool bImageConnected;
    bool bGridEnabled;
    bool bTextureCreated;
    
    GLuint texture;
    

    };

    @

    @
    #include "FrameGLWidget.h"
    FrameGLWidget::FrameGLWidget(QWidget *parent) :
    QGLWidget(parent)
    {
    setWindowTitle(tr("FrameGLWidget"));
    bImageConnected=false;
    bTextureCreated=false;
    bGridEnabled=false;

    XPan_Ratio=0.0f;
    YPan_Ratio=0.0f;
    Zoom_Ratio=1.0f;
    

    }

    FrameGLWidget::~FrameGLWidget()
    {
    if(bTextureCreated)
    glDeleteTextures(1,&texture);
    }

    void FrameGLWidget::initializeGL()
    {
    glDisable(GL_DEPTH_TEST); //disable for 2D painting
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    }

    void FrameGLWidget::resizeGL(int w, int h)
    {
    glViewport(0,0,w,h);
    }

    void FrameGLWidget::paintGL()
    {
    qglClearColor(bg_color);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    //set the window background color
    if(!bImageConnected)
    showTitlePage();
    else
    showImage();
    }

    void FrameGLWidget::showImage()
    {
    float ox,oy;
    float x1,y1,x2,y2,x3,y3,x4,y4;
    float rw,rh;

    //rw=w_h_ratio_image/w_h_ratio_window;
    rw=1.0f;rh=1.0f;
    
    ox=XPan_Ratio*(1.0+Zoom_Ratio*rw); oy=YPan_Ratio*(1.0+Zoom_Ratio*rh);
    x1=ox-Zoom_Ratio*rw; y1=oy-Zoom_Ratio*rh;
    x2=ox+Zoom_Ratio*rw; y2=oy-Zoom_Ratio*rh;
    x3=ox+Zoom_Ratio*rw; y3=oy+Zoom_Ratio*rh;
    x4=ox-Zoom_Ratio*rw; y4=oy+Zoom_Ratio*rh;
    y3=0.0;y4=0.0;
    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0,0,this->width(),this->height());
    
    glEnable(GL_TEXTURE_2D);
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    
    glBegin( GL_QUADS );
    glTexCoord2d(0.0,0.0); glVertex2d(x1,y1);
    glTexCoord2d(1.0,0.0); glVertex2d(x2,y2);
    glTexCoord2d(1.0,1.0); glVertex2d(x3,y3);
    glTexCoord2d(0.0,1.0); glVertex2d(x4,y4);
    glEnd();
    
    glDrawBuffer(GL_BACK);
    

    }

    void FrameGLWidget::loadImage(QImage &img)
    {
    width_img=img.width();
    height_img=img.height();

    /* Create texture object */
    if(!bTextureCreated)
    {
        glGenTextures(1, &texture);
        bTextureCreated=true;
    }
    
    /* Now upload pixels */
    if(img.format()!=QImage::Format_RGB32)
        img=img.convertToFormat(QImage::Format_RGB32);
    qDebug()<<"Color count:"<<img.colorCount();
    qDebug()<<"Depth:"<<img.depth();
    qDebug()<<"Format"<<img.format();
    qDebug()<<"Has Alpha channel:"<<img.hasAlphaChannel();
    
    QImage tex_image;
    tex_image = QGLWidget::convertToGLFormat(img);
    
    //make sure its not null
    if(tex_image.isNull())
    {
        QMessageBox::warning(this, tr("Error"),
                             tr("failed to transform image to opengl format."));
        return ;
    }
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
                 tex_image.width(), tex_image.height(), 0,
                 GL_RGB, GL_UNSIGNED_BYTE, tex_image.bits());
    
    bImageConnected=true;
    
    // Update scene
    updateGL();
    return;
    

    }

    void FrameGLWidget::loadImage(const QString &filename)
    {
    QImage img;
    img.load(filename);
    if(img.isNull())
    {
    QMessageBox::warning(this, tr("Error"),
    tr("Can not open specified file <%1>").arg(filename),
    QMessageBox::Ok);
    return;
    }
    else
    {
    loadImage(img);
    return ;
    }
    }

    void FrameGLWidget::setBackgroundColor(QColor color)
    {
    bg_color=color;
    }

    void FrameGLWidget::showTitlePage()
    {
    QFont serifFont("Times", 30, QFont::Bold);
    setFont(serifFont);
    QString text=tr("NO IMAGE");
    QFontMetrics metrics = QFontMetrics(font());
    int border = qMax(4, metrics.leading());
    QRect rect = metrics.boundingRect(0, 0, width() - 2*border, int(height()*0.125),
    Qt::AlignCenter | Qt::TextWordWrap, text);
    renderText((width() - rect.width())/2,(height()-rect.height())/2,text);
    }

    @

    @

    #include <QtWidgets/QApplication>
    #include <QtWidgets/QMessageBox>
    #include "FrameGLWidget.h"

    int main(int argc, char **argv)
    {
    QApplication app(argc, argv);
    if (!QGLFormat::hasOpenGL() || !QGLFramebufferObject::hasOpenGLFramebufferObjects()) {
    QMessageBox::information(0, "Warning",
    "This system does not support OpenGL/framebuffer objects.");
    return -1;
    }

    FrameGLWidget frameGL(0);
    frameGL.resize(640, 480);
    frameGL.setBackgroundColor(Qt::darkGreen);
    frameGL.loadImage("test.jpg");
    frameGL.show();
    return app.exec(&#41;;
    

    }
    @



  • Well, I think you want to debug this a bit first, and find out where the problem is before posting...

    Just a stab in the dark, but maybe double-check
    @glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ...@
    since my code has
    @glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ...@



  • Thanks for your hint.
    But I think that is not the cause of my problem.
    I copy the piece of code from my old project, which runs without problem.
    As you say, I try to debug it further.
    Thank you.



  • I tried to convert image format to QImage::Format_RGB32 and then call the following glTexImage2D with GL_RGB format. But it also failed.

    Can anyone help me out? Thank you.



  • I have solved the problem.
    In the main program, I try to load the image file and construct texture before QGLwidget window shows. In fact , the opengl context will not be constructed until the QGLwidget shows is called (and then initializeGL is called). I just change the order
    from
    @
    frameGL.loadImage("test.jpg");
    frameGL.show();
    @

    to
    @
    frameGL.show();
    frameGL.loadImage("test.jpg");
    @

    And then it works fine.



  • It's strange. I use your code without modification and it shows the image only in the lower half part of the window.
    I mean, the jpg image's height is halved (its width is unmodified) and the image is drawn starting from the position (0, height/2).
    Do you see an explanation ?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.