Rendering a large QGraphicsScene on a QImage clips it off

雨燕双飞 提交于 2019-12-12 01:59:12

问题


I am creating some images rendering the contents of a QGraphicsScene.
My project requirement is that it should handle a canvas size of 10 ft by 8 inches. On screen, and scene size, that is 8640 x 576 pixels.
I can render it fine.

The thing is, the output images need to have 300 resolution.
That means, the rendered image will have a width of 36000, which is over 2^15 - 1 = 32767 pixels.....

The output is clipped - in the code below, I would get a QImage of correct expected size (36000) but the QGraphicsScene only renders to 32767 pixels.

That is confusing... I cannot explain the outcome - if the QImage limitations were 32767 pixels, then I should not be able to create one in the first place. But I checked and the QImage "sanity check" is much higher.

Once the image is created, I do not see anything in the code for rendering QGraphicsScene that would clip at any value....

This is a simple code that is trying to expose my problem.
It creates a QImage of required size, and fills with yellow (for control).
Then it renders a QGraphicsScene with blue background brush and a red rectangle close to the right margin.
If it works correctly, the result should be: an image of width 36000, blue with a tiny red rectangle at the far right.
But... as it is, the result is an image of width 36000, blue for the first 32766 pixels then yellow for the rest, no red rectangle.

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QPainter>

void printScene(QGraphicsScene* s, qreal ratio) {
    qreal w = s->width() * ratio;
    qreal h = s->height() * ratio;
    QRectF target(0, 0, w, h);
    QImage image = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
    image.fill(QColor(Qt::yellow).rgb());

    QPainter painter;
    painter.begin(&image);
    s->render(&painter, target);
    painter.end();
    image.save("image.png");
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QGraphicsScene s;
    s.setSceneRect(0, 0, 8640, 576);
    s.setBackgroundBrush(Qt::blue);
    QGraphicsView view(&s);
    view.show();
    QGraphicsRectItem* r = s.addRect(8530, 250, 100, 100);
    r->setBrush(Qt::red);
    qreal ratio = 300/72.;
    printScene(&s, ratio);
    return app.exec();
}

As seen in sample images, the QImage is created successfully, QGraphicsScene though only renders to 2^15 - 1... But I stepped through their code and I didn't see it stop....

(I also tried creating the original scene 36000 x something (and setting the ratio to 1), and it displays fine... it just won't render to QImage anything beyond 32767 pixels)

Am I missing some setting ? What could be the cause of the QGraphicsScene::render() to not render more ?

I would love to find out how I can render the size I want - width of 36000 pixels - or a reason why this is not possible.

I am running this in Windows 7, 32 bit Qt 5.5.1 or 4.7.4


回答1:


I have found the reason for the clipping - and imagined 2 workarounds.

Why:

Stepping through the rendering code, the clip rect gets limited to 32767:

bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
{
    Q_D(QRasterPaintEngine);
    QRect clipRect = r & d->deviceRect;
    ...
}

Where deviceRect is set by

void QRasterPaintEnginePrivate::systemStateChanged()
{
    deviceRectUnclipped = QRect(0, 0,
            qMin(QT_RASTER_COORD_LIMIT, device->width()),
            qMin(QT_RASTER_COORD_LIMIT, device->height()));

    QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
    deviceRect = clippedDeviceRgn.boundingRect();
    baseClip->setClipRegion(clippedDeviceRgn);
    ...
}

and

// This limitations comes from qgrayraster.c. Any higher and
// rasterization of shapes will produce incorrect results.
const int QT_RASTER_COORD_LIMIT = 32767;

Options:

1) Render to a max of 32767 and, if the target must be bigger, scale result. (should give slightly lower quality)

2) Create 2 images and combine them (I still need to figure that out but I think it is the better fix)



来源:https://stackoverflow.com/questions/35782217/rendering-a-large-qgraphicsscene-on-a-qimage-clips-it-off

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!