Qt绘图图标使用颜色和alpha地图

时间:2014-07-24 20:50:32

标签: qt icons alpha qpainter

我想绘制不同颜色的图标(只有一种颜色)。为此,我想导入一个alpha纹理,然后将其与应用程序中的给定颜色组合。

结果应该是,当不透明度为1时,当alpha-map的不透明度为0并且应该绘制使用的颜色时,不会在背景上绘制任何内容。

由于您可以手动设置合成模式(QPainter),因此应在QPainter::setCompositionMode中的某处隐藏一个搜索。但我不能按照自己的意愿去工作。

有人有想法吗?

提前致谢。

编辑:这是一个小图解,解释了我想做什么。我想使用如图所示的Alpha-Map,然后使用颜色层来创建我的图标。重要的是,背景保持透明。

enter image description here

4 个答案:

答案 0 :(得分:4)

你可以使用QPainter这样做:

QColor color;
// set color value

// load gray-scale image (an alpha map)
QPixmap pixmap = QPixmap(":/images/earth.png");

// initialize painter to draw on a pixmap and set composition mode
QPainter painter(&pixmap);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);

painter.setBrush(color);
painter.setPen(color);

painter.drawRect(pixmap.rect());

// Here is our new colored icon!
QIcon icon = QIcon(pixmap);

这是灰度图像和两个彩色图标,我使用上面的代码(QPixmap.save()方法): icons

答案 1 :(得分:2)

DestinationIn构图模式可以解决问题。

  1. 使用SourceOver的默认合成模式绘制颜色图层。

  2. 使用DestinationIn合成模式绘制alpha图层。

  3. 例如:

    screenshot

    // https://github.com/KubaO/stackoverflown/tree/master/questions/alpha-mask-24943711
    #include <QtWidgets>
    
    QImage icon(int size) {
       QImage image{size, size, QImage::Format_ARGB32_Premultiplied};
       image.fill(Qt::transparent);
       QPainter p(&image);
       p.setRenderHint(QPainter::Antialiasing);
       p.setPen(Qt::NoPen);
       p.translate(image.rect().center());
       p.scale(image.width()/2.2, image.height()/2.2);
       p.setBrush(Qt::white);
       p.drawEllipse(QRectF{-.5, -.5, 1., 1.});
       p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
       p.setBrush(Qt::transparent);
       p.drawEllipse(QRectF{-.3, -.3, .6, .6});
       for (auto angle : {0., 100., 150.}) {
          p.save();
          p.rotate(angle);
          p.drawRect(QRectF{-.1, 0, .2, -1.});
          p.restore();
       }
       return image;
    }
    
    QImage checkers(int size) {
       QImage img{size*2, size*2, QImage::Format_ARGB32_Premultiplied};
       QPainter p(&img);
       p.fillRect(0, 0, size, size, Qt::darkGray);
       p.fillRect(size, size, size, 2*size, Qt::darkGray);
       p.fillRect(size, 0, size, size, Qt::lightGray);
       p.fillRect(0, size, size, size, Qt::lightGray);
       return img;
    }
    
    void drawColorIcon(QPainter & p, QColor color, const QImage & alpha)
    {
      p.save();
      p.setCompositionMode(QPainter::CompositionMode_SourceOver);
      p.fillRect(QRect{0, 0, alpha.width(), alpha.height()}, color);
      p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
      p.drawImage(0, 0, alpha);
      p.restore();
    }
    
    QImage drawColorIconProof(QColor color, const QImage & alpha) {
       QImage result{alpha.size(), alpha.format()};
       QPainter p(&result);
       drawColorIcon(p, color, alpha);
       p.setCompositionMode(QPainter::CompositionMode_DestinationAtop);
       p.fillRect(alpha.rect(), {checkers(10)});
       return result;
    }
    
    int main(int argc, char *argv[])
    {
       QApplication app{argc, argv};
       QLabel label;
       label.setPixmap(QPixmap::fromImage(drawColorIconProof("orangered", icon(200))));
       label.show();
       return app.exec();
    }
    

答案 2 :(得分:0)

我找到了解决方案。然而,我没有使用像我在第一篇文章中使用的alpha贴图的透明图形,而是使用黑/白图形,其中黑色像素是透明的而白色像素不是(=渲染)。

// ++++ in constructor ++++ 
QImage alphaMap = QImage(fileName);

QColor color;

// ++++ in paint Event ++++

QPainter painter(this);
painter.setRenderHints(QPainter::RenderHint::Antialiasing);
painter.setRenderHints(QPainter::RenderHint::HighQualityAntialiasing);

// draw icon
QImage renderedIcon(alphaMap);  
// fill with color
renderedIcon.fill(color);                   
// set alpha-map, black pixels -> opacity of 0, white pixels -> opacity 1
renderedIcon.setAlphaChannel(alphaMap);     

painter.drawImage(this->rect(), renderedIcon);  // draw image to QWidget

答案 3 :(得分:-1)

我不太明白这个问题,但可能你可以使用QGraphicsColorizeEffect类吗? QGraphicsColorizeEffect