使用QT搭建点云显示框架系列八---如何利用opengl在界面上绘制QImage

12 篇文章 4 订阅

这篇文章是上一篇的继续,摸不着头脑的童鞋先静下心来好好看看上一篇。

好我们直接走起:

首先你需要有一个QImage,我们需要在界面上绘制这样一个QImage:


然后我先放了一个效果上来,我们首先要生成这样的一个QImage显示出来:

void ScarletGLViewer::do_CreateLinearImage()
{
    int myheight = 400;
    int mywidth = 100;
    int border = 10;
    QLinearGradient gr(0, 0, 1, myheight - 2 * border);
    gr.setColorAt(1.0f, Qt::black);
    gr.setColorAt(0.8f, Qt::darkGreen);
    gr.setColorAt(0.6f, Qt::green);
    gr.setColorAt(0.4f, Qt::yellow);
    gr.setColorAt(0.2f, Qt::red);
    gr.setColorAt(0.0f, Qt::darkRed);
 
    QPixmap *m_LinearPm = new QPixmap(mywidth, myheight);
    m_LinearPm->fill(Qt::transparent);
 
    QPainter pmp(m_LinearPm);
    pmp.setBrush(QBrush(gr));
    pmp.setPen(Qt::NoPen);
    pmp.drawRect(border, border, 35, myheight - 2 * border);//如果border增加,就会往另外一边错开
    QImage *m_LinearRect=new QImage(QGLWidget::convertToGLFormat(m_LinearPm->toImage()));
    QPainter pmp2(m_LinearRect);
    pmp2.setPen(Qt::black);
    int step = (myheight - 2 * border) / 5;
    for (int i = 0; i < 6; i++)
    {
        int yPos = i * step + border;
        pmp2.drawLine(border, yPos, 55, yPos);
        pmp2.drawText(60, yPos + 2, QString("%1 m").arg(550 - (i * 110)));
    }
    QLabel *myLabel = new QLabel();
    myLabel->setPixmap(QPixmap::fromImage(*m_LinearRect));
    myLabel->show();
 
    glGenTextures(2, &m_texture[1]);     // 为第i个位图创建纹理
    glBindTexture(GL_TEXTURE_2D, m_texture[1]);// 将生成的纹理的名称绑定到指定的纹理上
 
    // Bind the img texture...
    glTexImage2D(GL_TEXTURE_2D, 0, 4, m_LinearRect->width(), m_LinearRect->height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, m_LinearRect->bits());
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

我先解释一下上面代码,首先我必须把QImage手动画出来,我先利用 QLinearGradient 建立一个画刷,然后调用这句话:

m_LinearPm->fill(Qt::transparent);

意思就是说这幅图像是透明的。如果没有这句话,或者替换成别的,你的效果就会变成这样:

其实你可以选择的参数有很多,是下面这些参数的其中之一:我们可以看到transparent实际上是最后一个。

enum GlobalColor {
        color0, color1, black,white,darkGray, gray,
        lightGray,red, green,  blue,   cyan,  magenta, yellow,   
darkRed,  darkGreen,  darkBlue, darkCyan, darkMagenta,    darkYellow,   transparent
    };

然后利用这三句话,图像就变成了渐变的:

QPainter pmp(m_LinearPm);
    pmp.setBrush(QBrush(gr));
    pmp.setPen(Qt::NoPen);

再然后,我们可以看到现在图像还没有文字,那么下面我们添加文字:

 for (int i = 0; i < 6; i++)
    {
        int yPos = i * step + border;
        pmp2.drawLine(border, yPos, 55, yPos);
        pmp2.drawText(60, yPos + 2, QString("%1 m").arg(550 - (i * 110)));
    }

那么效果就成了这样:


聪明的同学可能会发现,两个条颜色不一样啊,我们是按照绿色-黄色-红色显示出来的,为什么用QLabel显示出来,黄色变成了青色,而红色变成了蓝色呢?其实很简单,因为这句话:

QImage *m_LinearRect=new QImage(QGLWidget::convertToGLFormat(m_LinearPm->toImage()));
        为什么要将QImage转换成GLFormat呢?因为opengl的RGB存储格式为BGR,和QImage是恰恰相反的,但是绿色通道都在中间。我们程序中先执行了这句话,然后再显示,那么就变成这种效果了。还有,我们必须在转换成这种格式之后再进行文字绘制,不然这句话会把文字全都变成反向的了。

然后下面就比较关键了:

 glGenTextures(2, &m_texture[1]);     // 为第i个位图创建纹理
    glBindTexture(GL_TEXTURE_2D, m_texture[1]);// 将生成的纹理的名称绑定到指定的纹理上
 
    // Bind the img texture...
    glTexImage2D(GL_TEXTURE_2D, 0, 4, m_LinearRect->width(), m_LinearRect->height(), 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, m_LinearRect->bits());
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


        然后就是opengl的固定套路了,我们首先分配一个ID,这里是2,然后绑定纹理。最后将QImage的bits直接塞进去即可。比较关键的地方是,在这句话之后必须要设置一下纹理的属性,如果没有这一步,纹理似乎是不可用的。。。。。本人也是查了很久才发现的。

        现在我们有了纹理,如何使用的,只需要在你的绘制函数里面添加下面代码即可:

void ScarletGLViewer::do_drawlinearRectangle()
{
    glBindTexture(GL_TEXTURE_2D, m_texture[1]);// 将生成的纹理的名称绑定到指定的纹理上
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glEnable(GL_BLEND);
    //glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    //glColor3f(0.5,0.4,0.3);
    glColor3f(1.0,1.0,1.0);//参与混合的颜色,还是白色比较好,比较亮
    //glDisable(GL_BLEND);//必须开启混合否则背景是黑色的
    startScreenCoordinatesSystem(true);
 
    glNormal3f(0.0, 0.0, 1.0);
    QPoint UpLeftP,RightDownP;
//    UpLeftP.setX(width()-m_LinearRect->width()-50);
//    RightDownP.setX(width()-50);
//    UpLeftP.setY(height()/2-m_LinearRect->height()/2);
//    RightDownP.setY(height()/2+m_LinearRect->height()/2);
    UpLeftP.setX(width()-100-10);
    RightDownP.setX(width()-10);
    UpLeftP.setY(height()/2-400/2);
    RightDownP.setY(height()/2+400/2);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0,1.0);	glVertex2i(UpLeftP.x(),UpLeftP.y());
    glTexCoord2f(0.0,0.0);	glVertex2i(UpLeftP.x(),RightDownP.y());
    glTexCoord2f(1.0,0.0); glVertex2i(RightDownP.x(),RightDownP.y());
    glTexCoord2f(1.0,1.0);	glVertex2i(RightDownP.x(),UpLeftP.y());
    glEnd();
 
    stopScreenCoordinatesSystem();
 
    // Depth clear is not absolutely needed. An other option would have been to draw the
    // QUAD with a 0.999 z value (z ranges in [0, 1[ with startScreenCoordinatesSystem()).
    glClear(GL_DEPTH_BUFFER_BIT);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_LIGHTING);
    glEnable(GL_BLEND);
}

emmmm别忘了在这之前开启混合,这样你前面设置的透明QImage才能真正体现出来。如果你没有开启混合,效果会是这样的:


emmm好了,完整的代码就看这一个吧,注意日期哦,因为我的代码也是今后也要更新的。这一次是1018-4-9日最新添加的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值