我对 C++/Qt 相当陌生,我正在尝试使用 Visual Studio C++ 和 Qt (4.8.3) 创建一个应用程序。该应用程序使用 QGraphicsView 显示图像,我需要在像素级别更改图像。
基本代码是(简化):
QImage* img = new QImage(img_width,img_height,QImage::Format_RGB32);
while(do_some_stuff) {
img->setPixel(x,y,color);
}
QGraphicsPixmapItem* pm = new QGraphicsPixmapItem(QPixmap::fromImage(*img));
QGraphicsScene* sc = new QGraphicsScene;
sc->setSceneRect(0,0,img->width(),img->height());
sc->addItem(pm);
ui.graphicsView->setScene(sc);
这对于高达 12000x6000 像素左右的图像效果很好。超出这个尺寸就会发生奇怪的事情。例如,当我设置
img_width=16000
和 img_height=8000
时,img = new QImage(...)
行返回空图像。图像数据应约为 512,000,000 字节,因此即使在 32 位系统上也不应太大。另外,我的机器(Win 7 64位,8 GB RAM)应该能够保存数据。
我也尝试过这个版本:
uchar* imgbuf = (uchar*) malloc(img_width*img_height*4);
QImage* img = new QImage(imgbuf,img_width,img_height,QImage::Format_RGB32);
一开始,这很有效。 img 指针有效,并且调用
img->width()
例如会返回正确的图像宽度(而不是 0,以防图像指针为空)。
但是当我调用 img->setPixel()
时,指针就变成空并且 img->width()
返回 0。
那么我做错了什么?或者有没有更好的方法在像素级别上修改大图像?
问候, 大卫
QImage 支持最大 32768x32768 像素的图像(短符号)。这是根据以下条件得出的:宽度 * 高度 * 颜色深度 < INT_MAX (4 billion) -> 32768 * 32768 * 4 = 40 亿。第二个条件当然是malloc能够分配所请求的内存。
如果您确实需要更大的图像,则必须使用另一个包装器或分成多个 QImage。
我找到了问题所在。我只是忘记将
/LARGEADDRESSAWARE
标志添加到链接器选项中。
我也非常感谢 Stephen Chu 使用 scanLine() 提示的回答。首先,它节省了一些内存,其次,它确实快了很多。
现在我可以安全地创建高达 32000x16000 像素的图像,这是我想要的目标。
您的第二种方法是正确的方法。您遇到的问题是,当您调用
setPixel()
时,QImage
会复制您提供的外部缓冲区并耗尽内存。
scanLine()
来获取指向行缓冲区的指针。无论如何我不会使用setPixel()
,因为它真的很慢。
从 Qt 6 开始,您只需调用:
QImageReader::setAllocationLimit(4096);
在此处查看相关文档。在上面的示例中,我将限制设置为 4GB。可以通过设置环境变量来覆盖该值
QT_IMAGEIO_MAXALLOC
。