qt - 使用Qt通过TCP接收原始图像数据进行显示

标签 qt tcp

我正在开发一个 GUI 来显示来自传感器的图像。 GUI 充当客户端,而传感器充当服务器。一旦我向传感器发送命令,传感器就会通过 TCP 向 GUI 连续发送流式原始图像数据(二进制数据)。数据将是图像存储器的精确副本,大小为宽度 (1240) x 高度 (1028),以 U8(无符号 8 位)编码。一个传入数据的大小为(1240 x 1028 x 1 字节)+ 20 字节(元 header )= 1.3MByte。

我最大的障碍是: 1.) 我怎样才能连续接收和存储来自传感器的流数据以供显示? 2.) 如何显示原始数据?

我试过下面的代码,但它不起作用。请指教:

“客户端.h”

#ifndef CLIENT_H
#define CLIENT_H

#include <QObject>
#include <QWidget>
#include <QTcpSocket>

class Client : public QWidget
{
    Q_OBJECT
public:
    explicit Client(QWidget *parent = 0);
    int capture (int mode, int NBRLine);

signals:

public slots:

private:
    QTcpSocket* socket;

};

#endif // CLIENT_H

“客户端.cpp”

#include "client.h"
#include <QHostAddress>
#include "mainwindow.h"
#include <QtGui>
#include <QAbstractSocket>
#include <QImage>

Client::Client(QWidget *parent) :
    QWidget(parent)
{
    socket = new QTcpSocket(this);  
}

int Client::capture(int mode, int NBRLine)
{
    if (socket->state() != QTcpSocket::ConnectedState)
    {
        socket->connectToHost("192.168.0.65", 1096);
    }

    /* send command to retrieve raw image data from sensor */
    if(socket->waitForConnected(5000))
    {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_0);
        out.setByteOrder(QDataStream::LittleEndian);
        out << qint32(0) << qint32(0) << qint32(0) << qint32(1);
        out << qint32(9) << qint32(1) << qint32(0) << mode << qint32(10) << qint32(2) << qint32(0) << NBRLine ;
        socket->write(block);
        socket->flush();
    }
    else
    {
        return false;
    }
    /**********************************************************/

    /* to get data size of each scan through width and height in the meta header */
    QDataStream input(socket);
    input.setVersion(QDataStream::Qt_4_0);
    input.setByteOrder(QDataStream::LittleEndian);
    qint32 buffer, cmdID, counter, metaSize, width, height;
    do
    {
        if (socket->waitForReadyRead(1000))
        {
            input >> cmdID;
            if (cmdID == 101)
            {
                input >> buffer >>  buffer >> buffer >> buffer;
            }
        }
        else
        {
            socket->disconnectFromHost();
            break;

        }
    } while (cmdID != 1);

    input >> counter >> metaSize;
    if (metaSize != 8) return false;

    input >> width >> height;
    quint32 datasize =  width * height;

    /**********************************************************/

    /* Receiving streaming data which I have problem here !!!! */
    while (socket->bytesAvailable() < datasize + 80) {
        if (!socket->waitForReadyRead(1000)) {
            socket->disconnectFromHost();
            break;
        }
    }

    QImage img;
    input >> img;

    if (img.isNull())
    {
        return 0;
    }
    img.save("E:/temp1");
     return 1;
}

最佳答案

在发送缓冲区的内容之前,您需要找到一种方法来告诉客户端需要多少数据。所以首先你应该发送数据大小,然后是数据。

在服务器端你应该发送像这样的图像数据:

QTcpSocket socket;

QBuffer buffer;
QImageWriter writer(&buffer, "PNG");
writer.write(QImage("myImage.png") );

QByteArray data;
QDataStream stream( &data, QIODevice::WriteOnly );
stream.setVersion( QDataStream::Qt_4_8 );
stream << (quint32)buffer.data().size();
data.append( buffer.data() );

socket.write( data );

在客户端,您应该将套接字的 readyRead 信号连接到插槽,以便在收到新数据时读取数据:

connect( socket, SIGNAL(readyRead()),this, SLOT(tcpReady()) );

图像数据可以这样读取:

void Client::tcpReady()
{
    if( dataSize == 0 )
    {
        QDataStream stream( &socket );
        stream.setVersion( QDataStream::Qt_4_8 );

        if( socket.bytesAvailable() < sizeof(quint32) )
            return;

        stream >> dataSize;
    }

    if( dataSize > socket.bytesAvailable() )
        return;

    QByteArray array = socket.read( dataSize );
    QBuffer buffer(&array);
    buffer.open( QIODevice::ReadOnly );

    QImageReader reader(&buffer, "PNG");
    QImage image = reader.read();

    if( !image.isNull() )
    {
        image.save("E:/temp1");
    }
    else
    {
        QDebug()<<"Invalid image received!";
    }
}

关于qt - 使用Qt通过TCP接收原始图像数据进行显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24379915/

相关文章:

debugging - 如何在 Firefox 中调试 TCP 级别的 Web 连接?

sockets - Julia TCP 服务器和连接

c++ - Qt - 2 类中的信号和槽

c++ - 让 QScrollArea 动态适应其父级,但不会为其子级扩展

android - 如何仅在 .pro 文件中为 Android 平台构建指定库?

tcp - 既然 MQTT 基于 TCP,那为什么 MQTT 需要 QoS?

qt - QString度数符号

c++ - 如何让继承自 QgraphicsPolygonItem 的六边形改变颜色?

Java:发送和接收字节数组

javascript - Node.js 单击按钮并使用 TCP/IP 协议(protocol)发送内容