How to draw darkened QPixmap? - c++

I'm looking for a fast and effective way to draw a QPixmap with QPainter, but have the pixmap appear darker then normal. Is there some sort of filter or effect that can be applied to either the QPixmap or QPainter while drawing to create this effect?

You don't have pixel access in QPixmap, so going over the pixels and darkening them is out of the question.
You can however fill a pixmap with a transparent black brush, and use a number of composition modes to further customize the result.
QPainter painter(this);
QPixmap pm("d:/test.jpg");
painter.drawPixmap(QRect(0, 0, 400, 200), pm);
painter.translate(0, 200);
painter.drawPixmap(QRect(0, 0, 400, 200), pm);
painter.fillRect(QRect(0, 0, 400, 200), QBrush(QColor(0, 0, 0, 200)));

Some of the earlier comments will leave a dark gray rectangle on your screen. Using the composition mode, will darken everything visible, yet leaving any transparent areas still transparent.
painter.setCompositionMode (QPainter::CompositionMode_DestinationIn);
painter.fillRect (rect, QBrush (QColor (0,0,0,128)));

Related

Why QWidget::Mask based on QPixmap works fine, but Bitmap doesn't

Target: make my widget rounded, using QWidget::setMask
At first, I want to make a mask using QRegion, but later I found that, make a rounded Rect based on region is a not simple way.
So I decided to use QBitmap.
QBitmap pixmap(size());//create image
QPainter pixmapPainter(&pixmap);
QPainterPath path;
path.addRoundedRect(0, 0, width(), height(), m_borderRadius, m_borderRadius);//fill rounded rect
pixmapPainter.fillPath(path, Qt::color1);
QWidget::setMask(pixmap.mask());
Result is:
But when I change my type to QPixmap and add the fill method
QBitmap pixmap(size());//
pixmap.fill(Qt::transparent);//
QPainter pixmapPainter(&pixmap);
pixmapPainter.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
path.addRoundedRect(0, 0, width(), height(), m_borderRadius, m_borderRadius);//
pixmapPainter.fillPath(path, Qt::white);
QWidget::setMask(pixmap.mask());
It shows me:
What's wrong with my first code?
As the comment by G.M. explains, the bitmap needs to be cleared first.
Also, a widget mask is not really the best choice here. A widget mask is intended for defining the areas where your widget will take mouse input. On most window systems, it will also cause transparency. But the edges will be aliased and not pretty. In order to make a non-rectangular widget with nice edges, one should use translucent widget background and anti-aliased painting - in addition to the widget mask for the mouse input.
This is shown and explained in Qt's shapedclock example.

Restrict drawing of qpainter over pixmap

I am using QGraphicsView and Scene over which two QGraphicsPixmap item are set.
One is showing some image, another one is having transparent pixmap which is used to show marking.
I am using qpainter to draw over a transparent qpixmap.
I am using drawline between two points with qpen having rounded point with some pen size.
Problem is:
If i load some png image, with some part of image being transparent, I want to disable marking (on marking pixmap) over transparent region of image.
Is there any way to automatically restrict area of marking of qpainter?
It would be easiest to combine your two pixmaps into a single QGraphicsPixmapItem. Then you could simply use the correct QPainter::CompositionMode, which would need to be
QPainter::CompositionMode_SourceAtop
The source pixel is blended on top of the destination, with the alpha of the source pixel reduced by the alpha of the destination pixel.
e.g.:
QPixmap markingPixmap(sourceImage.size());
markingPixmap.fill(Qt::transparent);
{ // scope for painter1
QPainter painter1(&markingPixmap);
painter1.setPen(...);
painter1.drawLine(...);
}
QPainter painter(&sourceImage);
painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
painter.drawPixmap(0, 0, markingPixmap);
(Code untested!)
Or you could even use a QBitmap, see QPainter::drawPixmap():
If pixmap is a QBitmap it is drawn with the bits that are "set" using the pens color. If backgroundMode is Qt::OpaqueMode, the "unset" bits are drawn using the color of the background brush; if backgroundMode is Qt::TransparentMode, the "unset" bits are transparent. Drawing bitmaps with gradient or texture colors is not supported.
(You would need to try if this respects the CompositionMode.)

QPalette with multiple color background

I know that we can use QPalette to set the background for a QLabel. But could I draw a multiple color background with QPalette? For instance, the half above in black and the half below in blue.
I couldn't find a setRect() function QPalette. Or should I use other class? Or do I have to draw the background with a painter?
The documentation for QGradient class states:-
The QGradient class is used in combination with QBrush to specify gradient fills
So, you can start by creating a gradient and setting that to a QBrush
QLinearGradient linearGrad(QPointF(100, 100), QPointF(100, 200));
linearGrad.setColorAt(0, Qt::black);
linearGrad.setColorAt(0.5, Qt::blue);
You can experiment with setting different colours at different stops, which range from 0.0, to 1.0
Use the gradient to create a brush...
QBrush brush(linearGrad);
The documentation for QPalette states: -
Colors and brushes can be set for particular roles in any of a palette's color groups with setColor() and setBrush().
So, using the setBrush function of QPalette, set the brush that is created with the gradient: -
QPalette palette;
palette->setBrush(QPalette::Window, brush);

How can I apply a dark mask layer on a QPixmap?

I am fairly new to Qt and have been doing a lot of reading and practicing exercises.
I have searched for this one quite a lot but I could not find any examples.
I have a QPixmap object to which I load a .png image.
I need to create a copy of this QPixmap with a dark mask applied to it.
Basically I want this QPixmap's image to be covered with a layer of solid black of which the opacity is set to 50%.
I know how to set the opacity of a QPixmap's image but how can I add a layer of solid black with opacity on it?
Thank you!
You can use a QPainter and you a semi-transparent QBrush to paint that dark layer onto your QPixmap.
Assuming pic is a QPixmap loaded with your image:
QPainter p(&pic);
QBrush b(QColor(0,0,0,128)); // adjust color and alpha to taste
p.setBrush(b);
p.drawRect(0, 0, 200, 200);
Effect (before/after):
   vs   
The opaque black border can be removed by setting an semi-transparent pen before painting.
Copy the pixmap before applying the "mask" if you want to preserve the original.

How do I draw a semi-transparent rectangle in Qt?

I'm trying to draw a semi-transparent rectangle on top of an image to act as a highlight. Unfortunately, nothing I try seems to be able to perform the transparency effect I want. Instead I just get solid filled rectangles, with no transparency.
Here's what I'm doing right now:
void PageView::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QImage img=...;
painter.drawImage(0, 0, img);
...
// draw a light blue, transparent rectangle to highlight
QRect rect=...;
painter.fillRect(rect, QColor(128, 128, 255, 128));
...
}
Unfortunately, for me, this draws a solid blue rectangle, instead of the semi-transparent one I expect due to giving the QBrush an alpha value.
I've also tried drawing to an intermediate QImage or QPixMap, playing around with painter.setCompositionMode(...). No luck so far.
Thus my question: How can I convince Qt to draw a semi-transparent rectangle to my PageView?
EDIT: If it's relevant, I'm building this under Qt 4.8.1 on Windows.
The code works for me with a slight modification as it does not compile as you have it:
painter.fillRect(rect, QBrush(QColor(128, 128, 255, 128)));
NOTE:
The OP was painting the semi transparent rectangle in a loop causing the same area to be painted multiple times. This will result in an additive effect which will eventually cause that area to look the same as a solid fill.