Qt rotated image -> polygon

821 Views Asked by At

I have a QImage with center at (x,y) and with size (w,h). I apply a rotation and eventually scaling using QTransform. Now is easy to me to put the new image (rotated/scaled) centered at (x,y).

QTransform transform = QTransform().translate(0,0).rotateRadians(r).scale(s,s);
QImage image = new QImage(old_image->transformed(transform);

I want to have a QPolygon with 4 points in the corners of rotated/scaled image. All my attempts failed.

QPolygon p = QPolygon(QRect(x-w/2, y-h/2, w, h));
QPolygon p2 = transform.map(p);

or

QPolygon p2 = transform.mapToPolygon(QRect(x-w/2, y-h/2, w, h));

All I got is a polygon in wrong position. Which must be the correct code?

1

There are 1 best solutions below

0
On

Contrary to images, when we want to rotate a polygon (a rectangle in this case) around its center, we have to use a transformation like

T = translate(center).rotate(r).translate(-center)

(remember transformations are applied from right to left). Scaling is discarded for the moment. For images such initial translation is implicit.

The issue in this case is that the image changes its dimensions after rotating: the size of the new image is the bounding rectangle that contains the rotated pixels, thus the last translate is no longer valid for your case (the translate(center)).

Instead, you need something like:

T = translate(new_rect.size() / 2).rotate(r).translate(-original_center)

To achieve this, you have to split the transformation in two parts (scaling brought back too):

T1 = rotate(r).scale(s, s).translate(-center)
T2 = translate(new_rect.size() / 2)

since the new rect size can only be computed after applying the first transformation.

Also, see that for T2 I'm not talking about the center but the half size, because the new center will not express the same meaning for images than for polygon (images don't have negative pixel coordinate, for example)

Expressed using Qt API:

// Image transformation
auto transform = QTransform().rotateRadians(r).scale(s, s);
auto image = m_image.transformed(transform, Qt::SmoothTransformation);

// Assuming something like: QPainter painter(this);
painter.drawImage(0, 0, image);

// Rect to polygon
const auto rect = m_image.rect();
QPolygonF pol;
pol << rect.topLeft();
pol << rect.topRight();
pol << rect.bottomRight();
pol << rect.bottomLeft();

// First transformation
const auto center = rect.center();
transform = transform.translate(-center.x(), -center.y());
const auto pol2 = transform.map(pol);

// Second transformation
const auto rect2 = pol2.boundingRect();
painter.drawPolygon(QTransform().translate(rect2.width() / 2, rect2.height() / 2).map(pol2));

Full code available in GitHub.