QImage overlay with mouse selection - qt

How to highlight the pixels in a QImage to highlight or draw a overlay on the pixels which user selected using mouse. I just want to know how i can specify the particular area.
Ex: With a 400x400 QImage data how i can increase or decrease the pixel intensity or overlap an image on top of it where the user selected.

You can involve QPainter (please refer to the documentation) to draw over your QImage. It allows drawing another images, rectangles, lines etc.
void View::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
// Draws your original image.
painter.drawImage(0, 0, myImage);
// Draws a blue rectangle over the image.
QPen rectPen(Qt::blue);
rectPen.setStyle(Qt::DashLine);
painter.setPen(rectPen);
painter.drawRect(0, 0, 100, 100);
[..]
}
You can maintain your mouse clicks and movement and draw corresponding stuff in paint event handler.

Related

How do I add a border to a rounded QPixmap?

I'm trying to show a rounded avatar QPixMap with a white border around it. However, I have no clue as to how I could add the border... Is it even possible?
This is the function I have to draw the avatar image.
void AccountDropDownMenu::setAvatar(
const QByteArray& bytes)
{
QPixmap new_avatar;
new_avatar.loadFromData(bytes);
new_avatar = new_avatar.scaledToHeight(40, Qt::SmoothTransformation);
QBitmap map(new_avatar.size());
map.fill(Qt::color0);
QPainter painter(&map);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(Qt::color1);
painter.setPen(QPen(Qt::white, 10));
painter.drawRoundedRect(
m_avatar_label->x(),
m_avatar_label->y(),
new_avatar.width(),
new_avatar.height(),
45,
45);
new_avatar.setMask(map);
avatar_label->setPixmap(new_avatar);
}
Update
Thanks to dtech I was able to get the desired output using the following updated function.... Although it's a bit pixly (the border).
void AccountDropDownMenu::setAvatar(
const QByteArray& bytes)
{
QPixmap new_avatar;
new_avatar.loadFromData(bytes);
new_avatar = new_avatar.scaledToHeight(40, Qt::SmoothTransformation);
QBitmap map(new_avatar.size());
map.fill(Qt::color0);
QPainter painter(&map);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(Qt::color1);
painter.drawRoundedRect(
QRectF(
avatar_label->x(),
avatar_label->y(),
new_avatar.width(),
new_avatar.height()),
40,
40);
new_avatar.setMask(map);
QPainter painter2(&new_avatar);
painter2.setRenderHint(QPainter::Antialiasing);
painter2.setPen(QPen(Qt::white, 1));
painter2.drawRoundedRect(
QRectF(
avatar_label->x(),
avatar_label->y(),
new_avatar.width(),
new_avatar.height()),
40,
40);
avatar_label->setPixmap(new_avatar);
}
In Qt you draw fills with a brush, but outlines are drawn with a QPen.
I haven't used QPainter in a long time, but IIRC, the default pen is zero width, which would explain why you aren't getting anything - you are not setting a pen.
Also, you don't need "another" rounded rectangle, you can apply fill and outline to the same geometry, as demonstrated in this answer.
Update:
Your updated code sets a mask, which sets an alpha channel. That cuts away from what you already have, it could not possibly add anything. You have to paint on the pixmap. Simply use new_avatar as the paint device - QPainter painter(&new_avatar); and get rid of the rest.

How can I show/hide background drawing on QGraphicsScene or QGraphicsView?

I would like to have certain things drawn on QGraphicsScene, but not be QGraphicsItem (it would interfere with the processing of the QGraphicsItem collection).
Example: a scene bounding rectangle, a grid
I am overriding the drawBackground(QPainter *painter, const QRectF &rect) for that purpose. (I should subclass the scene... )
void MyView::showHideBounds()
{
m_showBackgroundBounds = !m_showBackgroundBounds;
// can't triger an update ???
update(); // neither does anything
viewport()->update();
}
void MyView::drawBackground(QPainter *painter, const QRectF &rect)
{
QPen pen;
if(m_showBackgroundBounds)
pen = QPen(QColor(0, 0, 0), 10, Qt::PenStyle(Qt::SolidLine));
else
pen = QPen(QColor(255, 255, 255), 10, Qt::PenStyle(Qt::SolidLine));
painter->setPen(pen);
painter->drawRect(QRect(QPoint(-scene()->sceneRect().size().toSize().width()/2,
-scene()->sceneRect().size().toSize().height()/2),
scene()->sceneRect().size().toSize()));
}
I would like the option to show/hide either the bounding rectangle or the grid.
The only thing I can think of is paint over them with the color of the background brush ? Is there any other option ?
As I have written it above, it works - except I need user action on items (or a zoom or some other scene changing action) to trigger refresh, or call an update... (the function showHideBounds doesn't - not sure how to make it force a refresh)
I would call the drawBackground from the showHideBounds function - but I don't know how to get the painter
[Also, the drawBackground seems to be drawn automatically... how can I give it the rect argument it needs ? (it seems if I draw the rect it does draw the scene rectangle but I only see the right and bottom edges)]
In order to redraw a particular section of scene, you can call
QGraphicsScene->invalidate(rect_to_redraw, Backgroundlayer)
Note that if drawBackground(*painter, rect) paints over area outside rect, it will not update automatically. In that case invalidate has to be called with appropriate rect parameters.

How to fill the void with transparent background when rotating a QImage?

When I rotate an image in Qt, It automatically enlarge the image to encapsulate the bigger dimensions which is great and intelligent. However, it fills the newly created void with white color which is not what I want. How can I make it fill with a totally transparent color?
Here is may code.
QImage lSource("/path/to/an/image/file");
QTransform lRotation;
lRotation.rotate(30.0);
QImage lRotated(lSource.transformed(lRotation, Qt::SmoothTransformation));
ui.labelImage->setPixmap(QPixmap::fromImage(lRotated));
Thanks a lot!
Based on my comment above...
I suspect, that the void areas of the rotated image are transparent, and the white color is the background color of your label. If you want to set a specific background to your rotated image, you can do the following:
// Create rotated image.
QImage lSource("source.png");
QTransform lRotation;
lRotation.rotate(30.0);
QImage lRotated(lSource.transformed(lRotation, Qt::SmoothTransformation));
// Create resulting image with specific background.
QImage img(lRotated.size(), QImage::Format_ARGB32);
img.fill(Qt::red); // Set the red background
QPainter p(&img);
p.drawImage(0, 0, lRotated);
QLabel l;
l.setPixmap(QPixmap::fromImage(img));
l.show();

Qt : draw triangle image

I need to do something similar to QPainter::drawImage, but drawing a triangle part of the given picture (into a triangular region of my widget) instead of working with rectangles.
Any idea how I could do that, besides painfully trying to redraw every pixel?
Thanks for your insights!
If it is feasible for you to use a QPixmap instead of a QImage, you can set a bitmap mask for the QPixmap which defines which of the pixels are shown and which are transparent:
myPixmap->setMask(myTriangleMask);
painter->drawPixmap(myPixmap);
Here is another solution based on QImage:
MaskWidget::MaskWidget(QWidget* parent) : QWidget(parent) {
img = QImage("Sample.jpg"); // The image to paint
mask = QImage("Mask.png"); // An indexed 2-bit colormap image
QPainter imgPainter(&img);
imgPainter.drawImage(0, 0, mask); // Paint the mask onto the image
}
void MaskWidget::paintEvent ( QPaintEvent * event ) {
QPainter painter(this);
painter.drawImage(10, 10, img);
}
Mask.png is an image file with the same size as Sample.jpg. It contains an alpha channel to support transparency. You can create this file easily with The GIMP, for example. I added an alpha channel, changed all areas I want to have painted to transparent and all other areas to white. To reduce the size, I finally converted it to an indexed 2-bit image.
You could even create the mask image programmatically with Qt, if you need your triangle be computed based on various parameters.

How to add an image on the top of another image?

I want to show difference between a trimed clip and non trimed clip in my video editor application, i.e. I want to add a small film image on my thumbnail for a trimed clip. How can I do this?
It would be just to show the difference between an image and a video in our gallery application.
How to add an image on the top of another one in Qt?
Open the QPainter on the bottom image and draw the top image using its drawPixmap()/drawImage() methods.
QPixmap base, overlay; // come from your code
{
QPainter painter(base);
painter.drawPixmap(100, 100, overlay);
}
If your overlay contains an alpha channel (e.g. fancy PNG icon) and your base image does not, you should create a new QPixmap with an alpha channel and draw both images into it:
QPixmap base, overlay; // come from your code
QPixmap result(base.width(), base.height());
result.fill(Qt::transparent); // force alpha channel
{
QPainter painter(&result);
painter.drawPixmap(0, 0, base);
painter.drawPixmap(100, 100, overlay);
}
QPixmaps and QImages can be used interchangeably, although not all combinations give good performance).
If it's just about showing an image above another, then you could also go with this answer.
QGridLayout *layout = new QGridLayout(widget);
Pixmap base, overlay;
QLabel *background = new Label();
background->setPixmap(&base);
QLabel *lOverlay = new QLabel();
lOverlay->setPixmap(&overlay);
//label gets positioned above textBrowser and is an overlay
layout->addWidget(background, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(lOverlay, 0, 0, Qt::AlignRight | Qt::AlignBottom);
Of course then the QPixbuf of the background doesn't contain the QPixbuf of the overlay-image, but it only appears to do.

Resources