Рендеринг QImage на QGLWidget плагина QML
Я пытаюсь написать плагин QML, который читает кадры из видео (используя пользовательский виджет для этой задачи, а не QtMultimedia/Phonon), и каждый кадр конвертируется в QImage
RGB888, а затем отображается на QGLWidget
(по причинам производительности). Сейчас на экране ничего не нарисовано, и экран постоянно остается белым.
Важно отметить, что у меня уже есть все это без QGLWidget
, поэтому я знаю, что проблема заключается в настройке и рисовании на QGLWidget.
Плагин регистрируется в:
qmlRegisterType<Video>(uri,1,0,"Video");
так Video
это основной класс плагина. По конструктору имеем:
Video::Video(QDeclarativeItem* parent)
: QDeclarativeItem(parent), d_ptr(new VideoPrivate(this))
{
setFlag(QGraphicsItem::ItemHasNoContents, false);
Q_D(Video);
QDeclarativeView* view = new QDeclarativeView;
view->setViewport(&d->canvas()); // canvas() returns a reference to my custom OpenGL Widget
}
Прежде чем я прыгну к canvas
объект, позвольте мне сказать, что я перегружен Video::paint()
так это называет canvas.paint()
во время прохождения QImage
как параметр, я не знаю, является ли это правильным способом сделать это, поэтому я хотел бы получить несколько советов по этому поводу:
void Video::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
Q_UNUSED(painter);
Q_UNUSED(widget);
Q_UNUSED(option);
Q_D(Video);
// I know for sure at this point "d->image()" is valid, but I'm hiding the code for clarity
d->canvas().paint(painter, option, d->image());
}
canvas
объект объявлен как GLWidget canvas;
и заголовок этого класса определяется как:
class GLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit GLWidget(QWidget* parent = NULL);
~GLWidget();
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image);
};
Кажется довольно просто. Теперь реализация QGLWidget
является следующим:
GLWidget::GLWidget(QWidget* parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
// Should I do something here?
// Maybe setAutoFillBackground(false); ???
}
GLWidget::~GLWidget()
{
}
И наконец:
void GLWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QImage* image)
{
// I ignore painter because it comes from Video, so I create a new one:
QPainter gl_painter(this);
// Perform drawing as Qt::KeepAspectRatio
gl_painter.fillRect(QRectF(QPoint(0, 0), QSize(this->width(), this->height())), Qt::black);
QImage scaled_img = image->scaled(QSize(this->width(), this->height()), _ar, Qt::FastTransformation);
gl_painter.drawImage(qRound(this->width()/2) - qRound(scaled_img.size().width()/2),
qRound(this->height()/2) - qRound(scaled_img.size().height()/2),
scaled_img);
}
Что мне не хватает?
Первоначально я задавал этот вопрос на форуме Qt, но не получил ответов.
2 ответа
Решено. Проблема заключалась в том, что я пытался создать новый контекст GL в своем плагине, когда мне нужно было извлечь контекст GL из приложения, которое его загрузило.
Этот код был очень полезен, чтобы понять, как этого добиться.
Кстати, я обнаружил, что материал был нарисован внутри view
, Просто мне нужно было выполнить view->show()
, но это создало другое окно, которое было не то, что я искал. Ссылка, которой я поделился выше, имеет ответ.
Я думаю, что вы должны нарисовать свой glwidget, используя функции opengl.
Один из возможных способов - переопределить метод paintGL() в GLWidget, а затем нарисовать изображение с помощью glDrawPixels().
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(buffer.width(), buffer.height(), GL_RGBA, GL_UNSIGNED_BYTE, buffer.bits());
Где буфер - это объект QImage, который необходимо преобразовать с помощью статического метода QGLWidget::converrtToGLFormat().
Посмотрите на этот источник для справки: https://github.com/nayyden/ZVector/blob/master/src/GLDebugBufferWidget.cpp