绘制一个太大的图像以适应QImage

时间:2014-01-30 16:33:10

标签: python c++ qt

我需要显示一个非常大的图表,例如图像分辨率可能是100 000 x 1000.但是,似乎我被QImage限制为32768 x 32768。

我不能在每个paintEvent处直接重绘图表,所以我需要将它存储到QImage中(它可能是一个不会改变任何东西的QPixmap)。但是,它不合适。

我的第一个想法是:

  • 创建QImage
  • 列表
  • 绘制各种QImage
  • 使用好QImage s重绘

第一点和最后一点很容易完成。但第二点更复杂。我非常有信心我的方法可行,但它需要重载基本的绘画方法(绘制矩形,圆形等),以便能够在多个图像上绘画。

所以,在继续之前,我想知道其他选项可能是什么。

3 个答案:

答案 0 :(得分:2)

您可能不希望一次显示多个QImage数据。很少有屏幕宽度超过32k像素。

所以你想要一个抽象类型生成 QImage s请求读取,偏移和可能不同的缩放因子。

下一个问题是修改这种抽象类型。一个易于使用,而不是最大性能的版本包括让用户将QImage blit到您的内部存储(无论是什么)。

用户仍然需要“平铺”他们的努力,但可以以方便他们的方式平铺他们的努力。

更高性能的版本暴露了一些我们尚未提及的底层实现。

大图像的传统实现是平铺图像。你有一个相互邻接的图像拼贴网格。当有人要求您提供图片中的blit时,您会生成一个临时的QImage,然后将相应的图块放在上面。如果有人对你很感兴趣,你会弄清楚合适的瓷砖是什么,并在其中部分内容上写下QImage部分。

性能更高的界面会公开这些图块。

低级别界面让外界知道你的牌位置,并让他们要求他们。这是一个糟糕的界面。

更好的接口公开子tile迭代器。他们要求一个区域,然后返回一对描述该区域的迭代器。迭代器中的数据由该图块中的图块和区域以及该区域在“完整图像”中的位置,或子图块对象(具有线条,线长等)和位置组成。子瓦片对象。

另一个好的界面是foreach样式界面。同样,大图像类的用户传入他们想要使用的区域,但也是回调。该回调类似于迭代器解除引用的上述任一结果。

与迭代器方法相比,这种方法有两大优势。首先,您可以在大型图像类中实现并行图像处理算法。其次,编写比滚动自己的迭代器要容易得多。

一旦你拥有其中任何一个,绘图相对容易。确定您正在绘制的区域(慷慨)。迭代生成的图块。在每个图块上,在将图块的偏移应用于图形后进行绘制。

答案 1 :(得分:1)

您可以使用Qt Graphics View Framework。为它创建QGraphicsViewQGraphicsScene。使用QGraphicsScene::addPixmap添加项目(返回QGraphicsPixmapItem派生的QGraphicsItem)并使用QGraphicsItem::setPos调整其位置。如果需要,QGraphicsView将有效地绘制场景并处理滚动和缩放。

答案 2 :(得分:0)

您是否意识到100,000 x 1000 RGBA QImage是400MBytes?浪费所有记忆是没有意义的。真的,没有。

每次只需在paintEvent中绘制一个请求。要聪明一点,这样你才能画出需要展示的东西。我认为应该专注于优化绘画过程和数据结构,以便有效地绘画。

在小尺度(缩小)时,通过近似/抽取/插值数据可以获得很多,使其看起来相同,但是你不会浪费时间多次绘制相同的像素。