Как сделать QImage или QPixmap полупрозрачным — или почему setAlphaChannel устарел?

4.7 и хотели бы наложить два изображения на qgraphicsview. Изображение сверху должно быть полупрозрачным, чтобы его можно было видеть сквозь него. Изначально оба изображения полностью непрозрачны. Я ожидал, что какая-то функция для установки глобального альфа-значения для каждого пикселя существует, но похоже, что такой функции нет. Ближе всего к нему QPixmap::setAlphaChannel(const QPixmap & alphaChannel), который, однако, помечен как устаревший, начиная с Qt-4.6. Вместо этого руководство ссылается на CompositionModes QPainter, но мне не удается добавить прозрачность к непрозрачному изображению, как я хочу. Может ли кто-нибудь указать мне на рабочий пример или поделиться кодом?

Редактировать: Мне почти жаль, что у меня есть собственный ответ, всего через несколько часов после того, как я задал вопрос. Из этой статьи я понял, что следующий код работает. Мне просто интересно, считается ли это «лучше» (что часто означает «быстрее»), чем изменение альфа-значений по пикселям.

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

person FFox    schedule 13.11.2010    source источник


Ответы (3)


демонстрация композиции Qt может немного пугать, поскольку они пытаются показать все выключено. Надеемся, что демонстрация плюс документация по QPainter помогут вам. Вы хотите использовать CompositionMode::SourceOver и убедитесь, что изображения преобразованы в ARGB32 (с предварительным умножением). Из документации:

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.

person bjoernz    schedule 13.11.2010
comment
спасибо, это сработало для моей проблемы, я использовал QPainter::CompositionMode_Source :) - person jamk; 24.01.2013

Используйте свой объект рисования и установите непрозрачность.

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

Во-первых, для внутренних операций с изображениями часто нужно использовать QImage вместо QPixmap, так как функциональность прямого доступа к QPixmap ограничена. Причина в том, что QPixmaps хранятся на устройстве рендеринга, например. растровое изображение на сервере X или текстуре GL. С другой стороны, переход от QPixmap к QImage и обратно обходится дорого, поскольку часто приводит к копированию из памяти видеокарты в основную память и обратно.

Насколько я понимаю, вам нужна операция, которая изменяет только альфа-значение пикселей, оставляя их исходные значения нетронутыми, для блитинга. Одно решение, которое не является элегантным, но работает, заключается в следующем:

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(), чем рисовать каждый пиксель с соответствующей альфой вручную.

person ypnos    schedule 13.11.2010