Я хочу реализовать метод, который уменьшает альфа каждого пикселя в QPixmap (4.8) на 1, каждый раз, когда он вызывается. Между вызовами могут быть добавлены новые линии к изображению (с альфа 255). Кроме того, я хотел бы иметь более низкий порог альфа, скажем, 15. Пиксели, у которых начальная альфа равна 0, сохранят эту альфа. В псевдокоде:
if alpha == 0:
newAlpha = 0
else:
newAlpha = max(15, alpha - 1)
Прямо сейчас я имею в виду два метода. Первый — это преобразование в QImage и попиксельное уменьшение альфа. Однако у этого есть два недостатка: производительность и цветовые артефакты: цвета некоторых пикселей сильно изменяются. Артефакты появляются, когда QPainting результирующего qpixmap на другой qpixmap, заполненный одним цветом (с QPainter::CompositionMode_SourceOver
). Это, скорее всего, связано с дизерингом ?! Я попробовал два доступных, оба производят артефакты этих типов.
QImage image = pixmap.toImage();
for (int y = 0; y < image.height(); ++y) {
for (int x = 0; x < image.width(); ++x) {
QRgb col = image.pixel(x,y);
int alpha = qAlpha(col);
if(alpha>15) {
alpha -= 1;
QRgb newCol = qRgba(qRed(col), qGreen(col), qBlue(col), alpha);
image.setPixel(x,y, newCol);
}
}
}
pixmap = QPixmap::fromImage(image, Qt::DiffuseAlphaDither | Qt::NoOpaqueDetection);
Артефакты появляются с этим:
QPixmap screen;
...
screen.fill(Qt::transparent);
QPainter painter( &screen );
// remove anti-aliasing, which (with current composition mode) results in even stronger artefacts
painter.setRenderHints(0);
background.fill(someRandomColor);
painter.drawPixmap(0, 0, w, h, background);
painter.drawPixmap(0, 0, w, h, pixmap);
painter.end();
В качестве альтернативы я попытался отобразить вышеупомянутый псевдокод с помощью операций рисования QPixmap. Например, режим композиции QPainter QPainter::CompositionMode_DestinationIn
полезно уменьшить альфа. Но я не знаю, как обрабатывать пороговое значение с одновременным сохранением значений 0 альфа.
Итак, сейчас есть три вопроса:
Можно ли избежать цветовых артефактов с помощью обхода QImage?
Или можно сопоставить приведенный выше псевдокод с чистыми операциями QPixmap / QPainter?
Есть ли совершенно другая идея?
РЕДАКТИРОВАТЬ:
QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
Похоже, удалить артефакты. Прежде чем это было бы преобразовано в QImage::Format_ARGB32_Premultiplied
и, следовательно, артефакты. Но теперь он еще менее производительный
Задача ещё не решена.
Других решений пока нет …