Search code examples
qtarraysqpixmapqdatastream

QPixmap.loadFromData() does not load image from QByteArray


I'm creating a socket-based program to send a screenshot from one user to another user. I need to convert a screenshot to a byte array before sending. After I convert my screenshot to a QByteArray I insert 4 bytes to the beginning of the array to mark that it is a picture (it is the number 20 to tell me it is a picture and not text or something else).

After I send the byte array via a socket to other user, when it is received I read the first 4 bytes to know what it is. Since it was a picture I then convert it from a QByteArray to QPixmap to show it on a label. I use secondPixmap.loadFromData(byteArray,"JPEG") to load it but it not load any picture.

This is a sample of my code:

 void MainWindow::shootScreen()
 {
     originalPixmap = QPixmap(); // clear image for low memory situations
                             // on embedded devices.
     originalPixmap = QGuiApplication::primaryScreen()->grabWindow(0);
     scaledPixmap = originalPixmap.scaled(500, 500);

     QByteArray bArray;
     QBuffer buffer(&bArray);
     buffer.open(QIODevice::WriteOnly);
     originalPixmap.save(&buffer,"JPEG",5);

     qDebug() << bArray.size() << "diz0";

     byteArray= QByteArray();

     QDataStream ds(&byteArray,QIODevice::ReadWrite);
     int32_t c = 20;
     ds << c;
     ds<<bArray;
 }

 void MainWindow::updateScreenshotLabel()
 {
     this->ui->label->setPixmap(secondPixmap.scaled(this->ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
 }

void MainWindow::on_pushButton_clicked()
{
    shootScreen();
}

void MainWindow::on_pushButton_2_clicked()
{
    secondPixmap = QPixmap();
    QDataStream ds(&byteArray,QIODevice::ReadOnly);
    qint32 code;
    ds>>code;
    secondPixmap.loadFromData(byteArray,"JPEG");
    updateScreenshotLabel();
}

Solution

  • Your MainWindow::on_pushButton_2_clicked implementation looks odd. You have...

    QDataStream ds(&byteArray,QIODevice::ReadOnly);
    

    which creates a read-only QDataStream that will read it's input data from byteArray. But later you have...

    secondPixmap.loadFromData(byteArray,"JPEG");
    

    which attempts to read the QPixmap directly from the same QByteArray -- bypassing the QDataStream completely.

    You can also make use of the QPixmap static members that read from/write to a QDataStream. So I think you're looking for something like...

    QDataStream ds(&byteArray,QIODevice::ReadOnly);
    qint32 code;
    ds >> code;
    if (code == 20)
      ds >> secondPixmap;
    

    And likewise for your MainWindow::shootScreen implementation. You could reduce your code a fair bit by making use of QDataStream & operator<<(QDataStream &stream, const QPixmap &pixmap).