Qt - fill circle with images
I tried to fill the circle with 4 images. First, each brush of the photo is the same size, and then scales the final image to that size. But the result is not what I want.
Currently there is a circle in the foreground and photos in the background, like here:
How to fill the circle with photos and delete the rectangle?
Here is my code:
QPixmap *CGlobalZone::profPicFromFourPics(QList<QPixmap> pixmapList)
{
QPixmap *avatar = NULL;
QImage roundedImage(CGlobalZone::AVATAR_WIDTH_M*2, CGlobalZone::AVATAR_HEIGHT_M*2, QImage::Format_ARGB32);
roundedImage.fill(Qt::transparent);
QBrush brush0(pixmapList[0]);
QBrush brush1(pixmapList[1]);
QBrush brush2(pixmapList[2]);
QBrush brush3(pixmapList[3]);
QPainter painter(&roundedImage);
QPen pen(QColor(176, 216, 242), 1);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(brush0);
painter.drawRect(0 , 0 , CGlobalZone::AVATAR_WIDTH_M , CGlobalZone::AVATAR_HEIGHT_M );
painter.setBrush(brush1);
painter.drawRect(CGlobalZone::AVATAR_WIDTH_M , 0 , CGlobalZone::AVATAR_WIDTH_M*2 , CGlobalZone::AVATAR_HEIGHT_M );
painter.setBrush(brush2);
painter.drawRect(CGlobalZone::AVATAR_WIDTH_M , CGlobalZone::AVATAR_HEIGHT_M , CGlobalZone::AVATAR_WIDTH_M*2 , CGlobalZone::AVATAR_HEIGHT_M*2 );
painter.setBrush(brush3);
painter.drawRect(0 , CGlobalZone::AVATAR_HEIGHT_M , CGlobalZone::AVATAR_WIDTH_M*2 , CGlobalZone::AVATAR_HEIGHT_M*2 );
painter.drawEllipse(0, 0, CGlobalZone::AVATAR_WIDTH_M*2-3 , CGlobalZone::AVATAR_HEIGHT_M*2-3 );
avatar = new QPixmap(QPixmap::fromImage(roundedImage).scaled(QSize(CGlobalZone::AVATAR_WIDTH_M, CGlobalZone::AVATAR_HEIGHT_M),
Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation));
return avatar;
}
source to share
I would do it like this (see original comments for details):
// The avatar image. Should be four, but use one for demonstration.
QPixmap source("avatar.png");
// Initialize the avatar and bring it to a standard size.
// This step may be skipped if avatars have the same sizes.
const int width = CGlobalZone::AVATAR_WIDTH_M;
const int height = CGlobalZone::AVATAR_HEIGHT_M;
source = source.scaled(width, height);
// Set up the final image that contains four avatar images.
QPixmap target(2 * width, 2 * height);
target.fill(Qt::transparent);
QPainter painter(&target);
// Set clipped region (circle) in the center of the target image
QRegion r(QRect(width / 2, height / 2, width, height), QRegion::Ellipse);
painter.setClipRegion(r);
painter.drawPixmap(0, 0, source); // First avatar
painter.drawPixmap(width, 0, source); // Second avatar
painter.drawPixmap(0, height, source); // Third avatar
painter.drawPixmap(width, height, source); // Fourth avatar
target.save("test.png");
source to share
Use the path of the painter for the task. Instead of drawEllipse, you should do
int dim = CGlobalZone::AVATAR_WIDTH_M*2;
QPainterPath entirePath;
QPainterPath ellipsePath;
entirePath.addRect(0, 0, dim, dim);
ellipsePath.addEllipse(0, 0, dim-3, dim-3);
QPainterPath outOfEllipse = entirePath.subtracted(ellipsePath);
painter.fillPath(outOfEllipse, QBrush(Qt::transparent));
edit: Since it is QPainterPath
intended for tricky cases, you should use QRegion
. After testing, I found that small pixel errors can occur when filling the inside and outside of the same path (in your case, that would be fine).
source to share