How to make a QImage or QPixmap semi-transparent - or why is setAlphaChannel obsolete?

微笑、不失礼 提交于 2019-12-10 04:19:17

问题


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));  

回答1:


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.




回答2:


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));
}



回答3:


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.



来源:https://stackoverflow.com/questions/4172661/how-to-make-a-qimage-or-qpixmap-semi-transparent-or-why-is-setalphachannel-obs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!