Sending infomartion like double and image with TCP



  • Hello,

    I'm new with Qt and I want to transmit some information about TCP. I use a QByteArray and a QDataStream for sending:

    @QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_0);
    out << (quint16)0;
    out << scaleFactor; //double
    out << imageData; //any format to transmit my image
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    tcpSocket->write(block);@

    and for receiving (by "readyRead()"):

    @QDataStream in(clientConnection);
    in.setVersion(QDataStream::Qt_5_0);

    if (blockSize == 0) {
    if (clientConnection->bytesAvailable() < (int)sizeof(quint16))
    return;
    in >> blockSize;
    }
    if (clientConnection->bytesAvailable() < blockSize)
    return;

    QByteArray img; // here should be the format in which I receive the data for my image
    double scaleFactor = 0.0;

    in >> scaleFactor;
    in >> imageData;

    qDebug() << "scaleFactor:" << scaleFactor; // this works, so transmitting a double is no problem
    img.loadFromData(imageData);@

    I tried to transmitt my QImage as a QByteArray:

    @QByteArray ba;
    QBuffer buffer(&ba);
    image.save(&buffer, "PNG");
    QByteArray imageData = buffer.data();@

    but I think QDataStream can't work with QByteArray. Then I tried to use:
    @const char *imageData = buffer.data().data();@

    but when I want to tranform the char back to a QByteArray which I need to create my QImage, this didn't work:

    @//this works:
    QByteArray ba;
    QBuffer buffer(&ba);
    image.save(&buffer, "PNG");
    QByteArray ba2 = buffer.data();
    QImage test;
    test.loadFromData(ba2);

    //and this not:
    QByteArray ba;
    QBuffer buffer(&ba);
    image.save(&buffer, "PNG");
    QByteArray ba2 = buffer.data();
    const char *imageData = ba2.data();
    QByteArray ba3 = QByteArray(imageData);
    QImage test;
    test.loadFromData(ba3);@

    So in the last version I would have my char which I could transmit by QDataStream, but I can't get my image from it.

    Maybe there is a much easier way to transmit a double and an QImage??
    Or can you show my any way how to do it? But important is, that I have to transmit both, the double an the QImage.
    Thank you!!!



  • Hi,

    why you don't try with

    @
    out << image; // your QImage object

    in >> image;
    @

    QImage implements
    @
    QDataStream& operator << (QDataStream & str, const QImage& img);
    QDataStream& operator >> (QDataStream & str, QImage& img);
    @

    so you can write directly code like mine


  • Lifetime Qt Champion

    Hi,

    You need to send the data size of the image you are sending before the data so you can rebuild it on the other side.

    Using the QByteArray(const char *) constructor, your are telling it it's a string so it will stop at the first \0 char. You need to use the other constructor giving the size of the char array.

    Hope it helps



  • Hi mcosta,

    when I write

    @in >> img; //my QImage@

    I get this in the Application Output: "QIODevice::seek: Cannot call seek on a sequential device"



  • Hi SGaist,

    thank you, your answer was helpful!
    So now this works:
    @QByteArray ba;
    QBuffer buffer(&ba);
    image.save(&buffer, "PNG");

    QByteArray ba2 = buffer.data();
    const char *imageData = ba2.data();
    int imageSize = ba2.size();

    QByteArray ba3 = QByteArray(imageData, imageSize);
    QImage test;
    test.loadFromData(ba3);@

    and I send it like this:
    @QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_0);
    out << (quint16)0;
    out << scaleFactor;
    out << imageData;
    out << imageSize;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));
    tcpSocket->write(block);@

    and receive it so:
    @QImage img;
    double scaleFactor;
    char *imageData;
    const char *cImageData;
    int imageSize;

    in >> scaleFactor;
    in >> imageData;
    in >> imageSize;
    cImageData = imageData;
    qDebug() << "scaleFactor:" << scaleFactor << "imageSize:" << imageSize; //right numbers
    //this still doesn't work:
    QByteArray ba = QByteArray(cImageData, imageSize); //doesn't work with imageData, too
    img.loadFromData(ba);@

    Do you have any idea why the last two lines still don't work? "scaleFactor" and "imageSize" are transmitted correctly.



  • Can it be, that the char is only read in untill the first \0 char? So that I need to append it, until it is really complete?


  • Lifetime Qt Champion

    You are taking the wrong assumption for the receiver end. All the data won't have necessarily arrived when the readyRead signal is emitted, it only means that you have something available.

    Have a look at the Fortune Server and Client example. It explains one way of doing the transfer from one side to the other.

    Hope it helps



  • I used that example. Before the "in >> .." I have this:
    @QDataStream in(clientConnection);
    in.setVersion(QDataStream::Qt_5_0);

    if (blockSize == 0) {
    if (clientConnection->bytesAvailable() < (int)sizeof(quint16))
    return;
    in >> blockSize;
    }
    if (clientConnection->bytesAvailable() < blockSize)
    return;@

    Doesn't that mean that all data is arrived?



  • My image was too big, "this helped.":http://qt-project.org/forums/viewthread/25609


  • Lifetime Qt Champion

    That was the second idea I had in mind but I failed to find the post.

    If everything is working as expected, don't forget to update the thread's title to solved so other forum users may know that a solution has been found :)


Log in to reply
 

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