Solved Send image inside Json through QTcpSocket
-
@Christian-Ehrlicher
Ok, I removed theqjo.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?
-
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.
-
@Tamfub
Dunno, let's start withwhile(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. -
@Christian-Ehrlicher @JonB
Ok, I guess I'll have to revise my protocol, then I'll return to the other problem later :) -
Hi,
@Tamfub said in Send image inside Json through QTcpSocket:
QString string = (QString)dataReceived;
dataReceived is a QByteArray, that cast is completely wrong.
-
@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 replacedout << 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? -
@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 somewhereqDebug(qPrintable(qString))
; or printQString::length()
. -
@SGaist
Hi.
Ok, I guess I should use something likeQString::fromLatin1(array)
, right? -
@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!
-
@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? :)
-
@JonB I already noticed the receivedData in double the sentData, I wrote it before. But I can't understand why.
-
@Tamfub
Because one is aQByteArray
and one is aQString
? You can't send one type, decode it as a different type, and expect them to be the same. -
@Tamfub
Hi
QString is 16 bit. QByteArray is 8bit -
-
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 anotherPixmap
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
ofui->myLabel
is removed, but now there is a white one. Any ideas? -
@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()
... -
@KroMignon
Hi.
I eventually managed to show the image. I was missing:ba = ba.fromBase64();
before
pm.loadFromData(...)
, and now it works. Thanks!