Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Issue when rotating an QImage



  • Hi all, I have trouble when rotating an image.

    To achieve that, I firstly try out QPixmap + QImage. And use a QMatrix to do the rotation:

    // myImage.png is a squared picture (same w and h)
    QImage image(":/resources/myImage.png")
    QMatrix rotate_matrix;
    QPoint center = image.rect().center();
    
    // this line seems to have no effect on the result
    rotate_matrix.translate(center.x(), center.y());
    
    rotate_matrix.rotate(degree);
    QImage dstImage = image.transformed(rotate_matrix);
    QPixmap pic = QPixmap::fromImage(dstImage);
    
    // "this" is a QLabel
    this->setPixmap(pic);
    

    However, I found that the rotating is not working as I expected. It seems that the image is "floating" a bit. It should be rotating around its center (pivot point). The truth is it rotates around a little bit offsets to the center, which makes the image "move" a bit when rotating.

    And then I try to draw an image with QPainter. To be honest, this method is a bit complicated because I have to calculate the center's offset every time I do (cause I have to rotate around coordinate (0,0) instead of image's center, and I need to recalculate the image's center's position)

    painter.rotate(degree);
    

    I am 99% sure that my offset calculation is correct. But the rotation is still incorrect (with some offsets)

    Could someone help me out? Do I rotate the image in the wrong way?

    Note: platform: Ubuntu 16.04 + Qt5.6 + C++14



  • @sylorr
    I think you are supposed to translate the centre of the image back to the origin not offset it to the centre.
    So I am guessing your initial translation should be the inverse of what it is now.
    NOTE: I only reasoned this and did not test it.



  • @kenchan
    Thanks for the response. But I have tested it out. It's not the issue.

    Now I have tackled down the issue to avoid image "floating" by using QPainter::drawImage() to draw a rotated QImage on my widget. However, I found another issue that once I rotate something by

    QMatrix::rotate(degree);
    

    The QImage scaled automatically for me. I would update the rotating degree every 0.1 seconds and my image just keeps scaling back and forth. The larger (in abs()) degree it rotates, the smaller the image it is. I really wonder how this rotate function is implemented.



  • @sylorr

    from the docs for QImage::transformed

    QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode = Qt::FastTransformation) const
    Returns a copy of the image that is transformed using the given transformation matrix and transformation mode.
    The transformation matrix is internally adjusted to compensate for unwanted translation; i.e. the image produced is the smallest image that contains all the transformed points of the original image. Use the trueMatrix() function to retrieve the actual matrix used for transforming an image.
    Unlike the other overload, this function can be used to perform perspective transformations on images.
    See also trueMatrix() and Image Transformations.
    

    So that kind of makes sense.


  • Qt Champions 2017

    @sylorr said in Issue when rotating an QImage:

    As @kenchan wrote, you should move the origin of the coordinate system back after rotating.

    The QImage scaled automatically for me. I would update the rotating degree every 0.1 seconds and my image just keeps scaling back and forth. The larger (in abs()) degree it rotates, the smaller the image it is. I really wonder how this rotate function is implemented.

    It may depend on how you move that rotating degree, numerical errors apply here.

    Also rotating something to anything but 0, 90, -90, 180 degrees is lossy. In that case pixels do not fit in their original positions, so you may see some "change" which would be more pronounced for small images.

    Lastly, the transformation is implemented the conventional way - through an extended-space transformation matrix which is applied to the pixel's coordinates (i.e the points) and then the space-extension is projected-out (i.e. clipped to 2D).
    I'm not sure what kind of interpolation is used, but I don't imagine it to be one that's very high quality or that's heavy to compute, for obvious reasons.



  • @kenchan
    Thanks! I have checked and tested that trueMatrix() function, the issue still exists. But that reminds me another truth that may cause the problem.

    So my QWidget is set to be sizing 100*100, and when I draw the image with QPainter::drawImage(rect, image), i need to pass a rect (in my case I just pass QRect(0, 0, 100, 100) everytime because this is my QWidget's rect()).

    However, an image is squared, which means when it rotates, taking an example of left-top corner (0, 0), may become negative. And in order to draw all the image, I guess Qt may scale it within the function QPainter::drawImage() to fit into that small QRect.

    For sure that is just a guess, but it totally makes sense in the case here.


Log in to reply