gpt4 book ai didi

c++ - 渲染一个透明的 QLabel

转载 作者:行者123 更新时间:2023-11-28 01:15:22 25 4
gpt4 key购买 nike

我正在尝试使用 QLabel 作为一个强大的工具来将一些带有 CSS 的文本渲染到纹理中。获取图像后,在 OpenGL 中形成纹理并丢弃原始 Qt 对象。之后,我在普通 OpenGL(无 Qt)渲染管道中使用该纹理作为任何其他纹理。

但是,我在处理背景透明度时遇到了问题。某些东西 - 可能是一些我不知道的 Qt 设置 - 似乎弄乱了我的设置。

经过一些简化,我的纹理是这样产生的:

QLabel label;
label.setAttribute(Qt::WA_TranslucentBackground, true);

const QString styleSheet{"color : #00bbbb; background-color : rgba(0,0,0,0);"
"font-family: 'Calibri'; text-decoration: none; margin: 5px;"};
label.setWordWrap(true);
label.setAutoFillBackground(false);
label.setStyleSheet(styleSheet);

QFont font = label.font();
font.setPointSizeF(12.0f);
label.setFont(font);

// set text
label.setText(QString("The quick brown fox jumps over the lazy dog"));

// render
label.adjustSize();
label.updateGeometry();

std::unique_ptr<QImage> imgTexture = std::make_unique<QImage>(label.size(), QImage::Format_RGBA8888);
QPainter painter(imgTexture.get());
label.render(&painter);

uint8_t *bits = imgTexture->bits();
std::cout << int(bits[0]) << " " << int(bits[1]) << " " << int(bits[2]) << " " << int(bits[3]) << std::endl;

输出 - 生成图像左上角像素的值 - 是:

205 205 205 205

而不是我预期的 0 0 0 0。因此,问题已经出现在这一点上,而不是稍后出现在我对纹理的 OpenGL 处理中。最终我的输出是:

enter image description here

正如所见,背景并不像预期的那样完全透明。


更新

根据 G.M. 的建议,我尝试了 setCompositionMode(没有效果),但也尝试了其他画家设置。显然将 QPainter::setBackgroundMode 设置为 Qt::OpaqueMode 更进一步:

enter image description here

Qt 手册说:

Qt::TransparentMode (the default) draws stippled lines and text without setting the background pixels. Qt::OpaqueMode fills these space with the current background color.

因此,默认设置似乎是在不存在字母的任何地方更改输出图像的原始像素。因此,透明的 (0,0,0,0) 没有被绘制,并且之前的颜色(由于某种原因显然是 205, 205, 205, 205)保持不变。

强制绘制背景会更新所有像素,但仅限于字母附近的像素。我现在需要弄清楚如何强制将 所有 像素清除为 CSS 中指定的颜色。

更新 显然它并不像看起来那么简单。我尝试了 painter.eraseRect(0, 0, width, height); 但这会将矩形清除为白色,忽略 CSS 设置。

最佳答案

结合实验结果和一些评论。该行为是以下各项的组合:

  • QImage 构造有一些图像区域时,该区域未初始化。

    QImage::QImage(int width, int height, QImage::Format format)

    Constructs an image with the given width, height and format.

    A null image will be returned if memory cannot be allocated.

    Warning: This will create a QImage with uninitialized data. Call fill() to fill the image with an appropriate pixel value before drawing onto it with QPainter.

    在 Debug模式下的 Visual Studio 中,未初始化的区域使用 0xCD 进行初始化。在 Release 中会是一些垃圾

  • 默认情况下,当使用QPainter 绘制文本时,背景保持不变。画家只是将字形添加到目标图像上先前存在的任何内容(在我们的例子中:未初始化的区域)。

    void QPainter::setBackgroundMode(Qt::BGMode mode)

    Sets the background mode of the painter to the given mode

    Qt::TransparentMode (the default) draws stippled lines and text without setting the background pixels. Qt::OpaqueMode fills these space with the current background color.

    Note that in order to draw a bitmap or pixmap transparently, you must use QPixmap::setMask().

    因此,为了按照 QLabel 的 CSS 中的设置绘制背景像素,需要将模式更改为 Qt::OpaqueMode。然而,这只在字形周围绘制,而不是整个区域。我们需要先手动清理整个区域。

  • 图像可以通过QPainter::fillRect清除:

    void QPainter::fillRect(int x, int y, int width, int height, const QColor &color)

    This is an overloaded function.

    Fills the rectangle beginning at (x, y) with the given width and height, using the given color.

    This function was introduced in Qt 4.5.

    但有一个警告 - 所有 QPainter 操作都与底层图像混合。默认情况下,它会考虑绘图颜色的 alpha channel 。因此,如果你用 (0,0,0,0) 绘画,你会得到......没有变化。混合操作由以下因素控制:

    void QPainter::setCompositionMode(QPainter::CompositionMode mode)

    Sets the composition mode to the given mode.

    Warning: Only a QPainter operating on a QImage fully supports all composition modes. The RasterOp modes are supported for X11 as described in compositionMode().

    See also compositionMode().

enum QPainter::CompositionMode

Defines the modes supported for digital image compositing. Composition modes are used to specify how the pixels in one image, the source, are merged with the pixel in another image, the destination. [...] When a composition mode is set it applies to all painting operator, pens, brushes, gradients and pixmap/image drawing.

Constant Value Description

QPainter::CompositionMode_SourceOver 0 This is the default mode. The alpha of the source is used to blend the pixel on top of the destination.

QPainter::CompositionMode_DestinationOver 1 The alpha of the destination is used to blend it on top of the source pixels. This mode is the inverse of CompositionMode_SourceOver.

QPainter::CompositionMode_Clear 2 The pixels in the destination are cleared (set to fully transparent) independent of the source.

QPainter::CompositionMode_Source 3 The output is the source pixel. (This means a basic copy operation and is identical to SourceOver when the source pixel is opaque).

QPainter::CompositionMode_Destination 4 The output is the destination pixel. This means that the blending has no effect. This mode is the inverse of CompositionMode_Source.

[...] (30 more modes...)

因此,在调用fillRect之前,需要将默认的SourceOver替换为Source

  • 清除也可以通过QImage::fill来完成。绘制模式更容易,不会造成困惑!

    不幸的是,任一解决方案(QImage::fillQPainter::fillRect)都需要明确指定背景颜色。它不能只从 QLable 的 CSS 中读取。


附言我不知道如何 block 引用表格:(

关于c++ - 渲染一个透明的 QLabel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58889139/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com