Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Process the RGB format stream in QImage and display it correctly on QLabel



  • I need to read files in .rgb format, process them frame by frame in QImage, and finally display them correctly on the Label. The problem encountered is that it seems that the streaming display is abnormal because of reading the array line by line. How can I correctly read one frame at a time instead of a row of arrays? Please help me improve my code, thank you very much!

    The picture is what it looks like now:
    2f37a508-d2a7-451e-baee-e9e474814b64-image.png

    my code:

    QFile file("/tmp/somergbfile.rgb");
        if (!file.open(QFile::ReadOnly))
        {
            qDebug("Could not open file");
        } else {
            qDebug() << file.fileName() << " opened";
        }
        
        QByteArray array = file.readAll();
        for (int i=0;i<=array.size();i++)
        {
            unsigned char* Data = (unsigned char*)&array.data()[i];
            qDebug() << Data;
            qDebug() << i;
            QImage myImage(Data, 640, 360, QImage::Format_BGR888);
            qDebug() << myImage;
            Sleeper::msleep(33);
            ui->label->setPixmap(QPixmap::fromImage(myImage));
            ui->label->repaint();
            
        }
    


  • @RAKULO said in Process the RGB format stream in QImage and display it correctly on QLabel:

    I need to read files in .rgb format, process them frame by frame in QImage, and finally display them correctly on the Label.
    The problem encountered is that it seems that the streaming display is abnormal because of reading the array line by line.
    How can I correctly read one frame at a time instead of a row of arrays? Please help me improve my code, thank you very much!

    I see many problems with code:

    • A for loop in main thread is not as good idea, you are locking main thread/event loop and GUI cannot be updated
    • Why do you have a active wait, which will locks the main thread and your GUI?
    • Why do you not read frame after frame from the file?

    My suggestion would be to create a "reader" class which will create the QImage for the next frame data.
    So you could read frames from another thread and per signal inform main thread when a QImage is ready to be displayed.



  • @KroMignon Thank you very much for your answer! The purpose of this program is only to play the .rgb format file. So it may be simple and has many imperfections.

    • The for loop will lock the thread, but this is not the most important for the program. What do I need to add to the loop to read each frame array correctly?
    • The part about waiting can be delete now . If I don't add waiting in the previous test, the program will crash.
    • I just want to read frame by frame from the file, but I can't do it. Do you have an example for reference?

    I am still a novice, thanks again for your answer!


  • Lifetime Qt Champion

    @RAKULO said in Process the RGB format stream in QImage and display it correctly on QLabel:

    unsigned char* Data = (unsigned char*)&array.data()[i];

    Why do you create a QImage for every byte in a frame?!



  • @jsulm Thanks for your answer, if it is not needed, how should I correct it to display it correctly? I'm sorry I'm still a novice, please forgive me.


  • Lifetime Qt Champion

    @RAKULO Remove the loop and use the whole QByteArray as data to create the image



  • @RAKULO said in Process the RGB format stream in QImage and display it correctly on QLabel:

    The purpose of this program is only to play the .rgb format file. So it may be simple and has many imperfections.

    Simple is always a good point ;)

    My suggestion is also a way to keep it as simple as possible, the reader could be something like this:

    class RgbReader : public QObject
    {
        Q_OBJECT
        
    public:
        explicit RgbReader(const QString &filename, QObject *parent = nullptr)
            : QObject(parent)
            , mFile(filename)
            , mWidth(640)
            , mHeight(360)
        {
            if (!mFile.open(QFile::ReadOnly))
            {
                qDebug("Could not open file");
            } else {
                qDebug() << mFile.fileName() << " opened";
            }
            
            //QImage::Format_BGR888 use 24bits per pixels (3 bytes)
            mImageSize = 3 * mWidth * mHeight;
        }
        
    signals:
        void nextFrame(QImage frame);
        void noMoreFrame();
        
    public slots:
        void readNextFrame()
        {
            if((mFile.size() - mFile.pos()) < mImageSize)
            {
                emit noMoreFrame();
                return;
            }
            QByteArray array = mFile.read(mImageSize);
            QImage myImage(array.data(), mWidth, mHeight, QImage::Format_BGR888);
            
            // use copy() to detach from local QByteArray()
            emit nextFrame(myImage.copy());
        }
        
    private:
        int mWidth;
        int mHeight;
        int mImageSize;
    }
    

    Then to read the pictures:

    auto reader = new RgbReader("/tmp/somergbfile.rgb");
    
    connect(reader, &RgbReader::nextFrame, this, [this, reader](QImage frame) {
            ui->label->setPixmap(QPixmap::fromImage(frame));
            ui->label->repaint();
            reader->readNextFrame();
    });
    // delete instance on end
    connect(reader, &RgbReader::noMoreFrame, reader,  &QObject::deleteLater);
    
    // read first frame
    reader->readNextFrame();
    


  • @jsulm I think I can study how to implement what you said in my code.
    @KroMignon I tried to use your code, but it seems to be unsuccessful. I can't even read the file. Is it feasible in your environment?



  • @RAKULO said in Process the RGB format stream in QImage and display it correctly on QLabel:

    I tried to use your code, but it seems to be unsuccessful. I can't even read the file. Is it feasible in your environment?

    I don't have tested it, sorry.
    I was just code example to help you to understand my purpose.
    There maybe some typos (I found some of them and change them in my previous post).



  • @KroMignon Thanks for your reply anyway, I will continue to try it, hope there will be good news!



  • Thank you everyone for your help. After a period of hard work, it will finally work!
    I'm sorry that I still used the for loop to make it work, and I was so stupid to make it increment by 6403603 each iteration.
    Although it is not very good code, it finally works! Thanks again!

        unsigned char* Data;
        QByteArray array = file.readAll();
        for (int i=0;i<=array.size();i+=691200)
        {
        Data = (unsigned char*)&array.data()[i];
        qDebug() << Data;
        QImage myImage(Data, 640, 360, QImage::Format_BGR888);
        qDebug() << myImage;
        Sleeper::msleep(33);
        ui->label->setPixmap(QPixmap::fromImage(myImage));
        ui->label->repaint();
        }
    

Log in to reply