0

我正在尝试为 Qt5 中的 qwebview 创建色度键。这意味着我需要使特定颜色透明(其他小部件应该通过具有该颜色的 webview 像素可见)。我发现它可以使用 QPainter::CompositionMode 操作来完成,但不能让它工作。

例如,我需要让 webview 的所有黑色像素都是透明的(应该在运行时更改源颜色)。

我在课堂上重新实现了 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);

但我不知道如何将白色转换为透明。

4

1 回答 1

0

我找到了一个解决方案,但它消耗了大量的 CPU。

首先需要设置

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 下渲染一个视频小部件。所以 WebView::paintEvent 每秒调用大约 25 次,在我的 PC 上的窗口模式下,每次调用大约需要 20-25 毫秒。在全屏模式下,它会占用大约 100% 的 CPU 内核。

于 2015-03-22T15:55:43.770 回答