如何使 QImage 或 QPixmap 半透明 - 或者为什么 setAlphaChannel 过时?

发布于 2024-10-03 00:50:23 字数 701 浏览 7 评论 0原文

4.7 并喜欢在 qgraphicsview 上叠加两个图像。顶部的图像应是半透明的,以便能够透过它看到。最初,两个图像都是完全不透明的。我期望存在一些为每个像素设置全局 alpha 值的函数,但似乎没有这样的函数。最接近的是 QPixmap::setAlphaChannel(const QPixmap & alphaChannel),但是,自 Qt-4.6 以来它被标记为过时。相反,手册引用了 QPainter 的 CompositionModes,但我没有成功地像我想要的那样为不透明图像添加透明度。 有人能给我指出一个工作示例或分享一些代码吗?

编辑: 我几乎为自己的答案感到抱歉,现在就在提出问题几个小时后。 从这篇文章中我发现以下代码可以完成这项工作。我只是想知道这是否被认为比按像素修改 alpha 值“更好”(通常转化为更快)。

QPainter p; 
p.begin(image);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(image->rect(), QColor(0, 0, 0, 120));
p.end();            
mpGraphicsView->scene()->addPixmap(QPixmap::fromImage(image->mirrored(false,true),0));  

4.7 and like to overlay two images on a qgraphicsview. The image on top shall be semi-transparent to allow to see through it. Initially both images are fully opaque. I expected some function for setting a global alpha-value for each pixel to exist, but it seems like there is no such function. The closest thing to it is QPixmap::setAlphaChannel(const QPixmap & alphaChannel), which, however, is marked as obsolete since Qt-4.6. Instead the manual refers to the CompositionModes of QPainter, but I don't succeed to add transparency to an opaque image like I want.
Could anyone point me to a working example or share some code?

Edit:
I'm almost sorry for having an own answer, now just a few hours after asking the question.
From this article I figured out that the following code does the job. I just wonder if this is considered "better" (which often translates to faster) than modifying the alpha values pixelwise.

QPainter p; 
p.begin(image);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(image->rect(), QColor(0, 0, 0, 120));
p.end();            
mpGraphicsView->scene()->addPixmap(QPixmap::fromImage(image->mirrored(false,true),0));  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冰葑 2024-10-10 00:50:23

使用您的画家对象并设置不透明度。

void ClassName::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setOpacity(1.00);  //0.00 = 0%, 1.00 = 100% opacity.
    painter.drawPixmap(QPixmap(path));
}

Use your painter object and set the opacity.

void ClassName::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setOpacity(1.00);  //0.00 = 0%, 1.00 = 100% opacity.
    painter.drawPixmap(QPixmap(path));
}
樱花细雨 2024-10-10 00:50:23

Qt 的组合演示可能有点令人生畏,因为它们试图展示一切都关闭了。希望演示加上 QPainter 文档 对您有所帮助。您想要使用 CompositionMode::SourceOver 并确保图像转换为 ARGB32(预乘)。来自文档:

当绘画设备是 QImage 时,图像格式必须设置为 Format_ARGB32Premultiplied 或 Format_ARGB32 以使合成模式产生任何效果。为了提高性能,预乘版本是首选格式。

The Qt's composition demo can be a bit intimidating, because they try to show everything off. Hopefully the demo plus the QPainter documentation is helpful for you. You want to use CompositionMode::SourceOver and make sure that the images are converted to ARGB32 (premultiplied). From the documentation:

When the paint device is a QImage, the image format must be set to Format_ARGB32Premultiplied or Format_ARGB32 for the composition modes to have any effect. For performance the premultiplied version is the preferred format.

々眼睛长脚气 2024-10-10 00:50:23

首先,对于图像的内部操作,通常需要使用QImage而不是QPixmap,因为对QPixmap的直接访问功能受到限制。原因是 QPixmap 存储在渲染设备上,例如 X 服务器上的像素图或 GL 纹理。另一方面,从 QPixmap 到 QImage 并返回的成本很高,因为它通常会导致从显卡内存复制到主内存并返回。

在我看来,您需要一个仅更改像素的 alpha 值的操作,保持其原始值不变,以进行位块传输。一种并不优雅但有效的解决方案如下:

for (int y = 0; y < image.height() ++y) {
  QRgb *row = (QRgb*)image.scanLine(y);
  for (int x = 0; x < image.width(); ++x) {
    ((unsigned char*)&row[x])[3] = alpha;
  }
}

注意:更改 QImage 的每个像素,然后执行 Painter.drawImage() 比用相应的 alpha 绘制每个像素要快得多手工。

First of all, for internal operations on images, often you need to use QImage instead of QPixmap, as the direct access functionality to QPixmap is restricted. Reason is that QPixmaps are stored on the rendering device, e.g. pixmap on the X server or GL texture. On the other hand, going from QPixmap to QImage and back is expensive as it often results in copying from the graphics card memory to main memory and back.

As I see it you need an operation that changes only the alpha value of the pixels, leaving their original values intact, for blitting. One solution that is not elegant, but works, is the following:

for (int y = 0; y < image.height() ++y) {
  QRgb *row = (QRgb*)image.scanLine(y);
  for (int x = 0; x < image.width(); ++x) {
    ((unsigned char*)&row[x])[3] = alpha;
  }
}

Note: it is much faster to alter each pixel of the QImage, and then do painter.drawImage() than drawing each pixel with corresponding alpha by hand.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文