How do I use paintEvent to paint a QImage from video data?

208 Views Asked by At

I construct a QImage with data I get from an API call. This QImage I will draw with the overridden paintEvent(QPaintEvent*) method into a widget. From the function that does the API call I emit a signal that sends the grabbed data to a slot that constructs the QImage. With this process there is no problem. The data is transfered and the construct of the image works.

My question is how can I use the constucted image in the overridden paintEvent? I can open a image from the disk and draw it into the widget, but this works from inside the paintEvent() method. With the API call I got the data from outside.

class GrabberClass : public QObject
{
    Q_OBJECT

public:
    GrabberClass(QObject* parent = nullptr);
    virtual ~GrabberClass();
    bool applyFrameCallback();
    bool getFrameData(DtMxData* data);
    bool startProcessing();
    
private:
    RenderClass *m_renderClass;
    DtMxProcess *m_process;
    DTAPI_RESULT m_result;
    DtFrame *m_Frame

signals:
    void sendFrameData(uchar* pData, int width, int height, int bytesPerRow);

};

//GrabberClass.cpp
//constructor
GrabberClass::GrabberClass(QObject *parent) :
    m_renderClass(new RenderClass)
{
   const bool connected = QObject::connect(this, &GrabberClass::sendFrameData, m_renderClass, &RenderClass::receiveFrameData, Qt::DirectConnection);
   Q_ASSERT(connected); //value is true.
}
        
bool GrabberClass::applyFrameCallback()
{
    auto frameCallback = [](DataContainer* frameData, void* pContext)
    {
        ((GrabberClass*)pContext)->getFrameData(frameData); 
    };
    
    m_result = m_process->AddMatrixCbFunc(frameCallback, this);
    if (m_result != DTAPI_OK) {
        return false;
    }
    return true;
}

bool GrabberClass::grabFrame(DataContainer* frameData)
{   
    m_Frame = frameData->m_Rows[IN_ROW].m_CurFrame;
            
    uchar* pData = m_Frame->m_Video->m_Planes->m_pBuf;
    int bytesPerRow = m_Frame->m_Video->m_Planes->m_Stride;
    int frameWidth = m_Frame->m_Video->m_Width;
    int frameHeight = m_Frame->m_Video->m_Height;
            
    emit sendFrameData(pData, frameWidth, frameHeight, bytesPerRow);
            
    return true;
}
       

//Render Class.h
class RenderClass : public QOpenGLWidget {
    Q_OBJECT

public:
    RenderClass(QWidget* parent = nullptr);
    virtual ~RenderClass();

private:
    QImage m_srcImage;

protected:
    void paintEvent(QPaintEvent*);

public slots:
    void receiveFrameData(uchar* pData, int width, int height, int bytesPerRow);
    
}; 

//RenderClass.cpp
VideoMonitor::VideoMonitor(QWidget* parent) :
    QOpenGLWidget(parent),
    m_srcImage(nullptr)
{
}

void RenderClass::receiveFrameData(uchar* pData, int width, int height, int bytesPerRow) 
{
    m_srcImage = QImage(pData, width, height, bytesPerRow, QImage::Format_Indexed8);
            
    qDebug() << "Slot is called." << m_srcImage; //QImage is constructed with valid data
    QWidget::update();
}
            
void RenderClass::paintEvent(QPaintEvent*)
{
    if (!m_srcImage.isNull()) { //m_srcImage is null
        QPainter painter(this);
        painter.drawImage(this->rect(), m_srcImage);
        painter.end();
        qDebug() << "Draw image.";
    }
    else {
        qDebug() << "QImage is null";
    }
}

I'am new to C++, so it would be nice if someone of you can give me an advice and explaination.

0

There are 0 best solutions below