Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Send image inside Json through QTcpSocket
Qt 6.11 is out! See what's new in the release blog

Send image inside Json through QTcpSocket

Scheduled Pinned Locked Moved Solved General and Desktop
28 Posts 6 Posters 10.7k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Tamfub

    @Christian-Ehrlicher
    Ok, I removed the qjo.insert("photo", obj["photo"].toString()); line but it still won't work.

    By the way, I noticed something in my client. This is the part where it receives data from the server:

    QByteArray dataReceived;
    QDataStream ds(sock);
    while(sock->bytesAvailable()){
        ds.startTransaction();
        ds >> dataReceived;
    }
    ds.commitTransaction();
    
    while(sock->bytesAvailable()){
        // Start the transaction
        ds.startTransaction();
        // Read data
        ds >> dataReceived;
        // Error checking
        if ((!ds.commitTransaction()) && (ds.status()!=QDataStream::Ok)){
             sock->flush();
             qDebug() << "Error!";
             return;
        }
    }
    
    QString string = (QString)dataReceived;
    QJsonDocument doc = QJsonDocument::fromJson(string.toUtf8());
    QJsonObject obj = doc.object();
    
    ...
    
    QJsonValue photo = obj.take("photo");
    qDebug() << photo.toString();
    
    

    Then the output, in all the examples, is:

    Error!
    Error!
    Error!
    Error!
    Error!
    Error!
    

    and it reaches the part where it reads the photo data. There is something wrong when the client receives data, maybe?

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #14

    @Tamfub
    Dunno, let's start with

    while(sock->bytesAvailable()){
        ds.startTransaction();
        ds >> dataReceived;
    }
    ds.commitTransaction();
    

    Why would you (at least potentially) start multiple transactions and only commit once at the end?

    Next, I don't understand your whole sequential bytesAvailable() loops. Why two loops? Are you sure your transactions/tests tally against what is being sent in the same fashion?

    Practice code just sending string "hello", perhaps with transactions commented out, while you verify the protocol is correct? Then move to the base64 stuff. And debug out the first & last few characters sent & received to verify they correspond before you look at decoding. You want to discover where your issue is little by little.

    T 1 Reply Last reply
    0
    • JonBJ JonB

      @Tamfub
      Dunno, let's start with

      while(sock->bytesAvailable()){
          ds.startTransaction();
          ds >> dataReceived;
      }
      ds.commitTransaction();
      

      Why would you (at least potentially) start multiple transactions and only commit once at the end?

      Next, I don't understand your whole sequential bytesAvailable() loops. Why two loops? Are you sure your transactions/tests tally against what is being sent in the same fashion?

      Practice code just sending string "hello", perhaps with transactions commented out, while you verify the protocol is correct? Then move to the base64 stuff. And debug out the first & last few characters sent & received to verify they correspond before you look at decoding. You want to discover where your issue is little by little.

      T Offline
      T Offline
      Tamfub
      wrote on last edited by
      #15

      @Christian-Ehrlicher @JonB
      Ok, I guess I'll have to revise my protocol, then I'll return to the other problem later :)

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #16

        Hi,

        @Tamfub said in Send image inside Json through QTcpSocket:

        QString string = (QString)dataReceived;

        dataReceived is a QByteArray, that cast is completely wrong.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        T 1 Reply Last reply
        1
        • T Offline
          T Offline
          Tamfub
          wrote on last edited by
          #17

          @Christian-Ehrlicher @JonB
          I've given a look to the fortune client and server examples and tried to toy with data.

          In server.cpp, I replaced

          out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];
          

          with

          QString str;
          for(int i=0; i<1000000; i++)
              str.append("a");
          out << str;
          

          void Client::readFortune() became:

          void Client::readFortune()
          {
              in.startTransaction();
          
              QString data;
              in >> data;
              qDebug() << "data: " << data;
          
              if (!in.commitTransaction())
                  return;
          
              qDebug() << "data (end): ";
              qDebug() << data;
          
          //    if (nextFortune == currentFortune) {
          //        QTimer::singleShot(0, this, &Client::requestNewFortune);
          //        return;
          //    }
          
          //    currentFortune = nextFortune;
          //    //statusLabel->setText(currentFortune);
          //    qDebug() << "current: " << currentFortune;
          //    getFortuneButton->setEnabled(true);
              qDebug() << "finished";
          }
          

          The output in the client is:

          next:  ""
          next (end): 
          finished
          

          I guess qDebug() does not print large data?

          JonBJ 1 Reply Last reply
          0
          • T Tamfub

            @Christian-Ehrlicher @JonB
            I've given a look to the fortune client and server examples and tried to toy with data.

            In server.cpp, I replaced

            out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];
            

            with

            QString str;
            for(int i=0; i<1000000; i++)
                str.append("a");
            out << str;
            

            void Client::readFortune() became:

            void Client::readFortune()
            {
                in.startTransaction();
            
                QString data;
                in >> data;
                qDebug() << "data: " << data;
            
                if (!in.commitTransaction())
                    return;
            
                qDebug() << "data (end): ";
                qDebug() << data;
            
            //    if (nextFortune == currentFortune) {
            //        QTimer::singleShot(0, this, &Client::requestNewFortune);
            //        return;
            //    }
            
            //    currentFortune = nextFortune;
            //    //statusLabel->setText(currentFortune);
            //    qDebug() << "current: " << currentFortune;
            //    getFortuneButton->setEnabled(true);
                qDebug() << "finished";
            }
            

            The output in the client is:

            next:  ""
            next (end): 
            finished
            

            I guess qDebug() does not print large data?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #18

            @Tamfub said in Send image inside Json through QTcpSocket:

            I guess qDebug() does not print large data?

            Do not rely on qDebug() output visibility. I think it says somewhere qDebug(qPrintable(qString)); or print QString::length().

            T 1 Reply Last reply
            0
            • SGaistS SGaist

              Hi,

              @Tamfub said in Send image inside Json through QTcpSocket:

              QString string = (QString)dataReceived;

              dataReceived is a QByteArray, that cast is completely wrong.

              T Offline
              T Offline
              Tamfub
              wrote on last edited by
              #19

              @SGaist
              Hi.
              Ok, I guess I should use something like QString::fromLatin1(array), right?

              1 Reply Last reply
              0
              • JonBJ JonB

                @Tamfub said in Send image inside Json through QTcpSocket:

                I guess qDebug() does not print large data?

                Do not rely on qDebug() output visibility. I think it says somewhere qDebug(qPrintable(qString)); or print QString::length().

                T Offline
                T Offline
                Tamfub
                wrote on last edited by Tamfub
                #20

                @JonB
                Ok, I put some printing of the sizes, and found out that receivedData.size() = 2 x sentData.size().

                Server

                ds << QString::fromLatin1(ba.toBase64());
                qDebug() << "size: " << QString::fromLatin1(ba.toBase64()).size(); // 75684
                

                Client

                ds.startTransaction();
                QByteArray data;
                ds >> data;
                
                if (!ds.commitTransaction())
                        return;
                
                qDebug() << "data(size): " << risp.size();  // 151368
                

                How is this possible? If I try with

                QByteArray str;
                for(int i=0; i<1000000; i++)
                       str.append("a");
                ds << str;
                qDebug() << "size: " << str.size();  // 1000000
                

                instead, the two sizes match!

                JonBJ 1 Reply Last reply
                0
                • T Tamfub

                  @JonB
                  Ok, I put some printing of the sizes, and found out that receivedData.size() = 2 x sentData.size().

                  Server

                  ds << QString::fromLatin1(ba.toBase64());
                  qDebug() << "size: " << QString::fromLatin1(ba.toBase64()).size(); // 75684
                  

                  Client

                  ds.startTransaction();
                  QByteArray data;
                  ds >> data;
                  
                  if (!ds.commitTransaction())
                          return;
                  
                  qDebug() << "data(size): " << risp.size();  // 151368
                  

                  How is this possible? If I try with

                  QByteArray str;
                  for(int i=0; i<1000000; i++)
                         str.append("a");
                  ds << str;
                  qDebug() << "size: " << str.size();  // 1000000
                  

                  instead, the two sizes match!

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #21

                  @Tamfub said in Send image inside Json through QTcpSocket:

                  qDebug() << "size: " << QString::fromLatin1(ba.toBase64()).size(); // 75684

                  qDebug() << "data(size): " << risp.size(); // 151368

                  What arithmetic formula do you notice connects the two numbers in your comments? :)

                  T 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @Tamfub said in Send image inside Json through QTcpSocket:

                    qDebug() << "size: " << QString::fromLatin1(ba.toBase64()).size(); // 75684

                    qDebug() << "data(size): " << risp.size(); // 151368

                    What arithmetic formula do you notice connects the two numbers in your comments? :)

                    T Offline
                    T Offline
                    Tamfub
                    wrote on last edited by Tamfub
                    #22

                    @JonB I already noticed the receivedData in double the sentData, I wrote it before. But I can't understand why.

                    JonBJ mrjjM 2 Replies Last reply
                    0
                    • T Tamfub

                      @JonB I already noticed the receivedData in double the sentData, I wrote it before. But I can't understand why.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #23

                      @Tamfub
                      Because one is a QByteArray and one is a QString? You can't send one type, decode it as a different type, and expect them to be the same.

                      1 Reply Last reply
                      1
                      • T Tamfub

                        @JonB I already noticed the receivedData in double the sentData, I wrote it before. But I can't understand why.

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by
                        #24

                        @Tamfub
                        Hi
                        QString is 16 bit. QByteArray is 8bit

                        T 1 Reply Last reply
                        0
                        • mrjjM mrjj

                          @Tamfub
                          Hi
                          QString is 16 bit. QByteArray is 8bit

                          T Offline
                          T Offline
                          Tamfub
                          wrote on last edited by
                          #25

                          @JonB @mrjj
                          you're damn right, I didn't notice that. My bad :)
                          Thank you both! Now I will try to pack/unpack correctly.

                          1 Reply Last reply
                          0
                          • T Offline
                            T Offline
                            Tamfub
                            wrote on last edited by
                            #26

                            I managed to fix the (un)packing during the sending/receiving part. Now I miss the final step: create a Pixmap from the received data and show it. To sum up:

                            Server

                            QImage imageObject;
                            imageObject.load(Path/to/image);
                            QPixmap image = QPixmap::fromImage(imageObject);
                            
                            QByteArray ba;              // Construct a QByteArray object
                            QBuffer buffer(&ba);        // Construct a QBuffer object using the QbyteArray
                            image.save(&buffer, "JPG"); // Save the QImage data into the QBuffer
                            
                            
                            qjo.insert("request_type", PHOTO_REQUEST);
                            qjo.insert("photo", QString::fromLatin1(ba.toBase64()));
                            
                            qDebug() << "Size of QString::fromLatin1(ba.toBase64())): " << QString::fromLatin1(ba.toBase64()).size();	// 470184
                            
                            QJsonDocument doc(qjo);
                            QString strJson(doc.toJson(QJsonDocument::Compact));
                            info.append(strJson);
                            ds << info;
                            

                            Client

                            ds.startTransaction();
                            
                            QByteArray risp;
                            ds >> risp;
                            qDebug() << "risp: " << risp;
                            
                            if (!ds.commitTransaction())
                                return;
                            
                            ...
                            
                            QJsonValue photo = obj.take("photo");
                            QByteArray ba = photo.toString().toLatin1();
                            qDebug() << "photo data size (latin): " << photo.toString().toLatin1().size();	// 470184
                            //qDebug() << "photo size (utf8): " << photo.toString().toUtf8().size();
                            QPixmap pm;
                            
                            ???  // Missing part
                            
                            ui->myLabel->setPixmap(pm);
                            

                            ui->myLabel has another Pixmap set at the moment. In the ??? part, I tried:

                            if(!pm.loadFromData(ba, "JPG")){
                                qDebug() << "Error: data could not be loaded.";
                                return;
                            }
                            

                            and it always ended up printing the error message.

                            Then, I read this and tried

                            const uchar * const data = reinterpret_cast<const uchar *>(ba.constData());
                            qDebug() << "uchar size: " << data;
                            
                            QPixmap pixmap = QPixmap::fromImage(
                                QImage(
                                    data,
                                    ui->myLabel->width(),
                                    ui->myLabel->height(),
                                    QImage::Format_RGB888
                                )
                            );
                            

                            The previous Pixmap of ui->myLabel is removed, but now there is a white one. Any ideas?

                            KroMignonK 1 Reply Last reply
                            0
                            • T Tamfub

                              I managed to fix the (un)packing during the sending/receiving part. Now I miss the final step: create a Pixmap from the received data and show it. To sum up:

                              Server

                              QImage imageObject;
                              imageObject.load(Path/to/image);
                              QPixmap image = QPixmap::fromImage(imageObject);
                              
                              QByteArray ba;              // Construct a QByteArray object
                              QBuffer buffer(&ba);        // Construct a QBuffer object using the QbyteArray
                              image.save(&buffer, "JPG"); // Save the QImage data into the QBuffer
                              
                              
                              qjo.insert("request_type", PHOTO_REQUEST);
                              qjo.insert("photo", QString::fromLatin1(ba.toBase64()));
                              
                              qDebug() << "Size of QString::fromLatin1(ba.toBase64())): " << QString::fromLatin1(ba.toBase64()).size();	// 470184
                              
                              QJsonDocument doc(qjo);
                              QString strJson(doc.toJson(QJsonDocument::Compact));
                              info.append(strJson);
                              ds << info;
                              

                              Client

                              ds.startTransaction();
                              
                              QByteArray risp;
                              ds >> risp;
                              qDebug() << "risp: " << risp;
                              
                              if (!ds.commitTransaction())
                                  return;
                              
                              ...
                              
                              QJsonValue photo = obj.take("photo");
                              QByteArray ba = photo.toString().toLatin1();
                              qDebug() << "photo data size (latin): " << photo.toString().toLatin1().size();	// 470184
                              //qDebug() << "photo size (utf8): " << photo.toString().toUtf8().size();
                              QPixmap pm;
                              
                              ???  // Missing part
                              
                              ui->myLabel->setPixmap(pm);
                              

                              ui->myLabel has another Pixmap set at the moment. In the ??? part, I tried:

                              if(!pm.loadFromData(ba, "JPG")){
                                  qDebug() << "Error: data could not be loaded.";
                                  return;
                              }
                              

                              and it always ended up printing the error message.

                              Then, I read this and tried

                              const uchar * const data = reinterpret_cast<const uchar *>(ba.constData());
                              qDebug() << "uchar size: " << data;
                              
                              QPixmap pixmap = QPixmap::fromImage(
                                  QImage(
                                      data,
                                      ui->myLabel->width(),
                                      ui->myLabel->height(),
                                      QImage::Format_RGB888
                                  )
                              );
                              

                              The previous Pixmap of ui->myLabel is removed, but now there is a white one. Any ideas?

                              KroMignonK Offline
                              KroMignonK Offline
                              KroMignon
                              wrote on last edited by KroMignon
                              #27

                              @Tamfub said in Send image inside Json through QTcpSocket:

                              ow I miss the final step: create a Pixmap from the received data and show it. To sum up:

                              Have you take a look at QPixmap documentation? I think you will quickly find QPixmap::loadFromData()...

                              It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                              T 1 Reply Last reply
                              1
                              • KroMignonK KroMignon

                                @Tamfub said in Send image inside Json through QTcpSocket:

                                ow I miss the final step: create a Pixmap from the received data and show it. To sum up:

                                Have you take a look at QPixmap documentation? I think you will quickly find QPixmap::loadFromData()...

                                T Offline
                                T Offline
                                Tamfub
                                wrote on last edited by Tamfub
                                #28

                                @KroMignon
                                Hi.
                                I eventually managed to show the image. I was missing:

                                ba = ba.fromBase64();
                                

                                before pm.loadFromData(...), and now it works. Thanks!

                                1 Reply Last reply
                                1

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved