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 18.9k 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.
  • Christian EhrlicherC Christian Ehrlicher

    Because you unpack your json structure wrong I would guess. In the first example you pack it twice as you can see.

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

    @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 1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #13

      Sorry but you should start with one problem first. Properly pack/unpack the data in your json string. Then we can go over to the next problem.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      2
      • 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