Создание хроматического ключа для qwebview в Qt5

Я пытаюсь создать хроматический ключ для qwebview в Qt5. Это означает, что мне нужно сделать определенный цвет прозрачным (другие виджеты должны быть видны через пиксели веб-просмотра с этим цветом). Я обнаружил, что это можно сделать с помощью операций QPainter::CompositionMode, но не могу заставить это работать.

Например, мне нужно сделать все черные пиксели веб-просмотра прозрачными (исходный цвет должен быть изменен во время выполнения).

Я переделал QWebView::paintEvent в своем классе (получил часть кода из исходников Qt), но не знаю, что делать дальше

WebView::paintEvent(QPaintEvent *event) {
    if (!page()) return;
    QWebFrame *frame = page()->mainFrame();
    QPainter painter(this);
    painter.setRenderHints(renderHints());
    painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
    frame->render(&painter, event->region());

}

Я нашел способ сделать любой исходный цвет белым с помощью следующего кода:

QWebFrame *frame = page()->mainFrame();
QImage source_image(size(), QImage::Format_ARGB32_Premultiplied);
QImage result_image(size(), QImage::Format_ARGB32_Premultiplied);

QPainter imagePainter(&source_image);
imagePainter.setRenderHints(renderHints());
frame->render(&imagePainter, event->region());
imagePainter.end();

QImage mask = source_image.createMaskFromColor(qRgb(0x00,0x00,0x00)); // Source color

QPainter resultPainter(&result_image);
resultPainter.drawImage(source_image.rect(), source_image);
resultPainter.setCompositionMode(QPainter::CompositionMode_Screen);
resultPainter.drawImage(source_image.rect(), mask);

QPainter painter(this);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.drawImage(0, 0, result_image);

Но я не знаю, как преобразовать белый цвет в прозрачный.


person VaMpir    schedule 19.03.2015    source источник


Ответы (1)


Я нашел решение, но оно потребляет много ресурсов процессора.

Сначала требуется установить

setStyleSheet("QWebView { background: transparent }");
setAttribute(Qt::WA_OpaquePaintEvent, true);

где-то в конструкторе WebView (просто забыл упомянуть об этом в первом сообщении). Затем переопределите paintEvent:

void WebView::paintEvent(QPaintEvent *event)
{
    if (!page())
        return;

    QWebFrame *frame = page()->mainFrame();
    QPainter painter(this);
    QColor chroma_color(0, 0, 0); // A color that should be transparent
    float opacity_level = 0.9; // WebView opacity

    m_render_pixmap.fill(Qt::transparent);

    QPainter pixmapPainter(&m_render_pixmap);
    pixmapPainter.setRenderHints(renderHints());
    frame->render(&pixmapPainter, event->region());
    pixmapPainter.end();
    m_render_pixmap.setMask(m_render_pixmap.createMaskFromColor(
        chroma_color, Qt::MaskInColor));

    painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
    painter.setOpacity(opacity_level);
    painter.drawPixmap(QPoint(event->rect().left(), event->rect().top()), m_render_pixmap, event->rect());
    painter.end();
}

m_render_pixmap — это экземпляр QPixmap. Я не хочу воссоздавать его каждый раз, когда вызывается paintEvent. Я просто воссоздаю его на resizeEvent

void WebView::resizeEvent(QResizeEvent *event)
{
    QWebView::resizeEvent(event);
    m_render_pixmap = QPixmap(size());
}

Приведенный выше код отлично работает, но в моем случае я хочу отобразить видео-виджет под веб-просмотром. Таким образом, WebView::paintEvent вызывает около 25 раз в секунду, и каждый вызов занимает около 20-25 мс в оконном режиме на моем ПК. И занимает около 100% одного из ядер процессора в полноэкранном режиме.

person VaMpir    schedule 22.03.2015