Search code examples
qtqt5qgraphicsviewtearing

Huge image tearing / disappearing on extreme scaling


I have a big image of 7589x5537 that I put in a scene as a QPixmapGraphicsItem.

If I scale the QGraphicsView to 14.2318 and rotate it -35 degrees, the render of the pixmap starts behaving weirdly; tearing or completely disappearing.

This happens also at other rotations and scales, but only if they are big scaling of more than 14.

I've read about X11 limitations but I'm on Windows.

I'm on Qt 5.5

I've tested changing the content of the image to a bucketfill of tree pattern, exactly the same behaviour. The image is indexed, but with a RGB I have the same issue.

Anybody has a clue why this happens and how to fix it? Is the problem reproducible?

The issue seems to be related to the maximum value of unsigned int, dimension independent if not rotated. Creating an untilted image of 1 million by 200 pixels, one can zoom up to 4384x. In my computer the size of unsigned int is 4 bytes, which can handle roughly values up to 4000 million.

I presume Qt doesn't crop the upscaled image to the view before scaling it, or something similar. It is weird, thought, that it tears it instead of crashing exhausting resources, failing to allocate contiguous memory or something else.

Those are suspicions since at the moment I don't know how QGraphicsView implements scaling.

#include <QtWidgets>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    unsigned int w = 7589;
    unsigned int h = 5537;

    QImage image(w, h, QImage::Format_ARGB32);
    for(unsigned int j = 0; j < h; j++)
    {
        for(unsigned int i = 0; i < w; i++)
        {
            QRgb rgb = qRgb(i%255,j%255,(i+j)%255);
            image.setPixel(i, j, rgb);
        }
    }

    QPixmap imagepm = QPixmap::fromImage(image);

    QGraphicsPixmapItem* item = new QGraphicsPixmapItem(imagepm);
    item->setTransformationMode(Qt::FastTransformation);
    QGraphicsScene* scene = new QGraphicsScene;
    scene->addItem(item);

    QGraphicsView* view = new QGraphicsView(scene);
    view->rotate(-35);
    view->scale(14.2318,14.2318);
    view->show();
    return a.exec();
}

Solution

  • The fix requires cutting the image up into tiles, grouping them under a single parent item, and then proceeding as you did before. The tiles would be an implementation detail that you don't need to worry about.