【问题标题】:Rendering QImage on QGLWidget of QML plugin在 QML 插件的 QGLWidget 上渲染 QImage
【发布时间】:2012-01-16 19:13:57
【问题描述】:

我正在尝试编写一个 QML 插件,它从视频中读取帧(使用自定义小部件来完成该任务,而不是 QtMultimedia/Phonon),并且每个帧都转换为 @987654322 @RGB888,然后显示在QGLWidget上(出于性能原因)。现在什么都没有画到屏幕上,屏幕一直保持白色。

重要的是要说明我已经在没有 QGLWidget 的情况下完成了所有这些工作,所以我知道问题在于设置和绘制 QGLWidget。

插件正在注册:

qmlRegisterType<Video>(uri,1,0,"Video");

所以Video 是插件的主类。在它的构造函数上,我们有:

Video::Video(QDeclarativeItem* parent)
: QDeclarativeItem(parent), d_ptr(new VideoPrivate(this))
{    
    setFlag(QGraphicsItem::ItemHasNoContents, false);            

    Q_D(Video);
    QDeclarativeView* view = new QDeclarativeView;
    view->setViewport(&d->canvas()); // canvas() returns a reference to my custom OpenGL Widget
}

在我跳转到canvas 对象之前,让我说我重载了Video::paint(),所以它在传递QImage 作为参数时调用canvas.paint(),我不知道这是否是正确的方法所以我想对此提出一些建议:

void Video::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    Q_UNUSED(painter);
    Q_UNUSED(widget);
    Q_UNUSED(option);

    Q_D(Video);
    // I know for sure at this point "d->image()" is valid, but I'm hiding the code for clarity
    d->canvas().paint(painter, option, d->image());
}

canvas 对象声明为GLWidget canvas;,该类的头部定义为:

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:        
    explicit GLWidget(QWidget* parent = NULL);
    ~GLWidget();

    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image);
};

看起来很简单。现在,QGLWidget 的实现如下:

GLWidget::GLWidget(QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
   // Should I do something here?
   // Maybe setAutoFillBackground(false); ???
}

GLWidget::~GLWidget()
{
}

最后:

void GLWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image)
{
   // I ignore painter because it comes from Video, so I create a new one:
   QPainter gl_painter(this);


   // Perform drawing as Qt::KeepAspectRatio

   gl_painter.fillRect(QRectF(QPoint(0, 0), QSize(this->width(), this->height())), Qt::black);

   QImage scaled_img = image->scaled(QSize(this->width(), this->height()), _ar, Qt::FastTransformation);

   gl_painter.drawImage(qRound(this->width()/2)  - qRound(scaled_img.size().width()/2),
                        qRound(this->height()/2) - qRound(scaled_img.size().height()/2),
                        scaled_img); 
}

我错过了什么?

我最初询问了this question on Qt Forum,但没有得到回复。

【问题讨论】:

    标签: c++ qt opengl qt4 qml


    【解决方案1】:

    我认为你必须使用 opengl 函数在你的 glwidget 上绘图。

    一种可能的方法是在 GLWidget 中覆盖您的 paintGL() 方法 然后使用 glDrawPixels() 绘制图像。

    glClear(GL_COLOR_BUFFER_BIT);
    glDrawPixels(buffer.width(), buffer.height(), GL_RGBA, GL_UNSIGNED_BYTE, buffer.bits());
    

    其中 buffer 是一个 QImage 对象,需要使用 QGLWidget::converrtToGLFormat() 静态方法进行转换。

    查看此来源以供参考: https://github.com/nayyden/ZVector/blob/master/src/GLDebugBufferWidget.cpp

    【讨论】:

    • 由于某种原因,GLWidget::paintGL() 没有被调用,即使我更改了Video::paint() 以使其执行d->canvas().update(); d->canvas().repaint();
    • 我可能给出的一个愚蠢的建议是向您的 GLWidget 添加一个新的公共方法,并在该方法中调用 paintGL() 和 updateGL() 但是您必须在需要时输入画布调用它。
    • 我真的不想直接使用 OpenGL 调用,所以我没有重载像 paintGL() 这样的 GL 方法。
    • 如果你还有兴趣,这个问题已经解决了。如果您愿意,可以查看我的答案。
    【解决方案2】:

    已解决。问题是当我应该从加载它的应用程序中检索 GL 上下文时,我试图在我的插件中创建一个新的 GL 上下文。

    This code 对了解如何实现这一点非常有帮助

    顺便说一句,我发现这些东西正在view 中绘制。只是我需要执行view->show(),但这会创建另一个窗口,这不是我想要的。我上面分享的链接有答案。

    【讨论】:

    • 你还有源吗?我目前面临类似的问题,链接转到 404。
    • 我会尽量把它贴在这里。
    • 死链接。也是新的。
    • 这个话题已经快9岁了。最初发布参考代码的存储库已死并且早已不复存在。这是我最后一次在网上追踪类似的源代码以供参考。 Here it is。从现在开始祝你好运。
    猜你喜欢
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多