PDA

View Full Version : QPainter::setCompositingMode without effect



olidem
4th March 2009, 20:09
Hi!

I am developping my own QGraphicsItem that should paint a partly transparent QImage. This is easy, it can just be realised via



void GraphicsHairstyleItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);

painter->drawImage(m_imgrect, m_img_warped);
}


OK. But now I qould like to be able to realise something like "erasing", or like the rubber-tool in Photoshop. Therefor I inted to have a second QImage called the "cutmask" that is transparent everywhere except for parts of the image that should be erased.

Following the documentation on Compositing modes (http://doc.trolltech.com/4.5/qpainter.html#CompositionMode-enum), if the image to be shown is the destination and the cutmask acts as the source (but I'm not a 100% sure about this), then QPainter::CompositionMode_DestinationOut should do the right thing.

This means that only portions of the image where the cutmask is transparent are shown.

So my code looks like



void GraphicsHairstyleItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);

painter->drawImage(m_imgrect, m_img_warped);
painter->setCompositionMode(QPainter::CompositionMode_Desti nationOut);
painter->drawImage(m_imgrect, m_img_cutmask);
}


see the attachments for my cutmask image "cut.png".

But in this realisation (and also in many others), the white spot is just drawn on top of the image, instead of erasing it out there.

Thank you very much for your help in advance,
Olli

Lykurg
4th March 2009, 20:24
Quick guess: is anti aliasing turned off? And what happens if you code your paint function like this of the image composition example (http://doc.trolltech.com/4.5/painting-imagecomposition.html)?

(And have you notified that "The RasterOp denoted blend modes are not supported for pens and brushes with alpha components."?)

olidem
4th March 2009, 20:52
Hmm, ok, I do not think that there is a connection to antialiasing.

The only idea I have is about the the format of the QImages. In the referred example, all images are kept in a premultiplied format (see the loadImage function), but I think this is mainly for rescaling reasons.

The problem I have is that the first step of there rendering process always at first fills the whole image with transparent color


painter.setCompositionMode(QPainter::CompositionMo de_Source);
painter.fillRect(resultImage.rect(), Qt::transparent);


which I can't do because I would delete other things.

What about the attached file? Do you see errors there?

olidem
4th March 2009, 20:59
News:

I have now converted everything into the premultiplied format, with no changes, still the destinationOut does not what I expect.

Thanks for help in advance!!!
Olli

olidem
5th March 2009, 17:59
Hmm,

I ahve found a workaround:

I just use another temporary QImage where I render the image together with the cutmask. This image is then rendered into the actual painter given by the paint(...) -method:



void GraphicsHairstyleItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);



QImage toPaint (m_img_warped.width(), m_img_warped.height(), m_img_warped.format());
QPainter p(&toPaint);
p.setCompositionMode(QPainter::CompositionMode_Sou rce);
p.fillRect(m_imgrect, Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_Sou rceOver);
p.drawImage(0, 0, m_img_warped);
p.setCompositionMode(QPainter::CompositionMode_Des tinationOut);
p.drawImage(0, 0, m_img_cutmask);
p.end();


painter->setCompositionMode(QPainter::CompositionMode_Sourc eOver);
painter->drawImage(m_imgrect, toPaint);
}


This does what it should.

But this is not elegant. I cannot understand why it should not be possible to do this DestinationOut rendering dierctly in the event-painter.

Can anyone clarify my problem?

Thnaks a lot in advance,
Olli