Reputation: 1964
I am trying to send an image over a network socket (TCP) in Qt. It works with small images (less than 8192 bytes) but won't handle larger images due to the receiving end not knowing how large it should be (hence not waiting to receive all data before trying to display and image).
I have tried adding the data size to the start of the array and reading it at the other end but I get numbers at the receiving end that do not match what was inserted before sending. Can anyone see what I am doing wrong?
void Screenshot_controller::serializeImage(std::string fileType, QImage imageToSerialize, QByteArray *imageStream)
{
QBuffer imageBuffer(imageStream);
const char * extention = fileType.c_str();
imageToSerialize.save(&imageBuffer, extention);
//QString dataType = "Img";
//imageStream->insert(0, dataType);
qint32 size = imageStream->size();
imageStream->insert(0, size);
}
//Called using a signal when data is received on the socket
void Screenshot_controller::readyRead()
{
qDebug() << "Client Reading...";
QByteArray rxByteArray;
rxByteArray = rxSocket->readAll();
qint32 size = rxByteArray.at(0);
QImage imageToDisplay;
deSerializeImage("BMP", &imageToDisplay, rxByteArray);
displayImage(imageToDisplay);
}
Upvotes: 1
Views: 799
Reputation: 73041
I believe your problem is this:
imageStream->insert(0, size);
If you look at the QByteArray man page you will see that the only implementation of the insert() method that can take a qint32 as its second argument is this one:
QByteArray & insert (int i, char ch);
… which means that you are inserting a single byte at the front of your QByteArray rather than four bytes. That truncates the value: the problem with that is that a single byte can't hold any value greater than 255, and most images are going to be more than 255 bytes long.
Similarly, in the decoding step, you have this:
qint32 size = rxByteArray.at(0);
Again, the at() method returns a single byte, thus your size value is going to be no larger than 255 regardless of how big your original image was.
The fix for this would be to insert 4 bytes (because sizeof(qint32)==4) that represent the size value instead. Something like this would insert the value (using a well-defined-endianness):
qint32 beSize = htonl(size);
imageStream->insert(0, (const char *) &beSize, sizeof(beSize));
… and then something like this could extract it again:
qint32 beSize = *((const qint32 *) rxByteArray.constData());
qint32 size = ntohl(beSize);
Upvotes: 1
Reputation: 1908
There is no method QByteArray::insert(int,uint32);
Your uint32 will be cast down to char and you end up with QByteArray::insert(int,char);
You might consider using
QByteArray(0,(const char *)&size,sizeof(uint32));
If endianess between multiple platforms is not an issue.
Upvotes: 1