Simply put, when I draw a border of a certain shape using QPainter with a pen of width e.g. penWidth = 10.0 then one half of the border width is actually painted outside of the shape area and one half is drawn inside.
I would however like to paint a shape with a pen such that the border is only on the inside of the shape area.
I probably can use this trick: I set the pen's width twice as big and I also set the clip path so that the outer half of the border line is clipped away and only the inner half of the border line remains.
Example:
QColor penColor(Qt::red);
qreal penWidth = 5.0;
QPainterPath shape;
// ...here I define the shape
QPainter painter(device);
// the trick comes here
QPen p(penColor, penWidth * 2); // we make the border pen twice as thick
painter.setClipPath(path); // and we clip the outer half of the border away
// now let's paint it
painter.drawPath(shape);
I think this is probably not the most efficient way since clipping is probably quite expensive operation.
Isn't there any other more elegant way?
I am using the following code to draw an image in a circle.
QPixmap target(110, 130); // the size may vary
target.fill(Qt::transparent);
QPixmap p = QPixmap::fromImage( QImage(":/Images/head").scaled(110,110,Qt::IgnoreAspectRatio,Qt::SmoothTransformation).convertToFormat(QImage::Format_ARGB32));
QPainter painter(&target);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::Antialiasing, true);
QRegion r(QRect(10,10,100,100), QRegion::Ellipse);
painter.setClipRegion(r);
painter.drawPixmap(0, 0,p);
ui->label->setPixmap(target);
This is the output that I get
Notice the circle is not smooth. My question is how could i make this circle smooth.
Using clip path will not has antialias ability in drawing.
You can use a mask image or make a color mask image to draw image to a special shape that.
Here is a simple example:
QPainter *painter....
QPixmap pixmapToDraw....
....
QImage dst(sourceRect.width(), sourceRect.height(), QImage::Format_ARGB32);
dst.fill(QColor(0, 0, 0, 0));
QPainter p(&dst);
QPainterPath path;
path.addRoundedRect(0, 0, sourceRect.width(), sourceRect.height(), sourceRect.width() / 2, sourceRect.height() / 2);
p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
p.fillPath(path, QBrush(Qt::white));
p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
p.drawPixmap(dst.rect(), pixmapToDraw);
painter->drawImage(0, 0, dst);
Here is Qt's doc Image Composition Example, QPainter::CompositionMode
Code for the beginning:
QColor yellow("#f0d048");
Qt::BrushStyle style = Qt::SolidPattern;
QBrush brush(yellow, style);
painter.setBrush(brush);
painter.drawEllipse(10,10,10,10);
Everytime I do this, I get a yellow circle surrounded by a black 1-pixel-sized border. In total the circle will have the same size like if I draw with black colour, so what shall I do to just get a single-coloured yellow circle without black border?
Best regards
Set a pen on painter
painter.setPen(Qt::NoPen);
Qt has 'brush' for filling figures, and 'pen' for drawing lines and outlines.
I am new to QT and I want to draw some image inside a shape and image should be croped by a shape.
I use the following code to draw a rectangle for example. How to draw image only inside shape?
QPen pen(Qt::black,penWidth);
pen.setStyle(Qt::DashLine);
QPicture picture;
picture.load("drawing.pic");
painter->setPen(pen);
painter->drawPicture(0,0, picture);
painter->drawRoundedRect( (QRectF(x, y, height, width),radius,radius);
PS. Can I load an image to brush?
Just set a QBrush for painter.
QBrush brush(QPixmap("file.png"));
painter->setBrush(brush);
It will draw the rounded rect filled with file.png image.
I would like to know how to draw semi-transparent shapes in OpenCV, similar to those in the image below (from http://tellthattomycamera.wordpress.com/)
I don't need those fancy circles, but I would like to be able to draw a rectangle, e.g, on a 3 channel color image and specify the transparency of the rectangle, something like
rectangle (img, Point (100,100), Point (300,300), Scalar (0,125,125,0.4), CV_FILLED);
where 0,125,125 is the color of the rectangle and 0.4 specifies the transparency.
However OpenCV doesn't have this functionality built into its drawing functions. How can I draw shapes in OpenCV so that the original image being drawn on is partially visible through the shape?
The image below illustrates transparency using OpenCV. You need to do an alpha blend between the image and the rectangle. Below is the code for one way to do this.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main( int argc, char** argv )
{
cv::Mat image = cv::imread("IMG_2083s.png");
cv::Mat roi = image(cv::Rect(100, 100, 300, 300));
cv::Mat color(roi.size(), CV_8UC3, cv::Scalar(0, 125, 125));
double alpha = 0.3;
cv::addWeighted(color, alpha, roi, 1.0 - alpha , 0.0, roi);
cv::imshow("image",image);
cv::waitKey(0);
}
In OpenCV 3 this code worked for me:
cv::Mat source = cv::imread("IMG_2083s.png");
cv::Mat overlay;
double alpha = 0.3;
// copy the source image to an overlay
source.copyTo(overlay);
// draw a filled, yellow rectangle on the overlay copy
cv::rectangle(overlay, cv::Rect(100, 100, 300, 300), cv::Scalar(0, 125, 125), -1);
// blend the overlay with the source image
cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source);
Source/Inspired by: http://bistr-o-mathik.org/2012/06/13/simple-transparency-in-opencv/
Adding to Alexander Taubenkorb's answer, you can draw random (semi-transparent) shapes by replacing the cv::rectangle line with the shape you want to draw.
For example, if you want to draw a series of semi-transparent circles, you can do it as follows:
cv::Mat source = cv::imread("IMG_2083s.png"); // loading the source image
cv::Mat overlay; // declaring overlay matrix, we'll copy source image to this matrix
double alpha = 0.3; // defining opacity value, 0 means fully transparent, 1 means fully opaque
source.copyTo(overlay); // copying the source image to overlay matrix, we'll be drawing shapes on overlay matrix and we'll blend it with original image
// change this section to draw the shapes you want to draw
vector<Point>::const_iterator points_it; // declaring points iterator
for( points_it = circles.begin(); points_it != circles.end(); ++points_it ) // circles is a vector of points, containing center of each circle
circle(overlay, *points_it, 1, (0, 255, 255), -1); // drawing circles on overlay image
cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source); // blending the overlay (with alpha opacity) with the source image (with 1-alpha opacity)
For C++, I personally like the readability of overloaded operators for scalar multiplication and matrix addition:
... same initial lines as other answers above ...
// blend the overlay with the source image
source = source * (1.0 - alpha) + overlay * alpha;