使用QT查看来自摄像头的流媒体图像

时间:2011-06-28 00:41:10

标签: c++ linux qt

我有一个软件可以通过网络将JPG发送到应该显示这些图像的GUI客户端。我基本上想要将它们显示到qt窗口,但我遇到qt如何显示连续JPG的问题。我做了一个测试,看看我是否正确地将图像打印到文件中并且检查结果很好。这是主要代码:

int main(int argc, char *argv[]) {
    // initialize resources, if needed
    // Q_INIT_RESOURCE(resfile);

    QApplication app(argc, argv);
    CameraWindow cw;
    cw.show();
    //app.setActiveWindow(&cw);
    cw.getData();       // this paints the window  
    return app.exec();
}

这是初始化小部件的代码:

class CameraWindow : public QDialog {
    Q_OBJECT
    public:
    bool serverConnected;
    void getData();
    CameraWindow()
    {
        imgl = new QLabel;
        widget.scrollImage->setWidget(imgl);
        widget.scrollImage->setBackgroundRole(QPalette::Dark);
    }
    QLabel *imgl;
    virtual ~CameraWindow();
    private:
    Ui::CameraWindow widget;
};

这是代码的相关部分,它应该将图像绘制到无限循环内的屏幕上:

从main调用getData():

while (myrval < Header.imageSize) {
    myrval = myrval + recv(msgsock, (char*) ((int) buff + myrval),
        Header.imageSize- myrval, 0);
}

//buff contains the jpg at this point
QPixmap imgjpg;
imgjpg.loadFromData((const unsigned char*)buff, Header.imageSize, "JPG");
//scroll image is the parent that displays child
//in this case, the label
imgl->setPixmap(imgjpg);

我让这个只适用于从文件加载的一个图像但是当我对一组流图像使用相同的方法时,这不起作用。我是Qt的新手,所以我确定我有一个微妙的错误。

非常感谢!

3 个答案:

答案 0 :(得分:1)

因为你处于无限循环中,Qt可能没有机会处理事件。你可以尝试在setPixmap之后调用QCoreApplication :: processEvents吗?

答案 1 :(得分:1)

我建议创建一个ImageProvider类,提醒其他人它已准备好图像:

public class ImageProvider : QObject {
    Q_OBJECT
public:
    QPixmap getCurrentImage() const { /* retrieve current image */ }
signals:
    void newImageAvailable();
};

现在你需要一个类来显示它,所以让我们称之为ImageDisplayer,并假设它有一个名为imageLabel的标签,上面有你当前的图像集:

public class ImageDisplayer : QWidget {
    Q_OBJECT
    QLabel *imageLabel;
    ImageProvider *provider; 
public:
    ImageDisplayer(QWidget *parent, ImageProvider *imageProvider) {
        this->imageLabel = /* setup QPixmap */;
        this->imageProvider = imageProvider;
        connect(imageProvider, SIGNAL("newImageAvailable()"), SLOT("setNewImage()"));
    }
    public void setNewImage() {
        imageLabel->setPixmap(imageProvider->getCurrentImage());
        update(); // schedule the repaint
    }
};

update的调用会在Qt认为合理时立即发生重绘。这也允许跳过的帧和其他东西(你可能不想要)。

最后,您需要确保所有内容都通过主要小部件连接:

public class MainWidget : QMainWindow {
    Q_OBJECT
    ImageDisplayer *imageDisplayer;
    ImageProvider *imageProvider;
public:
    void MainWidget() {
        this->imageProvider = new ImageProvider(/*your dependencies*/);
        this->imageDisplayer = new ImageDisplayer(this, imageProvider);
    }
}

主要是:

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    MainWidget w;
    w.show();
    return app.exec();
}

这可能不是性能最佳的实现,但它很简单,可能适合您的需求。

答案 2 :(得分:0)

除了Mason Chang的回答之外 - 更好的方法是让显示器成为一个插槽然后从计时器调用插槽。

setTimer值为0实际上是一个循环 - 它会在插槽完成后立即调用,但仍允许其他处理。