在 QImage 上渲染大型 QGraphicsScene 会将其剪掉 [英] Rendering a large QGraphicsScene on a QImage clips it off

查看:158
本文介绍了在 QImage 上渲染大型 QGraphicsScene 会将其剪掉的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一些图像来渲染 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 #include #include #include <QPainter>无效printScene(QGraphicsScene * s,qreal比率){qreal w = s->width() * ratio;qreal h = s-> height() * ratio;QRectF 目标(0, 0, w, h);QImage image = QImage(w, h, QImage::Format_ARGB32_Premultiplied);image.fill(QColor(Qt::yellow).rgb());QPainter 画家;Painter.begin(&image);s->render(&painter, target);画家结束();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 视图(&s);视图.show();QGraphicsRectItem* r = s.addRect(8530, 250, 100, 100);r-> setBrush(Qt::red);qreal 比率 = 300/72.;printScene(&s, ratio);返回 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 中运行此程序

解决方案

我找到了剪辑的原因 - 并设想了 2 个解决方法.

为什么:

逐步执行渲染代码,剪辑矩形被限制为 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);...}

//这个限制来自 qgrayraster.c.任何更高和//形状的光栅化会产生不正确的结果.const int QT_RASTER_COORD_LIMIT = 32767;

选项:

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

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

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

解决方案

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)

这篇关于在 QImage 上渲染大型 QGraphicsScene 会将其剪掉的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆