【问题标题】:Rendering a large QGraphicsScene on a QImage clips it off在 QImage 上渲染一个大的 QGraphicsScene 会将其剪掉
【发布时间】:2016-03-03 20:20:45
【问题描述】:

我正在创建一些图像来呈现QGraphicsScene 的内容。
我的项目要求是它应该处理 10 英尺 x 8 英寸的画布尺寸。屏幕和场景大小为 8640 x 576 像素。
我可以渲染得很好。

问题是,输出图像需要有 300 分辨率。
这意味着,渲染图像的宽度将为 36000,超过 2^15 - 1 = 32767 像素.....

输出被剪裁 - 在下面的代码中,我会得到一个正确预期大小 (36000) 的 QImage,但 QGraphicsScene 仅呈现为 32767 像素。

这令人困惑...我无法解释结果 - 如果 QImage 的限制是 32767 像素,那么我一开始就不应该创建一个。但我检查了QImage“健全性检查”要高得多。

创建图像后,我在用于渲染QGraphicsScene 的代码中看不到任何会以任何值剪辑的内容......

这是一个试图暴露我的问题的简单代码。
它创建一个所需大小的QImage,并用黄色填充(用于控制)。
然后它使用蓝色背景画笔和靠近右边距的红色矩形呈现QGraphicsScene
如果它工作正常,结果应该是:一个宽度为 36000 的图像,蓝色的,最右边有一个红色的小矩形。
但是......实际上,结果是一个宽度为 36000 的图像,前 32766 个像素为蓝色,其余为黄色,没有红色矩形。

#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();
}

从示例图像中可以看出,QImage 已成功创建,QGraphicsScene 虽然只呈现给2^15 - 1...但我浏览了他们的代码,但我并没有看到它停止......

(我还尝试创建原始场景 36000 x 一些东西(并将 ratio 设置为 1),它显示良好......它不会渲染到 QImage 超过 32767 像素的任何东西)

我错过了一些设置吗? QGraphicsScene::render() 没有渲染更多内容的原因可能是什么?

我很想知道如何渲染我想要的大小 - 36000 像素的宽度 - 或者这是不可能的原因。

我在 Windows 7、32 位 Qt 5.5.1 或 4.7.4 中运行它

【问题讨论】:

  • 我已经运行了你的代码,它创建了正确的图像 36000x2400 QtCreator 3.4.1/ MSVC 2013 32bit Qt 5.4.2 Windows 7 Pro link
  • @AlexanderChernin 如您所见,图像与场景内容不匹配,被剪掉了。您的附件准确地显示了正在发生的事情 - 您获得了高达 32767 像素的蓝色场景,这太短而无法显示红色矩形,并且图像的其余部分预填充了黄色。图像已创建 - 填充 - 但场景仅部分渲染。 (我曾在历史上贴过截图,但它们似乎没有帮助,所以我把它们删除了,你仍然可以看)
  • 我更新为“预期”和“实际”添加更漂亮的图像并描述问题,以便在不阅读/运行代码的情况下更容易理解。

标签: qt rendering qgraphicsscene qpainter


【解决方案1】:

我找到了剪辑的原因 - 并设想了两种解决方法。

原因:

单步执行渲染代码,clip rect 被限制为 32767:

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

deviceRect 的设置位置

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);
    ...
}

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

选项:

1) 最大渲染为 32767,如果目标必须更大,则缩放结果。 (应该给出稍低的质量)

2) 创建 2 张图像并将它们组合起来(我仍然需要弄清楚,但我认为这是更好的解决方法)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 2013-12-17
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 2014-11-23
    • 2012-01-23
    相关资源
    最近更新 更多